target-arm: fix neon vmon/vmvn with modified immediate
[qemu/kraxel.git] / target-arm / translate.c
blob5c54919c38375875f5daf192cd4e0908a49f23ed
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 } DisasContext;
64 #if defined(CONFIG_USER_ONLY)
65 #define IS_USER(s) 1
66 #else
67 #define IS_USER(s) (s->user)
68 #endif
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72 #define DISAS_WFI 4
73 #define DISAS_SWI 5
75 static TCGv_ptr cpu_env;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
78 static TCGv_i32 cpu_R[16];
79 static TCGv_i32 cpu_exclusive_addr;
80 static TCGv_i32 cpu_exclusive_val;
81 static TCGv_i32 cpu_exclusive_high;
82 #ifdef CONFIG_USER_ONLY
83 static TCGv_i32 cpu_exclusive_test;
84 static TCGv_i32 cpu_exclusive_info;
85 #endif
87 /* FIXME: These should be removed. */
88 static TCGv cpu_F0s, cpu_F1s;
89 static TCGv_i64 cpu_F0d, cpu_F1d;
91 #include "gen-icount.h"
93 static const char *regnames[] =
94 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
95 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
97 /* initialize TCG globals. */
98 void arm_translate_init(void)
100 int i;
102 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
104 for (i = 0; i < 16; i++) {
105 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
106 offsetof(CPUState, regs[i]),
107 regnames[i]);
109 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
110 offsetof(CPUState, exclusive_addr), "exclusive_addr");
111 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
112 offsetof(CPUState, exclusive_val), "exclusive_val");
113 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUState, exclusive_high), "exclusive_high");
115 #ifdef CONFIG_USER_ONLY
116 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
117 offsetof(CPUState, exclusive_test), "exclusive_test");
118 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
119 offsetof(CPUState, exclusive_info), "exclusive_info");
120 #endif
122 #define GEN_HELPER 2
123 #include "helpers.h"
126 static int num_temps;
128 /* Allocate a temporary variable. */
129 static TCGv_i32 new_tmp(void)
131 num_temps++;
132 return tcg_temp_new_i32();
135 /* Release a temporary variable. */
136 static void dead_tmp(TCGv tmp)
138 tcg_temp_free(tmp);
139 num_temps--;
142 static inline TCGv load_cpu_offset(int offset)
144 TCGv tmp = new_tmp();
145 tcg_gen_ld_i32(tmp, cpu_env, offset);
146 return tmp;
149 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
151 static inline void store_cpu_offset(TCGv var, int offset)
153 tcg_gen_st_i32(var, cpu_env, offset);
154 dead_tmp(var);
157 #define store_cpu_field(var, name) \
158 store_cpu_offset(var, offsetof(CPUState, name))
160 /* Set a variable to the value of a CPU register. */
161 static void load_reg_var(DisasContext *s, TCGv var, int reg)
163 if (reg == 15) {
164 uint32_t addr;
165 /* normaly, since we updated PC, we need only to add one insn */
166 if (s->thumb)
167 addr = (long)s->pc + 2;
168 else
169 addr = (long)s->pc + 4;
170 tcg_gen_movi_i32(var, addr);
171 } else {
172 tcg_gen_mov_i32(var, cpu_R[reg]);
176 /* Create a new temporary and set it to the value of a CPU register. */
177 static inline TCGv load_reg(DisasContext *s, int reg)
179 TCGv tmp = new_tmp();
180 load_reg_var(s, tmp, reg);
181 return tmp;
184 /* Set a CPU register. The source must be a temporary and will be
185 marked as dead. */
186 static void store_reg(DisasContext *s, int reg, TCGv var)
188 if (reg == 15) {
189 tcg_gen_andi_i32(var, var, ~1);
190 s->is_jmp = DISAS_JUMP;
192 tcg_gen_mov_i32(cpu_R[reg], var);
193 dead_tmp(var);
196 /* Value extensions. */
197 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
198 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
199 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
200 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
202 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
203 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
206 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
208 TCGv tmp_mask = tcg_const_i32(mask);
209 gen_helper_cpsr_write(var, tmp_mask);
210 tcg_temp_free_i32(tmp_mask);
212 /* Set NZCV flags from the high 4 bits of var. */
213 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
215 static void gen_exception(int excp)
217 TCGv tmp = new_tmp();
218 tcg_gen_movi_i32(tmp, excp);
219 gen_helper_exception(tmp);
220 dead_tmp(tmp);
223 static void gen_smul_dual(TCGv a, TCGv b)
225 TCGv tmp1 = new_tmp();
226 TCGv tmp2 = new_tmp();
227 tcg_gen_ext16s_i32(tmp1, a);
228 tcg_gen_ext16s_i32(tmp2, b);
229 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
230 dead_tmp(tmp2);
231 tcg_gen_sari_i32(a, a, 16);
232 tcg_gen_sari_i32(b, b, 16);
233 tcg_gen_mul_i32(b, b, a);
234 tcg_gen_mov_i32(a, tmp1);
235 dead_tmp(tmp1);
238 /* Byteswap each halfword. */
239 static void gen_rev16(TCGv var)
241 TCGv tmp = new_tmp();
242 tcg_gen_shri_i32(tmp, var, 8);
243 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
244 tcg_gen_shli_i32(var, var, 8);
245 tcg_gen_andi_i32(var, var, 0xff00ff00);
246 tcg_gen_or_i32(var, var, tmp);
247 dead_tmp(tmp);
250 /* Byteswap low halfword and sign extend. */
251 static void gen_revsh(TCGv var)
253 TCGv tmp = new_tmp();
254 tcg_gen_shri_i32(tmp, var, 8);
255 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
256 tcg_gen_shli_i32(var, var, 8);
257 tcg_gen_ext8s_i32(var, var);
258 tcg_gen_or_i32(var, var, tmp);
259 dead_tmp(tmp);
262 /* Unsigned bitfield extract. */
263 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
265 if (shift)
266 tcg_gen_shri_i32(var, var, shift);
267 tcg_gen_andi_i32(var, var, mask);
270 /* Signed bitfield extract. */
271 static void gen_sbfx(TCGv var, int shift, int width)
273 uint32_t signbit;
275 if (shift)
276 tcg_gen_sari_i32(var, var, shift);
277 if (shift + width < 32) {
278 signbit = 1u << (width - 1);
279 tcg_gen_andi_i32(var, var, (1u << width) - 1);
280 tcg_gen_xori_i32(var, var, signbit);
281 tcg_gen_subi_i32(var, var, signbit);
285 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
286 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
288 tcg_gen_andi_i32(val, val, mask);
289 tcg_gen_shli_i32(val, val, shift);
290 tcg_gen_andi_i32(base, base, ~(mask << shift));
291 tcg_gen_or_i32(dest, base, val);
294 /* Round the top 32 bits of a 64-bit value. */
295 static void gen_roundqd(TCGv a, TCGv b)
297 tcg_gen_shri_i32(a, a, 31);
298 tcg_gen_add_i32(a, a, b);
301 /* FIXME: Most targets have native widening multiplication.
302 It would be good to use that instead of a full wide multiply. */
303 /* 32x32->64 multiply. Marks inputs as dead. */
304 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
306 TCGv_i64 tmp1 = tcg_temp_new_i64();
307 TCGv_i64 tmp2 = tcg_temp_new_i64();
309 tcg_gen_extu_i32_i64(tmp1, a);
310 dead_tmp(a);
311 tcg_gen_extu_i32_i64(tmp2, b);
312 dead_tmp(b);
313 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
314 tcg_temp_free_i64(tmp2);
315 return tmp1;
318 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
320 TCGv_i64 tmp1 = tcg_temp_new_i64();
321 TCGv_i64 tmp2 = tcg_temp_new_i64();
323 tcg_gen_ext_i32_i64(tmp1, a);
324 dead_tmp(a);
325 tcg_gen_ext_i32_i64(tmp2, b);
326 dead_tmp(b);
327 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
328 tcg_temp_free_i64(tmp2);
329 return tmp1;
332 /* Signed 32x32->64 multiply. */
333 static void gen_imull(TCGv a, TCGv b)
335 TCGv_i64 tmp1 = tcg_temp_new_i64();
336 TCGv_i64 tmp2 = tcg_temp_new_i64();
338 tcg_gen_ext_i32_i64(tmp1, a);
339 tcg_gen_ext_i32_i64(tmp2, b);
340 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
341 tcg_temp_free_i64(tmp2);
342 tcg_gen_trunc_i64_i32(a, tmp1);
343 tcg_gen_shri_i64(tmp1, tmp1, 32);
344 tcg_gen_trunc_i64_i32(b, tmp1);
345 tcg_temp_free_i64(tmp1);
348 /* Swap low and high halfwords. */
349 static void gen_swap_half(TCGv var)
351 TCGv tmp = new_tmp();
352 tcg_gen_shri_i32(tmp, var, 16);
353 tcg_gen_shli_i32(var, var, 16);
354 tcg_gen_or_i32(var, var, tmp);
355 dead_tmp(tmp);
358 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
359 tmp = (t0 ^ t1) & 0x8000;
360 t0 &= ~0x8000;
361 t1 &= ~0x8000;
362 t0 = (t0 + t1) ^ tmp;
365 static void gen_add16(TCGv t0, TCGv t1)
367 TCGv tmp = new_tmp();
368 tcg_gen_xor_i32(tmp, t0, t1);
369 tcg_gen_andi_i32(tmp, tmp, 0x8000);
370 tcg_gen_andi_i32(t0, t0, ~0x8000);
371 tcg_gen_andi_i32(t1, t1, ~0x8000);
372 tcg_gen_add_i32(t0, t0, t1);
373 tcg_gen_xor_i32(t0, t0, tmp);
374 dead_tmp(tmp);
375 dead_tmp(t1);
378 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
380 /* Set CF to the top bit of var. */
381 static void gen_set_CF_bit31(TCGv var)
383 TCGv tmp = new_tmp();
384 tcg_gen_shri_i32(tmp, var, 31);
385 gen_set_CF(tmp);
386 dead_tmp(tmp);
389 /* Set N and Z flags from var. */
390 static inline void gen_logic_CC(TCGv var)
392 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
393 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
396 /* T0 += T1 + CF. */
397 static void gen_adc(TCGv t0, TCGv t1)
399 TCGv tmp;
400 tcg_gen_add_i32(t0, t0, t1);
401 tmp = load_cpu_field(CF);
402 tcg_gen_add_i32(t0, t0, tmp);
403 dead_tmp(tmp);
406 /* dest = T0 + T1 + CF. */
407 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
409 TCGv tmp;
410 tcg_gen_add_i32(dest, t0, t1);
411 tmp = load_cpu_field(CF);
412 tcg_gen_add_i32(dest, dest, tmp);
413 dead_tmp(tmp);
416 /* dest = T0 - T1 + CF - 1. */
417 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
419 TCGv tmp;
420 tcg_gen_sub_i32(dest, t0, t1);
421 tmp = load_cpu_field(CF);
422 tcg_gen_add_i32(dest, dest, tmp);
423 tcg_gen_subi_i32(dest, dest, 1);
424 dead_tmp(tmp);
427 /* FIXME: Implement this natively. */
428 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
430 static void shifter_out_im(TCGv var, int shift)
432 TCGv tmp = new_tmp();
433 if (shift == 0) {
434 tcg_gen_andi_i32(tmp, var, 1);
435 } else {
436 tcg_gen_shri_i32(tmp, var, shift);
437 if (shift != 31)
438 tcg_gen_andi_i32(tmp, tmp, 1);
440 gen_set_CF(tmp);
441 dead_tmp(tmp);
444 /* Shift by immediate. Includes special handling for shift == 0. */
445 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
447 switch (shiftop) {
448 case 0: /* LSL */
449 if (shift != 0) {
450 if (flags)
451 shifter_out_im(var, 32 - shift);
452 tcg_gen_shli_i32(var, var, shift);
454 break;
455 case 1: /* LSR */
456 if (shift == 0) {
457 if (flags) {
458 tcg_gen_shri_i32(var, var, 31);
459 gen_set_CF(var);
461 tcg_gen_movi_i32(var, 0);
462 } else {
463 if (flags)
464 shifter_out_im(var, shift - 1);
465 tcg_gen_shri_i32(var, var, shift);
467 break;
468 case 2: /* ASR */
469 if (shift == 0)
470 shift = 32;
471 if (flags)
472 shifter_out_im(var, shift - 1);
473 if (shift == 32)
474 shift = 31;
475 tcg_gen_sari_i32(var, var, shift);
476 break;
477 case 3: /* ROR/RRX */
478 if (shift != 0) {
479 if (flags)
480 shifter_out_im(var, shift - 1);
481 tcg_gen_rotri_i32(var, var, shift); break;
482 } else {
483 TCGv tmp = load_cpu_field(CF);
484 if (flags)
485 shifter_out_im(var, 0);
486 tcg_gen_shri_i32(var, var, 1);
487 tcg_gen_shli_i32(tmp, tmp, 31);
488 tcg_gen_or_i32(var, var, tmp);
489 dead_tmp(tmp);
494 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
495 TCGv shift, int flags)
497 if (flags) {
498 switch (shiftop) {
499 case 0: gen_helper_shl_cc(var, var, shift); break;
500 case 1: gen_helper_shr_cc(var, var, shift); break;
501 case 2: gen_helper_sar_cc(var, var, shift); break;
502 case 3: gen_helper_ror_cc(var, var, shift); break;
504 } else {
505 switch (shiftop) {
506 case 0: gen_helper_shl(var, var, shift); break;
507 case 1: gen_helper_shr(var, var, shift); break;
508 case 2: gen_helper_sar(var, var, shift); break;
509 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
510 tcg_gen_rotr_i32(var, var, shift); break;
513 dead_tmp(shift);
516 #define PAS_OP(pfx) \
517 switch (op2) { \
518 case 0: gen_pas_helper(glue(pfx,add16)); break; \
519 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
520 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
521 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
522 case 4: gen_pas_helper(glue(pfx,add8)); break; \
523 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
525 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
527 TCGv_ptr tmp;
529 switch (op1) {
530 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
531 case 1:
532 tmp = tcg_temp_new_ptr();
533 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
534 PAS_OP(s)
535 tcg_temp_free_ptr(tmp);
536 break;
537 case 5:
538 tmp = tcg_temp_new_ptr();
539 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
540 PAS_OP(u)
541 tcg_temp_free_ptr(tmp);
542 break;
543 #undef gen_pas_helper
544 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
545 case 2:
546 PAS_OP(q);
547 break;
548 case 3:
549 PAS_OP(sh);
550 break;
551 case 6:
552 PAS_OP(uq);
553 break;
554 case 7:
555 PAS_OP(uh);
556 break;
557 #undef gen_pas_helper
560 #undef PAS_OP
562 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
563 #define PAS_OP(pfx) \
564 switch (op2) { \
565 case 0: gen_pas_helper(glue(pfx,add8)); break; \
566 case 1: gen_pas_helper(glue(pfx,add16)); break; \
567 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
568 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
569 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
570 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
572 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
574 TCGv_ptr tmp;
576 switch (op1) {
577 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
578 case 0:
579 tmp = tcg_temp_new_ptr();
580 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
581 PAS_OP(s)
582 tcg_temp_free_ptr(tmp);
583 break;
584 case 4:
585 tmp = tcg_temp_new_ptr();
586 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
587 PAS_OP(u)
588 tcg_temp_free_ptr(tmp);
589 break;
590 #undef gen_pas_helper
591 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
592 case 1:
593 PAS_OP(q);
594 break;
595 case 2:
596 PAS_OP(sh);
597 break;
598 case 5:
599 PAS_OP(uq);
600 break;
601 case 6:
602 PAS_OP(uh);
603 break;
604 #undef gen_pas_helper
607 #undef PAS_OP
609 static void gen_test_cc(int cc, int label)
611 TCGv tmp;
612 TCGv tmp2;
613 int inv;
615 switch (cc) {
616 case 0: /* eq: Z */
617 tmp = load_cpu_field(ZF);
618 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
619 break;
620 case 1: /* ne: !Z */
621 tmp = load_cpu_field(ZF);
622 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
623 break;
624 case 2: /* cs: C */
625 tmp = load_cpu_field(CF);
626 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
627 break;
628 case 3: /* cc: !C */
629 tmp = load_cpu_field(CF);
630 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
631 break;
632 case 4: /* mi: N */
633 tmp = load_cpu_field(NF);
634 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
635 break;
636 case 5: /* pl: !N */
637 tmp = load_cpu_field(NF);
638 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
639 break;
640 case 6: /* vs: V */
641 tmp = load_cpu_field(VF);
642 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
643 break;
644 case 7: /* vc: !V */
645 tmp = load_cpu_field(VF);
646 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
647 break;
648 case 8: /* hi: C && !Z */
649 inv = gen_new_label();
650 tmp = load_cpu_field(CF);
651 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
652 dead_tmp(tmp);
653 tmp = load_cpu_field(ZF);
654 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
655 gen_set_label(inv);
656 break;
657 case 9: /* ls: !C || Z */
658 tmp = load_cpu_field(CF);
659 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
660 dead_tmp(tmp);
661 tmp = load_cpu_field(ZF);
662 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
663 break;
664 case 10: /* ge: 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 dead_tmp(tmp2);
669 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
670 break;
671 case 11: /* lt: N != V -> N ^ V != 0 */
672 tmp = load_cpu_field(VF);
673 tmp2 = load_cpu_field(NF);
674 tcg_gen_xor_i32(tmp, tmp, tmp2);
675 dead_tmp(tmp2);
676 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
677 break;
678 case 12: /* gt: !Z && N == V */
679 inv = gen_new_label();
680 tmp = load_cpu_field(ZF);
681 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
682 dead_tmp(tmp);
683 tmp = load_cpu_field(VF);
684 tmp2 = load_cpu_field(NF);
685 tcg_gen_xor_i32(tmp, tmp, tmp2);
686 dead_tmp(tmp2);
687 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
688 gen_set_label(inv);
689 break;
690 case 13: /* le: Z || N != V */
691 tmp = load_cpu_field(ZF);
692 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
693 dead_tmp(tmp);
694 tmp = load_cpu_field(VF);
695 tmp2 = load_cpu_field(NF);
696 tcg_gen_xor_i32(tmp, tmp, tmp2);
697 dead_tmp(tmp2);
698 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
699 break;
700 default:
701 fprintf(stderr, "Bad condition code 0x%x\n", cc);
702 abort();
704 dead_tmp(tmp);
707 static const uint8_t table_logic_cc[16] = {
708 1, /* and */
709 1, /* xor */
710 0, /* sub */
711 0, /* rsb */
712 0, /* add */
713 0, /* adc */
714 0, /* sbc */
715 0, /* rsc */
716 1, /* andl */
717 1, /* xorl */
718 0, /* cmp */
719 0, /* cmn */
720 1, /* orr */
721 1, /* mov */
722 1, /* bic */
723 1, /* mvn */
726 /* Set PC and Thumb state from an immediate address. */
727 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
729 TCGv tmp;
731 s->is_jmp = DISAS_UPDATE;
732 if (s->thumb != (addr & 1)) {
733 tmp = new_tmp();
734 tcg_gen_movi_i32(tmp, addr & 1);
735 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
736 dead_tmp(tmp);
738 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
741 /* Set PC and Thumb state from var. var is marked as dead. */
742 static inline void gen_bx(DisasContext *s, TCGv var)
744 s->is_jmp = DISAS_UPDATE;
745 tcg_gen_andi_i32(cpu_R[15], var, ~1);
746 tcg_gen_andi_i32(var, var, 1);
747 store_cpu_field(var, thumb);
750 /* Variant of store_reg which uses branch&exchange logic when storing
751 to r15 in ARM architecture v7 and above. The source must be a temporary
752 and will be marked as dead. */
753 static inline void store_reg_bx(CPUState *env, DisasContext *s,
754 int reg, TCGv var)
756 if (reg == 15 && ENABLE_ARCH_7) {
757 gen_bx(s, var);
758 } else {
759 store_reg(s, reg, var);
763 static inline TCGv gen_ld8s(TCGv addr, int index)
765 TCGv tmp = new_tmp();
766 tcg_gen_qemu_ld8s(tmp, addr, index);
767 return tmp;
769 static inline TCGv gen_ld8u(TCGv addr, int index)
771 TCGv tmp = new_tmp();
772 tcg_gen_qemu_ld8u(tmp, addr, index);
773 return tmp;
775 static inline TCGv gen_ld16s(TCGv addr, int index)
777 TCGv tmp = new_tmp();
778 tcg_gen_qemu_ld16s(tmp, addr, index);
779 return tmp;
781 static inline TCGv gen_ld16u(TCGv addr, int index)
783 TCGv tmp = new_tmp();
784 tcg_gen_qemu_ld16u(tmp, addr, index);
785 return tmp;
787 static inline TCGv gen_ld32(TCGv addr, int index)
789 TCGv tmp = new_tmp();
790 tcg_gen_qemu_ld32u(tmp, addr, index);
791 return tmp;
793 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
795 TCGv_i64 tmp = tcg_temp_new_i64();
796 tcg_gen_qemu_ld64(tmp, addr, index);
797 return tmp;
799 static inline void gen_st8(TCGv val, TCGv addr, int index)
801 tcg_gen_qemu_st8(val, addr, index);
802 dead_tmp(val);
804 static inline void gen_st16(TCGv val, TCGv addr, int index)
806 tcg_gen_qemu_st16(val, addr, index);
807 dead_tmp(val);
809 static inline void gen_st32(TCGv val, TCGv addr, int index)
811 tcg_gen_qemu_st32(val, addr, index);
812 dead_tmp(val);
814 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
816 tcg_gen_qemu_st64(val, addr, index);
817 tcg_temp_free_i64(val);
820 static inline void gen_set_pc_im(uint32_t val)
822 tcg_gen_movi_i32(cpu_R[15], val);
825 /* Force a TB lookup after an instruction that changes the CPU state. */
826 static inline void gen_lookup_tb(DisasContext *s)
828 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
829 s->is_jmp = DISAS_UPDATE;
832 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
833 TCGv var)
835 int val, rm, shift, shiftop;
836 TCGv offset;
838 if (!(insn & (1 << 25))) {
839 /* immediate */
840 val = insn & 0xfff;
841 if (!(insn & (1 << 23)))
842 val = -val;
843 if (val != 0)
844 tcg_gen_addi_i32(var, var, val);
845 } else {
846 /* shift/register */
847 rm = (insn) & 0xf;
848 shift = (insn >> 7) & 0x1f;
849 shiftop = (insn >> 5) & 3;
850 offset = load_reg(s, rm);
851 gen_arm_shift_im(offset, shiftop, shift, 0);
852 if (!(insn & (1 << 23)))
853 tcg_gen_sub_i32(var, var, offset);
854 else
855 tcg_gen_add_i32(var, var, offset);
856 dead_tmp(offset);
860 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
861 int extra, TCGv var)
863 int val, rm;
864 TCGv offset;
866 if (insn & (1 << 22)) {
867 /* immediate */
868 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
869 if (!(insn & (1 << 23)))
870 val = -val;
871 val += extra;
872 if (val != 0)
873 tcg_gen_addi_i32(var, var, val);
874 } else {
875 /* register */
876 if (extra)
877 tcg_gen_addi_i32(var, var, extra);
878 rm = (insn) & 0xf;
879 offset = load_reg(s, rm);
880 if (!(insn & (1 << 23)))
881 tcg_gen_sub_i32(var, var, offset);
882 else
883 tcg_gen_add_i32(var, var, offset);
884 dead_tmp(offset);
888 #define VFP_OP2(name) \
889 static inline void gen_vfp_##name(int dp) \
891 if (dp) \
892 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
893 else \
894 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
897 VFP_OP2(add)
898 VFP_OP2(sub)
899 VFP_OP2(mul)
900 VFP_OP2(div)
902 #undef VFP_OP2
904 static inline void gen_vfp_abs(int dp)
906 if (dp)
907 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
908 else
909 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
912 static inline void gen_vfp_neg(int dp)
914 if (dp)
915 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
916 else
917 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
920 static inline void gen_vfp_sqrt(int dp)
922 if (dp)
923 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
924 else
925 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
928 static inline void gen_vfp_cmp(int dp)
930 if (dp)
931 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
932 else
933 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
936 static inline void gen_vfp_cmpe(int dp)
938 if (dp)
939 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
940 else
941 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
944 static inline void gen_vfp_F1_ld0(int dp)
946 if (dp)
947 tcg_gen_movi_i64(cpu_F1d, 0);
948 else
949 tcg_gen_movi_i32(cpu_F1s, 0);
952 static inline void gen_vfp_uito(int dp)
954 if (dp)
955 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
956 else
957 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
960 static inline void gen_vfp_sito(int dp)
962 if (dp)
963 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
964 else
965 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
968 static inline void gen_vfp_toui(int dp)
970 if (dp)
971 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
972 else
973 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
976 static inline void gen_vfp_touiz(int dp)
978 if (dp)
979 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
980 else
981 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
984 static inline void gen_vfp_tosi(int dp)
986 if (dp)
987 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
988 else
989 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
992 static inline void gen_vfp_tosiz(int dp)
994 if (dp)
995 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
996 else
997 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1000 #define VFP_GEN_FIX(name) \
1001 static inline void gen_vfp_##name(int dp, int shift) \
1003 TCGv tmp_shift = tcg_const_i32(shift); \
1004 if (dp) \
1005 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1006 else \
1007 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1008 tcg_temp_free_i32(tmp_shift); \
1010 VFP_GEN_FIX(tosh)
1011 VFP_GEN_FIX(tosl)
1012 VFP_GEN_FIX(touh)
1013 VFP_GEN_FIX(toul)
1014 VFP_GEN_FIX(shto)
1015 VFP_GEN_FIX(slto)
1016 VFP_GEN_FIX(uhto)
1017 VFP_GEN_FIX(ulto)
1018 #undef VFP_GEN_FIX
1020 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1022 if (dp)
1023 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1024 else
1025 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1028 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1030 if (dp)
1031 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1032 else
1033 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1036 static inline long
1037 vfp_reg_offset (int dp, int reg)
1039 if (dp)
1040 return offsetof(CPUARMState, vfp.regs[reg]);
1041 else if (reg & 1) {
1042 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1043 + offsetof(CPU_DoubleU, l.upper);
1044 } else {
1045 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1046 + offsetof(CPU_DoubleU, l.lower);
1050 /* Return the offset of a 32-bit piece of a NEON register.
1051 zero is the least significant end of the register. */
1052 static inline long
1053 neon_reg_offset (int reg, int n)
1055 int sreg;
1056 sreg = reg * 2 + n;
1057 return vfp_reg_offset(0, sreg);
1060 static TCGv neon_load_reg(int reg, int pass)
1062 TCGv tmp = new_tmp();
1063 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1064 return tmp;
1067 static void neon_store_reg(int reg, int pass, TCGv var)
1069 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1070 dead_tmp(var);
1073 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1075 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1078 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1080 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1083 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1084 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1085 #define tcg_gen_st_f32 tcg_gen_st_i32
1086 #define tcg_gen_st_f64 tcg_gen_st_i64
1088 static inline void gen_mov_F0_vreg(int dp, int reg)
1090 if (dp)
1091 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1092 else
1093 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1096 static inline void gen_mov_F1_vreg(int dp, int reg)
1098 if (dp)
1099 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1100 else
1101 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1104 static inline void gen_mov_vreg_F0(int dp, int reg)
1106 if (dp)
1107 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1108 else
1109 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1112 #define ARM_CP_RW_BIT (1 << 20)
1114 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1116 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1119 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1121 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1124 static inline TCGv iwmmxt_load_creg(int reg)
1126 TCGv var = new_tmp();
1127 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1128 return var;
1131 static inline void iwmmxt_store_creg(int reg, TCGv var)
1133 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1134 dead_tmp(var);
1137 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1139 iwmmxt_store_reg(cpu_M0, rn);
1142 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1144 iwmmxt_load_reg(cpu_M0, rn);
1147 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1149 iwmmxt_load_reg(cpu_V1, rn);
1150 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1153 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1155 iwmmxt_load_reg(cpu_V1, rn);
1156 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1159 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1161 iwmmxt_load_reg(cpu_V1, rn);
1162 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1165 #define IWMMXT_OP(name) \
1166 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1168 iwmmxt_load_reg(cpu_V1, rn); \
1169 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1172 #define IWMMXT_OP_ENV(name) \
1173 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1175 iwmmxt_load_reg(cpu_V1, rn); \
1176 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1179 #define IWMMXT_OP_ENV_SIZE(name) \
1180 IWMMXT_OP_ENV(name##b) \
1181 IWMMXT_OP_ENV(name##w) \
1182 IWMMXT_OP_ENV(name##l)
1184 #define IWMMXT_OP_ENV1(name) \
1185 static inline void gen_op_iwmmxt_##name##_M0(void) \
1187 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1190 IWMMXT_OP(maddsq)
1191 IWMMXT_OP(madduq)
1192 IWMMXT_OP(sadb)
1193 IWMMXT_OP(sadw)
1194 IWMMXT_OP(mulslw)
1195 IWMMXT_OP(mulshw)
1196 IWMMXT_OP(mululw)
1197 IWMMXT_OP(muluhw)
1198 IWMMXT_OP(macsw)
1199 IWMMXT_OP(macuw)
1201 IWMMXT_OP_ENV_SIZE(unpackl)
1202 IWMMXT_OP_ENV_SIZE(unpackh)
1204 IWMMXT_OP_ENV1(unpacklub)
1205 IWMMXT_OP_ENV1(unpackluw)
1206 IWMMXT_OP_ENV1(unpacklul)
1207 IWMMXT_OP_ENV1(unpackhub)
1208 IWMMXT_OP_ENV1(unpackhuw)
1209 IWMMXT_OP_ENV1(unpackhul)
1210 IWMMXT_OP_ENV1(unpacklsb)
1211 IWMMXT_OP_ENV1(unpacklsw)
1212 IWMMXT_OP_ENV1(unpacklsl)
1213 IWMMXT_OP_ENV1(unpackhsb)
1214 IWMMXT_OP_ENV1(unpackhsw)
1215 IWMMXT_OP_ENV1(unpackhsl)
1217 IWMMXT_OP_ENV_SIZE(cmpeq)
1218 IWMMXT_OP_ENV_SIZE(cmpgtu)
1219 IWMMXT_OP_ENV_SIZE(cmpgts)
1221 IWMMXT_OP_ENV_SIZE(mins)
1222 IWMMXT_OP_ENV_SIZE(minu)
1223 IWMMXT_OP_ENV_SIZE(maxs)
1224 IWMMXT_OP_ENV_SIZE(maxu)
1226 IWMMXT_OP_ENV_SIZE(subn)
1227 IWMMXT_OP_ENV_SIZE(addn)
1228 IWMMXT_OP_ENV_SIZE(subu)
1229 IWMMXT_OP_ENV_SIZE(addu)
1230 IWMMXT_OP_ENV_SIZE(subs)
1231 IWMMXT_OP_ENV_SIZE(adds)
1233 IWMMXT_OP_ENV(avgb0)
1234 IWMMXT_OP_ENV(avgb1)
1235 IWMMXT_OP_ENV(avgw0)
1236 IWMMXT_OP_ENV(avgw1)
1238 IWMMXT_OP(msadb)
1240 IWMMXT_OP_ENV(packuw)
1241 IWMMXT_OP_ENV(packul)
1242 IWMMXT_OP_ENV(packuq)
1243 IWMMXT_OP_ENV(packsw)
1244 IWMMXT_OP_ENV(packsl)
1245 IWMMXT_OP_ENV(packsq)
1247 static void gen_op_iwmmxt_set_mup(void)
1249 TCGv tmp;
1250 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1251 tcg_gen_ori_i32(tmp, tmp, 2);
1252 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1255 static void gen_op_iwmmxt_set_cup(void)
1257 TCGv tmp;
1258 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1259 tcg_gen_ori_i32(tmp, tmp, 1);
1260 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1263 static void gen_op_iwmmxt_setpsr_nz(void)
1265 TCGv tmp = new_tmp();
1266 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1267 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1270 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1272 iwmmxt_load_reg(cpu_V1, rn);
1273 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1274 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1277 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1279 int rd;
1280 uint32_t offset;
1281 TCGv tmp;
1283 rd = (insn >> 16) & 0xf;
1284 tmp = load_reg(s, rd);
1286 offset = (insn & 0xff) << ((insn >> 7) & 2);
1287 if (insn & (1 << 24)) {
1288 /* Pre indexed */
1289 if (insn & (1 << 23))
1290 tcg_gen_addi_i32(tmp, tmp, offset);
1291 else
1292 tcg_gen_addi_i32(tmp, tmp, -offset);
1293 tcg_gen_mov_i32(dest, tmp);
1294 if (insn & (1 << 21))
1295 store_reg(s, rd, tmp);
1296 else
1297 dead_tmp(tmp);
1298 } else if (insn & (1 << 21)) {
1299 /* Post indexed */
1300 tcg_gen_mov_i32(dest, tmp);
1301 if (insn & (1 << 23))
1302 tcg_gen_addi_i32(tmp, tmp, offset);
1303 else
1304 tcg_gen_addi_i32(tmp, tmp, -offset);
1305 store_reg(s, rd, tmp);
1306 } else if (!(insn & (1 << 23)))
1307 return 1;
1308 return 0;
1311 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1313 int rd = (insn >> 0) & 0xf;
1314 TCGv tmp;
1316 if (insn & (1 << 8)) {
1317 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1318 return 1;
1319 } else {
1320 tmp = iwmmxt_load_creg(rd);
1322 } else {
1323 tmp = new_tmp();
1324 iwmmxt_load_reg(cpu_V0, rd);
1325 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1327 tcg_gen_andi_i32(tmp, tmp, mask);
1328 tcg_gen_mov_i32(dest, tmp);
1329 dead_tmp(tmp);
1330 return 0;
1333 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1334 (ie. an undefined instruction). */
1335 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1337 int rd, wrd;
1338 int rdhi, rdlo, rd0, rd1, i;
1339 TCGv addr;
1340 TCGv tmp, tmp2, tmp3;
1342 if ((insn & 0x0e000e00) == 0x0c000000) {
1343 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1344 wrd = insn & 0xf;
1345 rdlo = (insn >> 12) & 0xf;
1346 rdhi = (insn >> 16) & 0xf;
1347 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1348 iwmmxt_load_reg(cpu_V0, wrd);
1349 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1350 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1351 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1352 } else { /* TMCRR */
1353 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1354 iwmmxt_store_reg(cpu_V0, wrd);
1355 gen_op_iwmmxt_set_mup();
1357 return 0;
1360 wrd = (insn >> 12) & 0xf;
1361 addr = new_tmp();
1362 if (gen_iwmmxt_address(s, insn, addr)) {
1363 dead_tmp(addr);
1364 return 1;
1366 if (insn & ARM_CP_RW_BIT) {
1367 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1368 tmp = new_tmp();
1369 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1370 iwmmxt_store_creg(wrd, tmp);
1371 } else {
1372 i = 1;
1373 if (insn & (1 << 8)) {
1374 if (insn & (1 << 22)) { /* WLDRD */
1375 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1376 i = 0;
1377 } else { /* WLDRW wRd */
1378 tmp = gen_ld32(addr, IS_USER(s));
1380 } else {
1381 if (insn & (1 << 22)) { /* WLDRH */
1382 tmp = gen_ld16u(addr, IS_USER(s));
1383 } else { /* WLDRB */
1384 tmp = gen_ld8u(addr, IS_USER(s));
1387 if (i) {
1388 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1389 dead_tmp(tmp);
1391 gen_op_iwmmxt_movq_wRn_M0(wrd);
1393 } else {
1394 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1395 tmp = iwmmxt_load_creg(wrd);
1396 gen_st32(tmp, addr, IS_USER(s));
1397 } else {
1398 gen_op_iwmmxt_movq_M0_wRn(wrd);
1399 tmp = new_tmp();
1400 if (insn & (1 << 8)) {
1401 if (insn & (1 << 22)) { /* WSTRD */
1402 dead_tmp(tmp);
1403 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1404 } else { /* WSTRW wRd */
1405 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1406 gen_st32(tmp, addr, IS_USER(s));
1408 } else {
1409 if (insn & (1 << 22)) { /* WSTRH */
1410 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1411 gen_st16(tmp, addr, IS_USER(s));
1412 } else { /* WSTRB */
1413 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1414 gen_st8(tmp, addr, IS_USER(s));
1419 dead_tmp(addr);
1420 return 0;
1423 if ((insn & 0x0f000000) != 0x0e000000)
1424 return 1;
1426 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1427 case 0x000: /* WOR */
1428 wrd = (insn >> 12) & 0xf;
1429 rd0 = (insn >> 0) & 0xf;
1430 rd1 = (insn >> 16) & 0xf;
1431 gen_op_iwmmxt_movq_M0_wRn(rd0);
1432 gen_op_iwmmxt_orq_M0_wRn(rd1);
1433 gen_op_iwmmxt_setpsr_nz();
1434 gen_op_iwmmxt_movq_wRn_M0(wrd);
1435 gen_op_iwmmxt_set_mup();
1436 gen_op_iwmmxt_set_cup();
1437 break;
1438 case 0x011: /* TMCR */
1439 if (insn & 0xf)
1440 return 1;
1441 rd = (insn >> 12) & 0xf;
1442 wrd = (insn >> 16) & 0xf;
1443 switch (wrd) {
1444 case ARM_IWMMXT_wCID:
1445 case ARM_IWMMXT_wCASF:
1446 break;
1447 case ARM_IWMMXT_wCon:
1448 gen_op_iwmmxt_set_cup();
1449 /* Fall through. */
1450 case ARM_IWMMXT_wCSSF:
1451 tmp = iwmmxt_load_creg(wrd);
1452 tmp2 = load_reg(s, rd);
1453 tcg_gen_andc_i32(tmp, tmp, tmp2);
1454 dead_tmp(tmp2);
1455 iwmmxt_store_creg(wrd, tmp);
1456 break;
1457 case ARM_IWMMXT_wCGR0:
1458 case ARM_IWMMXT_wCGR1:
1459 case ARM_IWMMXT_wCGR2:
1460 case ARM_IWMMXT_wCGR3:
1461 gen_op_iwmmxt_set_cup();
1462 tmp = load_reg(s, rd);
1463 iwmmxt_store_creg(wrd, tmp);
1464 break;
1465 default:
1466 return 1;
1468 break;
1469 case 0x100: /* WXOR */
1470 wrd = (insn >> 12) & 0xf;
1471 rd0 = (insn >> 0) & 0xf;
1472 rd1 = (insn >> 16) & 0xf;
1473 gen_op_iwmmxt_movq_M0_wRn(rd0);
1474 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1475 gen_op_iwmmxt_setpsr_nz();
1476 gen_op_iwmmxt_movq_wRn_M0(wrd);
1477 gen_op_iwmmxt_set_mup();
1478 gen_op_iwmmxt_set_cup();
1479 break;
1480 case 0x111: /* TMRC */
1481 if (insn & 0xf)
1482 return 1;
1483 rd = (insn >> 12) & 0xf;
1484 wrd = (insn >> 16) & 0xf;
1485 tmp = iwmmxt_load_creg(wrd);
1486 store_reg(s, rd, tmp);
1487 break;
1488 case 0x300: /* WANDN */
1489 wrd = (insn >> 12) & 0xf;
1490 rd0 = (insn >> 0) & 0xf;
1491 rd1 = (insn >> 16) & 0xf;
1492 gen_op_iwmmxt_movq_M0_wRn(rd0);
1493 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1494 gen_op_iwmmxt_andq_M0_wRn(rd1);
1495 gen_op_iwmmxt_setpsr_nz();
1496 gen_op_iwmmxt_movq_wRn_M0(wrd);
1497 gen_op_iwmmxt_set_mup();
1498 gen_op_iwmmxt_set_cup();
1499 break;
1500 case 0x200: /* WAND */
1501 wrd = (insn >> 12) & 0xf;
1502 rd0 = (insn >> 0) & 0xf;
1503 rd1 = (insn >> 16) & 0xf;
1504 gen_op_iwmmxt_movq_M0_wRn(rd0);
1505 gen_op_iwmmxt_andq_M0_wRn(rd1);
1506 gen_op_iwmmxt_setpsr_nz();
1507 gen_op_iwmmxt_movq_wRn_M0(wrd);
1508 gen_op_iwmmxt_set_mup();
1509 gen_op_iwmmxt_set_cup();
1510 break;
1511 case 0x810: case 0xa10: /* WMADD */
1512 wrd = (insn >> 12) & 0xf;
1513 rd0 = (insn >> 0) & 0xf;
1514 rd1 = (insn >> 16) & 0xf;
1515 gen_op_iwmmxt_movq_M0_wRn(rd0);
1516 if (insn & (1 << 21))
1517 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1518 else
1519 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1520 gen_op_iwmmxt_movq_wRn_M0(wrd);
1521 gen_op_iwmmxt_set_mup();
1522 break;
1523 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1524 wrd = (insn >> 12) & 0xf;
1525 rd0 = (insn >> 16) & 0xf;
1526 rd1 = (insn >> 0) & 0xf;
1527 gen_op_iwmmxt_movq_M0_wRn(rd0);
1528 switch ((insn >> 22) & 3) {
1529 case 0:
1530 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1531 break;
1532 case 1:
1533 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1534 break;
1535 case 2:
1536 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1537 break;
1538 case 3:
1539 return 1;
1541 gen_op_iwmmxt_movq_wRn_M0(wrd);
1542 gen_op_iwmmxt_set_mup();
1543 gen_op_iwmmxt_set_cup();
1544 break;
1545 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1546 wrd = (insn >> 12) & 0xf;
1547 rd0 = (insn >> 16) & 0xf;
1548 rd1 = (insn >> 0) & 0xf;
1549 gen_op_iwmmxt_movq_M0_wRn(rd0);
1550 switch ((insn >> 22) & 3) {
1551 case 0:
1552 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1553 break;
1554 case 1:
1555 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1556 break;
1557 case 2:
1558 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1559 break;
1560 case 3:
1561 return 1;
1563 gen_op_iwmmxt_movq_wRn_M0(wrd);
1564 gen_op_iwmmxt_set_mup();
1565 gen_op_iwmmxt_set_cup();
1566 break;
1567 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1568 wrd = (insn >> 12) & 0xf;
1569 rd0 = (insn >> 16) & 0xf;
1570 rd1 = (insn >> 0) & 0xf;
1571 gen_op_iwmmxt_movq_M0_wRn(rd0);
1572 if (insn & (1 << 22))
1573 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1574 else
1575 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1576 if (!(insn & (1 << 20)))
1577 gen_op_iwmmxt_addl_M0_wRn(wrd);
1578 gen_op_iwmmxt_movq_wRn_M0(wrd);
1579 gen_op_iwmmxt_set_mup();
1580 break;
1581 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1582 wrd = (insn >> 12) & 0xf;
1583 rd0 = (insn >> 16) & 0xf;
1584 rd1 = (insn >> 0) & 0xf;
1585 gen_op_iwmmxt_movq_M0_wRn(rd0);
1586 if (insn & (1 << 21)) {
1587 if (insn & (1 << 20))
1588 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1589 else
1590 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1591 } else {
1592 if (insn & (1 << 20))
1593 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1594 else
1595 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1597 gen_op_iwmmxt_movq_wRn_M0(wrd);
1598 gen_op_iwmmxt_set_mup();
1599 break;
1600 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1601 wrd = (insn >> 12) & 0xf;
1602 rd0 = (insn >> 16) & 0xf;
1603 rd1 = (insn >> 0) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0);
1605 if (insn & (1 << 21))
1606 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1607 else
1608 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1609 if (!(insn & (1 << 20))) {
1610 iwmmxt_load_reg(cpu_V1, wrd);
1611 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1613 gen_op_iwmmxt_movq_wRn_M0(wrd);
1614 gen_op_iwmmxt_set_mup();
1615 break;
1616 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1617 wrd = (insn >> 12) & 0xf;
1618 rd0 = (insn >> 16) & 0xf;
1619 rd1 = (insn >> 0) & 0xf;
1620 gen_op_iwmmxt_movq_M0_wRn(rd0);
1621 switch ((insn >> 22) & 3) {
1622 case 0:
1623 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1624 break;
1625 case 1:
1626 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1627 break;
1628 case 2:
1629 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1630 break;
1631 case 3:
1632 return 1;
1634 gen_op_iwmmxt_movq_wRn_M0(wrd);
1635 gen_op_iwmmxt_set_mup();
1636 gen_op_iwmmxt_set_cup();
1637 break;
1638 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1639 wrd = (insn >> 12) & 0xf;
1640 rd0 = (insn >> 16) & 0xf;
1641 rd1 = (insn >> 0) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0);
1643 if (insn & (1 << 22)) {
1644 if (insn & (1 << 20))
1645 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1646 else
1647 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1648 } else {
1649 if (insn & (1 << 20))
1650 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1651 else
1652 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1654 gen_op_iwmmxt_movq_wRn_M0(wrd);
1655 gen_op_iwmmxt_set_mup();
1656 gen_op_iwmmxt_set_cup();
1657 break;
1658 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1659 wrd = (insn >> 12) & 0xf;
1660 rd0 = (insn >> 16) & 0xf;
1661 rd1 = (insn >> 0) & 0xf;
1662 gen_op_iwmmxt_movq_M0_wRn(rd0);
1663 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1664 tcg_gen_andi_i32(tmp, tmp, 7);
1665 iwmmxt_load_reg(cpu_V1, rd1);
1666 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1667 dead_tmp(tmp);
1668 gen_op_iwmmxt_movq_wRn_M0(wrd);
1669 gen_op_iwmmxt_set_mup();
1670 break;
1671 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1672 if (((insn >> 6) & 3) == 3)
1673 return 1;
1674 rd = (insn >> 12) & 0xf;
1675 wrd = (insn >> 16) & 0xf;
1676 tmp = load_reg(s, rd);
1677 gen_op_iwmmxt_movq_M0_wRn(wrd);
1678 switch ((insn >> 6) & 3) {
1679 case 0:
1680 tmp2 = tcg_const_i32(0xff);
1681 tmp3 = tcg_const_i32((insn & 7) << 3);
1682 break;
1683 case 1:
1684 tmp2 = tcg_const_i32(0xffff);
1685 tmp3 = tcg_const_i32((insn & 3) << 4);
1686 break;
1687 case 2:
1688 tmp2 = tcg_const_i32(0xffffffff);
1689 tmp3 = tcg_const_i32((insn & 1) << 5);
1690 break;
1691 default:
1692 TCGV_UNUSED(tmp2);
1693 TCGV_UNUSED(tmp3);
1695 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1696 tcg_temp_free(tmp3);
1697 tcg_temp_free(tmp2);
1698 dead_tmp(tmp);
1699 gen_op_iwmmxt_movq_wRn_M0(wrd);
1700 gen_op_iwmmxt_set_mup();
1701 break;
1702 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1703 rd = (insn >> 12) & 0xf;
1704 wrd = (insn >> 16) & 0xf;
1705 if (rd == 15 || ((insn >> 22) & 3) == 3)
1706 return 1;
1707 gen_op_iwmmxt_movq_M0_wRn(wrd);
1708 tmp = new_tmp();
1709 switch ((insn >> 22) & 3) {
1710 case 0:
1711 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1712 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1713 if (insn & 8) {
1714 tcg_gen_ext8s_i32(tmp, tmp);
1715 } else {
1716 tcg_gen_andi_i32(tmp, tmp, 0xff);
1718 break;
1719 case 1:
1720 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1721 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1722 if (insn & 8) {
1723 tcg_gen_ext16s_i32(tmp, tmp);
1724 } else {
1725 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1727 break;
1728 case 2:
1729 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1730 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1731 break;
1733 store_reg(s, rd, tmp);
1734 break;
1735 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1736 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1737 return 1;
1738 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1739 switch ((insn >> 22) & 3) {
1740 case 0:
1741 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1742 break;
1743 case 1:
1744 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1745 break;
1746 case 2:
1747 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1748 break;
1750 tcg_gen_shli_i32(tmp, tmp, 28);
1751 gen_set_nzcv(tmp);
1752 dead_tmp(tmp);
1753 break;
1754 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1755 if (((insn >> 6) & 3) == 3)
1756 return 1;
1757 rd = (insn >> 12) & 0xf;
1758 wrd = (insn >> 16) & 0xf;
1759 tmp = load_reg(s, rd);
1760 switch ((insn >> 6) & 3) {
1761 case 0:
1762 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1763 break;
1764 case 1:
1765 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1766 break;
1767 case 2:
1768 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1769 break;
1771 dead_tmp(tmp);
1772 gen_op_iwmmxt_movq_wRn_M0(wrd);
1773 gen_op_iwmmxt_set_mup();
1774 break;
1775 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1776 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1777 return 1;
1778 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1779 tmp2 = new_tmp();
1780 tcg_gen_mov_i32(tmp2, tmp);
1781 switch ((insn >> 22) & 3) {
1782 case 0:
1783 for (i = 0; i < 7; i ++) {
1784 tcg_gen_shli_i32(tmp2, tmp2, 4);
1785 tcg_gen_and_i32(tmp, tmp, tmp2);
1787 break;
1788 case 1:
1789 for (i = 0; i < 3; i ++) {
1790 tcg_gen_shli_i32(tmp2, tmp2, 8);
1791 tcg_gen_and_i32(tmp, tmp, tmp2);
1793 break;
1794 case 2:
1795 tcg_gen_shli_i32(tmp2, tmp2, 16);
1796 tcg_gen_and_i32(tmp, tmp, tmp2);
1797 break;
1799 gen_set_nzcv(tmp);
1800 dead_tmp(tmp2);
1801 dead_tmp(tmp);
1802 break;
1803 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1804 wrd = (insn >> 12) & 0xf;
1805 rd0 = (insn >> 16) & 0xf;
1806 gen_op_iwmmxt_movq_M0_wRn(rd0);
1807 switch ((insn >> 22) & 3) {
1808 case 0:
1809 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1810 break;
1811 case 1:
1812 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1813 break;
1814 case 2:
1815 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1816 break;
1817 case 3:
1818 return 1;
1820 gen_op_iwmmxt_movq_wRn_M0(wrd);
1821 gen_op_iwmmxt_set_mup();
1822 break;
1823 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1824 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1825 return 1;
1826 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1827 tmp2 = new_tmp();
1828 tcg_gen_mov_i32(tmp2, tmp);
1829 switch ((insn >> 22) & 3) {
1830 case 0:
1831 for (i = 0; i < 7; i ++) {
1832 tcg_gen_shli_i32(tmp2, tmp2, 4);
1833 tcg_gen_or_i32(tmp, tmp, tmp2);
1835 break;
1836 case 1:
1837 for (i = 0; i < 3; i ++) {
1838 tcg_gen_shli_i32(tmp2, tmp2, 8);
1839 tcg_gen_or_i32(tmp, tmp, tmp2);
1841 break;
1842 case 2:
1843 tcg_gen_shli_i32(tmp2, tmp2, 16);
1844 tcg_gen_or_i32(tmp, tmp, tmp2);
1845 break;
1847 gen_set_nzcv(tmp);
1848 dead_tmp(tmp2);
1849 dead_tmp(tmp);
1850 break;
1851 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1852 rd = (insn >> 12) & 0xf;
1853 rd0 = (insn >> 16) & 0xf;
1854 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1855 return 1;
1856 gen_op_iwmmxt_movq_M0_wRn(rd0);
1857 tmp = new_tmp();
1858 switch ((insn >> 22) & 3) {
1859 case 0:
1860 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1861 break;
1862 case 1:
1863 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1864 break;
1865 case 2:
1866 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1867 break;
1869 store_reg(s, rd, tmp);
1870 break;
1871 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1872 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1873 wrd = (insn >> 12) & 0xf;
1874 rd0 = (insn >> 16) & 0xf;
1875 rd1 = (insn >> 0) & 0xf;
1876 gen_op_iwmmxt_movq_M0_wRn(rd0);
1877 switch ((insn >> 22) & 3) {
1878 case 0:
1879 if (insn & (1 << 21))
1880 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1881 else
1882 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1883 break;
1884 case 1:
1885 if (insn & (1 << 21))
1886 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1887 else
1888 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1889 break;
1890 case 2:
1891 if (insn & (1 << 21))
1892 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1893 else
1894 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1895 break;
1896 case 3:
1897 return 1;
1899 gen_op_iwmmxt_movq_wRn_M0(wrd);
1900 gen_op_iwmmxt_set_mup();
1901 gen_op_iwmmxt_set_cup();
1902 break;
1903 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1904 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1905 wrd = (insn >> 12) & 0xf;
1906 rd0 = (insn >> 16) & 0xf;
1907 gen_op_iwmmxt_movq_M0_wRn(rd0);
1908 switch ((insn >> 22) & 3) {
1909 case 0:
1910 if (insn & (1 << 21))
1911 gen_op_iwmmxt_unpacklsb_M0();
1912 else
1913 gen_op_iwmmxt_unpacklub_M0();
1914 break;
1915 case 1:
1916 if (insn & (1 << 21))
1917 gen_op_iwmmxt_unpacklsw_M0();
1918 else
1919 gen_op_iwmmxt_unpackluw_M0();
1920 break;
1921 case 2:
1922 if (insn & (1 << 21))
1923 gen_op_iwmmxt_unpacklsl_M0();
1924 else
1925 gen_op_iwmmxt_unpacklul_M0();
1926 break;
1927 case 3:
1928 return 1;
1930 gen_op_iwmmxt_movq_wRn_M0(wrd);
1931 gen_op_iwmmxt_set_mup();
1932 gen_op_iwmmxt_set_cup();
1933 break;
1934 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1935 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1936 wrd = (insn >> 12) & 0xf;
1937 rd0 = (insn >> 16) & 0xf;
1938 gen_op_iwmmxt_movq_M0_wRn(rd0);
1939 switch ((insn >> 22) & 3) {
1940 case 0:
1941 if (insn & (1 << 21))
1942 gen_op_iwmmxt_unpackhsb_M0();
1943 else
1944 gen_op_iwmmxt_unpackhub_M0();
1945 break;
1946 case 1:
1947 if (insn & (1 << 21))
1948 gen_op_iwmmxt_unpackhsw_M0();
1949 else
1950 gen_op_iwmmxt_unpackhuw_M0();
1951 break;
1952 case 2:
1953 if (insn & (1 << 21))
1954 gen_op_iwmmxt_unpackhsl_M0();
1955 else
1956 gen_op_iwmmxt_unpackhul_M0();
1957 break;
1958 case 3:
1959 return 1;
1961 gen_op_iwmmxt_movq_wRn_M0(wrd);
1962 gen_op_iwmmxt_set_mup();
1963 gen_op_iwmmxt_set_cup();
1964 break;
1965 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1966 case 0x214: case 0x614: case 0xa14: case 0xe14:
1967 if (((insn >> 22) & 3) == 0)
1968 return 1;
1969 wrd = (insn >> 12) & 0xf;
1970 rd0 = (insn >> 16) & 0xf;
1971 gen_op_iwmmxt_movq_M0_wRn(rd0);
1972 tmp = new_tmp();
1973 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1974 dead_tmp(tmp);
1975 return 1;
1977 switch ((insn >> 22) & 3) {
1978 case 1:
1979 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1980 break;
1981 case 2:
1982 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1983 break;
1984 case 3:
1985 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1986 break;
1988 dead_tmp(tmp);
1989 gen_op_iwmmxt_movq_wRn_M0(wrd);
1990 gen_op_iwmmxt_set_mup();
1991 gen_op_iwmmxt_set_cup();
1992 break;
1993 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1994 case 0x014: case 0x414: case 0x814: case 0xc14:
1995 if (((insn >> 22) & 3) == 0)
1996 return 1;
1997 wrd = (insn >> 12) & 0xf;
1998 rd0 = (insn >> 16) & 0xf;
1999 gen_op_iwmmxt_movq_M0_wRn(rd0);
2000 tmp = new_tmp();
2001 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2002 dead_tmp(tmp);
2003 return 1;
2005 switch ((insn >> 22) & 3) {
2006 case 1:
2007 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2008 break;
2009 case 2:
2010 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2011 break;
2012 case 3:
2013 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2014 break;
2016 dead_tmp(tmp);
2017 gen_op_iwmmxt_movq_wRn_M0(wrd);
2018 gen_op_iwmmxt_set_mup();
2019 gen_op_iwmmxt_set_cup();
2020 break;
2021 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2022 case 0x114: case 0x514: case 0x914: case 0xd14:
2023 if (((insn >> 22) & 3) == 0)
2024 return 1;
2025 wrd = (insn >> 12) & 0xf;
2026 rd0 = (insn >> 16) & 0xf;
2027 gen_op_iwmmxt_movq_M0_wRn(rd0);
2028 tmp = new_tmp();
2029 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2030 dead_tmp(tmp);
2031 return 1;
2033 switch ((insn >> 22) & 3) {
2034 case 1:
2035 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2036 break;
2037 case 2:
2038 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2039 break;
2040 case 3:
2041 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2042 break;
2044 dead_tmp(tmp);
2045 gen_op_iwmmxt_movq_wRn_M0(wrd);
2046 gen_op_iwmmxt_set_mup();
2047 gen_op_iwmmxt_set_cup();
2048 break;
2049 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2050 case 0x314: case 0x714: case 0xb14: case 0xf14:
2051 if (((insn >> 22) & 3) == 0)
2052 return 1;
2053 wrd = (insn >> 12) & 0xf;
2054 rd0 = (insn >> 16) & 0xf;
2055 gen_op_iwmmxt_movq_M0_wRn(rd0);
2056 tmp = new_tmp();
2057 switch ((insn >> 22) & 3) {
2058 case 1:
2059 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2060 dead_tmp(tmp);
2061 return 1;
2063 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2064 break;
2065 case 2:
2066 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2067 dead_tmp(tmp);
2068 return 1;
2070 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2071 break;
2072 case 3:
2073 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2074 dead_tmp(tmp);
2075 return 1;
2077 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2078 break;
2080 dead_tmp(tmp);
2081 gen_op_iwmmxt_movq_wRn_M0(wrd);
2082 gen_op_iwmmxt_set_mup();
2083 gen_op_iwmmxt_set_cup();
2084 break;
2085 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2086 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 16) & 0xf;
2089 rd1 = (insn >> 0) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0);
2091 switch ((insn >> 22) & 3) {
2092 case 0:
2093 if (insn & (1 << 21))
2094 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2095 else
2096 gen_op_iwmmxt_minub_M0_wRn(rd1);
2097 break;
2098 case 1:
2099 if (insn & (1 << 21))
2100 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2101 else
2102 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2103 break;
2104 case 2:
2105 if (insn & (1 << 21))
2106 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2107 else
2108 gen_op_iwmmxt_minul_M0_wRn(rd1);
2109 break;
2110 case 3:
2111 return 1;
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 break;
2116 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2117 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2118 wrd = (insn >> 12) & 0xf;
2119 rd0 = (insn >> 16) & 0xf;
2120 rd1 = (insn >> 0) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0);
2122 switch ((insn >> 22) & 3) {
2123 case 0:
2124 if (insn & (1 << 21))
2125 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2126 else
2127 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2128 break;
2129 case 1:
2130 if (insn & (1 << 21))
2131 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2132 else
2133 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2134 break;
2135 case 2:
2136 if (insn & (1 << 21))
2137 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2138 else
2139 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2140 break;
2141 case 3:
2142 return 1;
2144 gen_op_iwmmxt_movq_wRn_M0(wrd);
2145 gen_op_iwmmxt_set_mup();
2146 break;
2147 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2148 case 0x402: case 0x502: case 0x602: case 0x702:
2149 wrd = (insn >> 12) & 0xf;
2150 rd0 = (insn >> 16) & 0xf;
2151 rd1 = (insn >> 0) & 0xf;
2152 gen_op_iwmmxt_movq_M0_wRn(rd0);
2153 tmp = tcg_const_i32((insn >> 20) & 3);
2154 iwmmxt_load_reg(cpu_V1, rd1);
2155 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2156 tcg_temp_free(tmp);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd);
2158 gen_op_iwmmxt_set_mup();
2159 break;
2160 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2161 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2162 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2163 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2164 wrd = (insn >> 12) & 0xf;
2165 rd0 = (insn >> 16) & 0xf;
2166 rd1 = (insn >> 0) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0);
2168 switch ((insn >> 20) & 0xf) {
2169 case 0x0:
2170 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2171 break;
2172 case 0x1:
2173 gen_op_iwmmxt_subub_M0_wRn(rd1);
2174 break;
2175 case 0x3:
2176 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2177 break;
2178 case 0x4:
2179 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2180 break;
2181 case 0x5:
2182 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2183 break;
2184 case 0x7:
2185 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2186 break;
2187 case 0x8:
2188 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2189 break;
2190 case 0x9:
2191 gen_op_iwmmxt_subul_M0_wRn(rd1);
2192 break;
2193 case 0xb:
2194 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2195 break;
2196 default:
2197 return 1;
2199 gen_op_iwmmxt_movq_wRn_M0(wrd);
2200 gen_op_iwmmxt_set_mup();
2201 gen_op_iwmmxt_set_cup();
2202 break;
2203 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2204 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2205 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2206 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2207 wrd = (insn >> 12) & 0xf;
2208 rd0 = (insn >> 16) & 0xf;
2209 gen_op_iwmmxt_movq_M0_wRn(rd0);
2210 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2211 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2212 tcg_temp_free(tmp);
2213 gen_op_iwmmxt_movq_wRn_M0(wrd);
2214 gen_op_iwmmxt_set_mup();
2215 gen_op_iwmmxt_set_cup();
2216 break;
2217 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2218 case 0x418: case 0x518: case 0x618: case 0x718:
2219 case 0x818: case 0x918: case 0xa18: case 0xb18:
2220 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2221 wrd = (insn >> 12) & 0xf;
2222 rd0 = (insn >> 16) & 0xf;
2223 rd1 = (insn >> 0) & 0xf;
2224 gen_op_iwmmxt_movq_M0_wRn(rd0);
2225 switch ((insn >> 20) & 0xf) {
2226 case 0x0:
2227 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2228 break;
2229 case 0x1:
2230 gen_op_iwmmxt_addub_M0_wRn(rd1);
2231 break;
2232 case 0x3:
2233 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2234 break;
2235 case 0x4:
2236 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2237 break;
2238 case 0x5:
2239 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2240 break;
2241 case 0x7:
2242 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2243 break;
2244 case 0x8:
2245 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2246 break;
2247 case 0x9:
2248 gen_op_iwmmxt_addul_M0_wRn(rd1);
2249 break;
2250 case 0xb:
2251 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2252 break;
2253 default:
2254 return 1;
2256 gen_op_iwmmxt_movq_wRn_M0(wrd);
2257 gen_op_iwmmxt_set_mup();
2258 gen_op_iwmmxt_set_cup();
2259 break;
2260 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2261 case 0x408: case 0x508: case 0x608: case 0x708:
2262 case 0x808: case 0x908: case 0xa08: case 0xb08:
2263 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2264 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2265 return 1;
2266 wrd = (insn >> 12) & 0xf;
2267 rd0 = (insn >> 16) & 0xf;
2268 rd1 = (insn >> 0) & 0xf;
2269 gen_op_iwmmxt_movq_M0_wRn(rd0);
2270 switch ((insn >> 22) & 3) {
2271 case 1:
2272 if (insn & (1 << 21))
2273 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2274 else
2275 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2276 break;
2277 case 2:
2278 if (insn & (1 << 21))
2279 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2280 else
2281 gen_op_iwmmxt_packul_M0_wRn(rd1);
2282 break;
2283 case 3:
2284 if (insn & (1 << 21))
2285 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2286 else
2287 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2288 break;
2290 gen_op_iwmmxt_movq_wRn_M0(wrd);
2291 gen_op_iwmmxt_set_mup();
2292 gen_op_iwmmxt_set_cup();
2293 break;
2294 case 0x201: case 0x203: case 0x205: case 0x207:
2295 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2296 case 0x211: case 0x213: case 0x215: case 0x217:
2297 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2298 wrd = (insn >> 5) & 0xf;
2299 rd0 = (insn >> 12) & 0xf;
2300 rd1 = (insn >> 0) & 0xf;
2301 if (rd0 == 0xf || rd1 == 0xf)
2302 return 1;
2303 gen_op_iwmmxt_movq_M0_wRn(wrd);
2304 tmp = load_reg(s, rd0);
2305 tmp2 = load_reg(s, rd1);
2306 switch ((insn >> 16) & 0xf) {
2307 case 0x0: /* TMIA */
2308 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2309 break;
2310 case 0x8: /* TMIAPH */
2311 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2312 break;
2313 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2314 if (insn & (1 << 16))
2315 tcg_gen_shri_i32(tmp, tmp, 16);
2316 if (insn & (1 << 17))
2317 tcg_gen_shri_i32(tmp2, tmp2, 16);
2318 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2319 break;
2320 default:
2321 dead_tmp(tmp2);
2322 dead_tmp(tmp);
2323 return 1;
2325 dead_tmp(tmp2);
2326 dead_tmp(tmp);
2327 gen_op_iwmmxt_movq_wRn_M0(wrd);
2328 gen_op_iwmmxt_set_mup();
2329 break;
2330 default:
2331 return 1;
2334 return 0;
2337 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2338 (ie. an undefined instruction). */
2339 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2341 int acc, rd0, rd1, rdhi, rdlo;
2342 TCGv tmp, tmp2;
2344 if ((insn & 0x0ff00f10) == 0x0e200010) {
2345 /* Multiply with Internal Accumulate Format */
2346 rd0 = (insn >> 12) & 0xf;
2347 rd1 = insn & 0xf;
2348 acc = (insn >> 5) & 7;
2350 if (acc != 0)
2351 return 1;
2353 tmp = load_reg(s, rd0);
2354 tmp2 = load_reg(s, rd1);
2355 switch ((insn >> 16) & 0xf) {
2356 case 0x0: /* MIA */
2357 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2358 break;
2359 case 0x8: /* MIAPH */
2360 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2361 break;
2362 case 0xc: /* MIABB */
2363 case 0xd: /* MIABT */
2364 case 0xe: /* MIATB */
2365 case 0xf: /* MIATT */
2366 if (insn & (1 << 16))
2367 tcg_gen_shri_i32(tmp, tmp, 16);
2368 if (insn & (1 << 17))
2369 tcg_gen_shri_i32(tmp2, tmp2, 16);
2370 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2371 break;
2372 default:
2373 return 1;
2375 dead_tmp(tmp2);
2376 dead_tmp(tmp);
2378 gen_op_iwmmxt_movq_wRn_M0(acc);
2379 return 0;
2382 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2383 /* Internal Accumulator Access Format */
2384 rdhi = (insn >> 16) & 0xf;
2385 rdlo = (insn >> 12) & 0xf;
2386 acc = insn & 7;
2388 if (acc != 0)
2389 return 1;
2391 if (insn & ARM_CP_RW_BIT) { /* MRA */
2392 iwmmxt_load_reg(cpu_V0, acc);
2393 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2394 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2395 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2396 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2397 } else { /* MAR */
2398 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2399 iwmmxt_store_reg(cpu_V0, acc);
2401 return 0;
2404 return 1;
2407 /* Disassemble system coprocessor instruction. Return nonzero if
2408 instruction is not defined. */
2409 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2411 TCGv tmp, tmp2;
2412 uint32_t rd = (insn >> 12) & 0xf;
2413 uint32_t cp = (insn >> 8) & 0xf;
2414 if (IS_USER(s)) {
2415 return 1;
2418 if (insn & ARM_CP_RW_BIT) {
2419 if (!env->cp[cp].cp_read)
2420 return 1;
2421 gen_set_pc_im(s->pc);
2422 tmp = new_tmp();
2423 tmp2 = tcg_const_i32(insn);
2424 gen_helper_get_cp(tmp, cpu_env, tmp2);
2425 tcg_temp_free(tmp2);
2426 store_reg(s, rd, tmp);
2427 } else {
2428 if (!env->cp[cp].cp_write)
2429 return 1;
2430 gen_set_pc_im(s->pc);
2431 tmp = load_reg(s, rd);
2432 tmp2 = tcg_const_i32(insn);
2433 gen_helper_set_cp(cpu_env, tmp2, tmp);
2434 tcg_temp_free(tmp2);
2435 dead_tmp(tmp);
2437 return 0;
2440 static int cp15_user_ok(uint32_t insn)
2442 int cpn = (insn >> 16) & 0xf;
2443 int cpm = insn & 0xf;
2444 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2446 if (cpn == 13 && cpm == 0) {
2447 /* TLS register. */
2448 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2449 return 1;
2451 if (cpn == 7) {
2452 /* ISB, DSB, DMB. */
2453 if ((cpm == 5 && op == 4)
2454 || (cpm == 10 && (op == 4 || op == 5)))
2455 return 1;
2457 return 0;
2460 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2462 TCGv tmp;
2463 int cpn = (insn >> 16) & 0xf;
2464 int cpm = insn & 0xf;
2465 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2467 if (!arm_feature(env, ARM_FEATURE_V6K))
2468 return 0;
2470 if (!(cpn == 13 && cpm == 0))
2471 return 0;
2473 if (insn & ARM_CP_RW_BIT) {
2474 switch (op) {
2475 case 2:
2476 tmp = load_cpu_field(cp15.c13_tls1);
2477 break;
2478 case 3:
2479 tmp = load_cpu_field(cp15.c13_tls2);
2480 break;
2481 case 4:
2482 tmp = load_cpu_field(cp15.c13_tls3);
2483 break;
2484 default:
2485 return 0;
2487 store_reg(s, rd, tmp);
2489 } else {
2490 tmp = load_reg(s, rd);
2491 switch (op) {
2492 case 2:
2493 store_cpu_field(tmp, cp15.c13_tls1);
2494 break;
2495 case 3:
2496 store_cpu_field(tmp, cp15.c13_tls2);
2497 break;
2498 case 4:
2499 store_cpu_field(tmp, cp15.c13_tls3);
2500 break;
2501 default:
2502 dead_tmp(tmp);
2503 return 0;
2506 return 1;
2509 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2510 instruction is not defined. */
2511 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2513 uint32_t rd;
2514 TCGv tmp, tmp2;
2516 /* M profile cores use memory mapped registers instead of cp15. */
2517 if (arm_feature(env, ARM_FEATURE_M))
2518 return 1;
2520 if ((insn & (1 << 25)) == 0) {
2521 if (insn & (1 << 20)) {
2522 /* mrrc */
2523 return 1;
2525 /* mcrr. Used for block cache operations, so implement as no-op. */
2526 return 0;
2528 if ((insn & (1 << 4)) == 0) {
2529 /* cdp */
2530 return 1;
2532 if (IS_USER(s) && !cp15_user_ok(insn)) {
2533 return 1;
2535 if ((insn & 0x0fff0fff) == 0x0e070f90
2536 || (insn & 0x0fff0fff) == 0x0e070f58) {
2537 /* Wait for interrupt. */
2538 gen_set_pc_im(s->pc);
2539 s->is_jmp = DISAS_WFI;
2540 return 0;
2542 rd = (insn >> 12) & 0xf;
2544 if (cp15_tls_load_store(env, s, insn, rd))
2545 return 0;
2547 tmp2 = tcg_const_i32(insn);
2548 if (insn & ARM_CP_RW_BIT) {
2549 tmp = new_tmp();
2550 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2551 /* If the destination register is r15 then sets condition codes. */
2552 if (rd != 15)
2553 store_reg(s, rd, tmp);
2554 else
2555 dead_tmp(tmp);
2556 } else {
2557 tmp = load_reg(s, rd);
2558 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2559 dead_tmp(tmp);
2560 /* Normally we would always end the TB here, but Linux
2561 * arch/arm/mach-pxa/sleep.S expects two instructions following
2562 * an MMU enable to execute from cache. Imitate this behaviour. */
2563 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2564 (insn & 0x0fff0fff) != 0x0e010f10)
2565 gen_lookup_tb(s);
2567 tcg_temp_free_i32(tmp2);
2568 return 0;
2571 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2572 #define VFP_SREG(insn, bigbit, smallbit) \
2573 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2574 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2575 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2576 reg = (((insn) >> (bigbit)) & 0x0f) \
2577 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2578 } else { \
2579 if (insn & (1 << (smallbit))) \
2580 return 1; \
2581 reg = ((insn) >> (bigbit)) & 0x0f; \
2582 }} while (0)
2584 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2585 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2586 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2587 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2588 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2589 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2591 /* Move between integer and VFP cores. */
2592 static TCGv gen_vfp_mrs(void)
2594 TCGv tmp = new_tmp();
2595 tcg_gen_mov_i32(tmp, cpu_F0s);
2596 return tmp;
2599 static void gen_vfp_msr(TCGv tmp)
2601 tcg_gen_mov_i32(cpu_F0s, tmp);
2602 dead_tmp(tmp);
2605 static inline int
2606 vfp_enabled(CPUState * env)
2608 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2611 static void gen_neon_dup_u8(TCGv var, int shift)
2613 TCGv tmp = new_tmp();
2614 if (shift)
2615 tcg_gen_shri_i32(var, var, shift);
2616 tcg_gen_ext8u_i32(var, var);
2617 tcg_gen_shli_i32(tmp, var, 8);
2618 tcg_gen_or_i32(var, var, tmp);
2619 tcg_gen_shli_i32(tmp, var, 16);
2620 tcg_gen_or_i32(var, var, tmp);
2621 dead_tmp(tmp);
2624 static void gen_neon_dup_low16(TCGv var)
2626 TCGv tmp = new_tmp();
2627 tcg_gen_ext16u_i32(var, var);
2628 tcg_gen_shli_i32(tmp, var, 16);
2629 tcg_gen_or_i32(var, var, tmp);
2630 dead_tmp(tmp);
2633 static void gen_neon_dup_high16(TCGv var)
2635 TCGv tmp = new_tmp();
2636 tcg_gen_andi_i32(var, var, 0xffff0000);
2637 tcg_gen_shri_i32(tmp, var, 16);
2638 tcg_gen_or_i32(var, var, tmp);
2639 dead_tmp(tmp);
2642 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2643 (ie. an undefined instruction). */
2644 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2646 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2647 int dp, veclen;
2648 TCGv addr;
2649 TCGv tmp;
2650 TCGv tmp2;
2652 if (!arm_feature(env, ARM_FEATURE_VFP))
2653 return 1;
2655 if (!vfp_enabled(env)) {
2656 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2657 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2658 return 1;
2659 rn = (insn >> 16) & 0xf;
2660 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2661 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2662 return 1;
2664 dp = ((insn & 0xf00) == 0xb00);
2665 switch ((insn >> 24) & 0xf) {
2666 case 0xe:
2667 if (insn & (1 << 4)) {
2668 /* single register transfer */
2669 rd = (insn >> 12) & 0xf;
2670 if (dp) {
2671 int size;
2672 int pass;
2674 VFP_DREG_N(rn, insn);
2675 if (insn & 0xf)
2676 return 1;
2677 if (insn & 0x00c00060
2678 && !arm_feature(env, ARM_FEATURE_NEON))
2679 return 1;
2681 pass = (insn >> 21) & 1;
2682 if (insn & (1 << 22)) {
2683 size = 0;
2684 offset = ((insn >> 5) & 3) * 8;
2685 } else if (insn & (1 << 5)) {
2686 size = 1;
2687 offset = (insn & (1 << 6)) ? 16 : 0;
2688 } else {
2689 size = 2;
2690 offset = 0;
2692 if (insn & ARM_CP_RW_BIT) {
2693 /* vfp->arm */
2694 tmp = neon_load_reg(rn, pass);
2695 switch (size) {
2696 case 0:
2697 if (offset)
2698 tcg_gen_shri_i32(tmp, tmp, offset);
2699 if (insn & (1 << 23))
2700 gen_uxtb(tmp);
2701 else
2702 gen_sxtb(tmp);
2703 break;
2704 case 1:
2705 if (insn & (1 << 23)) {
2706 if (offset) {
2707 tcg_gen_shri_i32(tmp, tmp, 16);
2708 } else {
2709 gen_uxth(tmp);
2711 } else {
2712 if (offset) {
2713 tcg_gen_sari_i32(tmp, tmp, 16);
2714 } else {
2715 gen_sxth(tmp);
2718 break;
2719 case 2:
2720 break;
2722 store_reg(s, rd, tmp);
2723 } else {
2724 /* arm->vfp */
2725 tmp = load_reg(s, rd);
2726 if (insn & (1 << 23)) {
2727 /* VDUP */
2728 if (size == 0) {
2729 gen_neon_dup_u8(tmp, 0);
2730 } else if (size == 1) {
2731 gen_neon_dup_low16(tmp);
2733 for (n = 0; n <= pass * 2; n++) {
2734 tmp2 = new_tmp();
2735 tcg_gen_mov_i32(tmp2, tmp);
2736 neon_store_reg(rn, n, tmp2);
2738 neon_store_reg(rn, n, tmp);
2739 } else {
2740 /* VMOV */
2741 switch (size) {
2742 case 0:
2743 tmp2 = neon_load_reg(rn, pass);
2744 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2745 dead_tmp(tmp2);
2746 break;
2747 case 1:
2748 tmp2 = neon_load_reg(rn, pass);
2749 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2750 dead_tmp(tmp2);
2751 break;
2752 case 2:
2753 break;
2755 neon_store_reg(rn, pass, tmp);
2758 } else { /* !dp */
2759 if ((insn & 0x6f) != 0x00)
2760 return 1;
2761 rn = VFP_SREG_N(insn);
2762 if (insn & ARM_CP_RW_BIT) {
2763 /* vfp->arm */
2764 if (insn & (1 << 21)) {
2765 /* system register */
2766 rn >>= 1;
2768 switch (rn) {
2769 case ARM_VFP_FPSID:
2770 /* VFP2 allows access to FSID from userspace.
2771 VFP3 restricts all id registers to privileged
2772 accesses. */
2773 if (IS_USER(s)
2774 && arm_feature(env, ARM_FEATURE_VFP3))
2775 return 1;
2776 tmp = load_cpu_field(vfp.xregs[rn]);
2777 break;
2778 case ARM_VFP_FPEXC:
2779 if (IS_USER(s))
2780 return 1;
2781 tmp = load_cpu_field(vfp.xregs[rn]);
2782 break;
2783 case ARM_VFP_FPINST:
2784 case ARM_VFP_FPINST2:
2785 /* Not present in VFP3. */
2786 if (IS_USER(s)
2787 || arm_feature(env, ARM_FEATURE_VFP3))
2788 return 1;
2789 tmp = load_cpu_field(vfp.xregs[rn]);
2790 break;
2791 case ARM_VFP_FPSCR:
2792 if (rd == 15) {
2793 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2794 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2795 } else {
2796 tmp = new_tmp();
2797 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2799 break;
2800 case ARM_VFP_MVFR0:
2801 case ARM_VFP_MVFR1:
2802 if (IS_USER(s)
2803 || !arm_feature(env, ARM_FEATURE_VFP3))
2804 return 1;
2805 tmp = load_cpu_field(vfp.xregs[rn]);
2806 break;
2807 default:
2808 return 1;
2810 } else {
2811 gen_mov_F0_vreg(0, rn);
2812 tmp = gen_vfp_mrs();
2814 if (rd == 15) {
2815 /* Set the 4 flag bits in the CPSR. */
2816 gen_set_nzcv(tmp);
2817 dead_tmp(tmp);
2818 } else {
2819 store_reg(s, rd, tmp);
2821 } else {
2822 /* arm->vfp */
2823 tmp = load_reg(s, rd);
2824 if (insn & (1 << 21)) {
2825 rn >>= 1;
2826 /* system register */
2827 switch (rn) {
2828 case ARM_VFP_FPSID:
2829 case ARM_VFP_MVFR0:
2830 case ARM_VFP_MVFR1:
2831 /* Writes are ignored. */
2832 break;
2833 case ARM_VFP_FPSCR:
2834 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2835 dead_tmp(tmp);
2836 gen_lookup_tb(s);
2837 break;
2838 case ARM_VFP_FPEXC:
2839 if (IS_USER(s))
2840 return 1;
2841 /* TODO: VFP subarchitecture support.
2842 * For now, keep the EN bit only */
2843 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2844 store_cpu_field(tmp, vfp.xregs[rn]);
2845 gen_lookup_tb(s);
2846 break;
2847 case ARM_VFP_FPINST:
2848 case ARM_VFP_FPINST2:
2849 store_cpu_field(tmp, vfp.xregs[rn]);
2850 break;
2851 default:
2852 return 1;
2854 } else {
2855 gen_vfp_msr(tmp);
2856 gen_mov_vreg_F0(0, rn);
2860 } else {
2861 /* data processing */
2862 /* The opcode is in bits 23, 21, 20 and 6. */
2863 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2864 if (dp) {
2865 if (op == 15) {
2866 /* rn is opcode */
2867 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2868 } else {
2869 /* rn is register number */
2870 VFP_DREG_N(rn, insn);
2873 if (op == 15 && (rn == 15 || rn > 17)) {
2874 /* Integer or single precision destination. */
2875 rd = VFP_SREG_D(insn);
2876 } else {
2877 VFP_DREG_D(rd, insn);
2880 if (op == 15 && (rn == 16 || rn == 17)) {
2881 /* Integer source. */
2882 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2883 } else {
2884 VFP_DREG_M(rm, insn);
2886 } else {
2887 rn = VFP_SREG_N(insn);
2888 if (op == 15 && rn == 15) {
2889 /* Double precision destination. */
2890 VFP_DREG_D(rd, insn);
2891 } else {
2892 rd = VFP_SREG_D(insn);
2894 rm = VFP_SREG_M(insn);
2897 veclen = env->vfp.vec_len;
2898 if (op == 15 && rn > 3)
2899 veclen = 0;
2901 /* Shut up compiler warnings. */
2902 delta_m = 0;
2903 delta_d = 0;
2904 bank_mask = 0;
2906 if (veclen > 0) {
2907 if (dp)
2908 bank_mask = 0xc;
2909 else
2910 bank_mask = 0x18;
2912 /* Figure out what type of vector operation this is. */
2913 if ((rd & bank_mask) == 0) {
2914 /* scalar */
2915 veclen = 0;
2916 } else {
2917 if (dp)
2918 delta_d = (env->vfp.vec_stride >> 1) + 1;
2919 else
2920 delta_d = env->vfp.vec_stride + 1;
2922 if ((rm & bank_mask) == 0) {
2923 /* mixed scalar/vector */
2924 delta_m = 0;
2925 } else {
2926 /* vector */
2927 delta_m = delta_d;
2932 /* Load the initial operands. */
2933 if (op == 15) {
2934 switch (rn) {
2935 case 16:
2936 case 17:
2937 /* Integer source */
2938 gen_mov_F0_vreg(0, rm);
2939 break;
2940 case 8:
2941 case 9:
2942 /* Compare */
2943 gen_mov_F0_vreg(dp, rd);
2944 gen_mov_F1_vreg(dp, rm);
2945 break;
2946 case 10:
2947 case 11:
2948 /* Compare with zero */
2949 gen_mov_F0_vreg(dp, rd);
2950 gen_vfp_F1_ld0(dp);
2951 break;
2952 case 20:
2953 case 21:
2954 case 22:
2955 case 23:
2956 case 28:
2957 case 29:
2958 case 30:
2959 case 31:
2960 /* Source and destination the same. */
2961 gen_mov_F0_vreg(dp, rd);
2962 break;
2963 default:
2964 /* One source operand. */
2965 gen_mov_F0_vreg(dp, rm);
2966 break;
2968 } else {
2969 /* Two source operands. */
2970 gen_mov_F0_vreg(dp, rn);
2971 gen_mov_F1_vreg(dp, rm);
2974 for (;;) {
2975 /* Perform the calculation. */
2976 switch (op) {
2977 case 0: /* mac: fd + (fn * fm) */
2978 gen_vfp_mul(dp);
2979 gen_mov_F1_vreg(dp, rd);
2980 gen_vfp_add(dp);
2981 break;
2982 case 1: /* nmac: fd - (fn * fm) */
2983 gen_vfp_mul(dp);
2984 gen_vfp_neg(dp);
2985 gen_mov_F1_vreg(dp, rd);
2986 gen_vfp_add(dp);
2987 break;
2988 case 2: /* msc: -fd + (fn * fm) */
2989 gen_vfp_mul(dp);
2990 gen_mov_F1_vreg(dp, rd);
2991 gen_vfp_sub(dp);
2992 break;
2993 case 3: /* nmsc: -fd - (fn * fm) */
2994 gen_vfp_mul(dp);
2995 gen_vfp_neg(dp);
2996 gen_mov_F1_vreg(dp, rd);
2997 gen_vfp_sub(dp);
2998 break;
2999 case 4: /* mul: fn * fm */
3000 gen_vfp_mul(dp);
3001 break;
3002 case 5: /* nmul: -(fn * fm) */
3003 gen_vfp_mul(dp);
3004 gen_vfp_neg(dp);
3005 break;
3006 case 6: /* add: fn + fm */
3007 gen_vfp_add(dp);
3008 break;
3009 case 7: /* sub: fn - fm */
3010 gen_vfp_sub(dp);
3011 break;
3012 case 8: /* div: fn / fm */
3013 gen_vfp_div(dp);
3014 break;
3015 case 14: /* fconst */
3016 if (!arm_feature(env, ARM_FEATURE_VFP3))
3017 return 1;
3019 n = (insn << 12) & 0x80000000;
3020 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3021 if (dp) {
3022 if (i & 0x40)
3023 i |= 0x3f80;
3024 else
3025 i |= 0x4000;
3026 n |= i << 16;
3027 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3028 } else {
3029 if (i & 0x40)
3030 i |= 0x780;
3031 else
3032 i |= 0x800;
3033 n |= i << 19;
3034 tcg_gen_movi_i32(cpu_F0s, n);
3036 break;
3037 case 15: /* extension space */
3038 switch (rn) {
3039 case 0: /* cpy */
3040 /* no-op */
3041 break;
3042 case 1: /* abs */
3043 gen_vfp_abs(dp);
3044 break;
3045 case 2: /* neg */
3046 gen_vfp_neg(dp);
3047 break;
3048 case 3: /* sqrt */
3049 gen_vfp_sqrt(dp);
3050 break;
3051 case 4: /* vcvtb.f32.f16 */
3052 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3053 return 1;
3054 tmp = gen_vfp_mrs();
3055 tcg_gen_ext16u_i32(tmp, tmp);
3056 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3057 dead_tmp(tmp);
3058 break;
3059 case 5: /* vcvtt.f32.f16 */
3060 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3061 return 1;
3062 tmp = gen_vfp_mrs();
3063 tcg_gen_shri_i32(tmp, tmp, 16);
3064 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3065 dead_tmp(tmp);
3066 break;
3067 case 6: /* vcvtb.f16.f32 */
3068 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3069 return 1;
3070 tmp = new_tmp();
3071 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3072 gen_mov_F0_vreg(0, rd);
3073 tmp2 = gen_vfp_mrs();
3074 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3075 tcg_gen_or_i32(tmp, tmp, tmp2);
3076 dead_tmp(tmp2);
3077 gen_vfp_msr(tmp);
3078 break;
3079 case 7: /* vcvtt.f16.f32 */
3080 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3081 return 1;
3082 tmp = new_tmp();
3083 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3084 tcg_gen_shli_i32(tmp, tmp, 16);
3085 gen_mov_F0_vreg(0, rd);
3086 tmp2 = gen_vfp_mrs();
3087 tcg_gen_ext16u_i32(tmp2, tmp2);
3088 tcg_gen_or_i32(tmp, tmp, tmp2);
3089 dead_tmp(tmp2);
3090 gen_vfp_msr(tmp);
3091 break;
3092 case 8: /* cmp */
3093 gen_vfp_cmp(dp);
3094 break;
3095 case 9: /* cmpe */
3096 gen_vfp_cmpe(dp);
3097 break;
3098 case 10: /* cmpz */
3099 gen_vfp_cmp(dp);
3100 break;
3101 case 11: /* cmpez */
3102 gen_vfp_F1_ld0(dp);
3103 gen_vfp_cmpe(dp);
3104 break;
3105 case 15: /* single<->double conversion */
3106 if (dp)
3107 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3108 else
3109 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3110 break;
3111 case 16: /* fuito */
3112 gen_vfp_uito(dp);
3113 break;
3114 case 17: /* fsito */
3115 gen_vfp_sito(dp);
3116 break;
3117 case 20: /* fshto */
3118 if (!arm_feature(env, ARM_FEATURE_VFP3))
3119 return 1;
3120 gen_vfp_shto(dp, 16 - rm);
3121 break;
3122 case 21: /* fslto */
3123 if (!arm_feature(env, ARM_FEATURE_VFP3))
3124 return 1;
3125 gen_vfp_slto(dp, 32 - rm);
3126 break;
3127 case 22: /* fuhto */
3128 if (!arm_feature(env, ARM_FEATURE_VFP3))
3129 return 1;
3130 gen_vfp_uhto(dp, 16 - rm);
3131 break;
3132 case 23: /* fulto */
3133 if (!arm_feature(env, ARM_FEATURE_VFP3))
3134 return 1;
3135 gen_vfp_ulto(dp, 32 - rm);
3136 break;
3137 case 24: /* ftoui */
3138 gen_vfp_toui(dp);
3139 break;
3140 case 25: /* ftouiz */
3141 gen_vfp_touiz(dp);
3142 break;
3143 case 26: /* ftosi */
3144 gen_vfp_tosi(dp);
3145 break;
3146 case 27: /* ftosiz */
3147 gen_vfp_tosiz(dp);
3148 break;
3149 case 28: /* ftosh */
3150 if (!arm_feature(env, ARM_FEATURE_VFP3))
3151 return 1;
3152 gen_vfp_tosh(dp, 16 - rm);
3153 break;
3154 case 29: /* ftosl */
3155 if (!arm_feature(env, ARM_FEATURE_VFP3))
3156 return 1;
3157 gen_vfp_tosl(dp, 32 - rm);
3158 break;
3159 case 30: /* ftouh */
3160 if (!arm_feature(env, ARM_FEATURE_VFP3))
3161 return 1;
3162 gen_vfp_touh(dp, 16 - rm);
3163 break;
3164 case 31: /* ftoul */
3165 if (!arm_feature(env, ARM_FEATURE_VFP3))
3166 return 1;
3167 gen_vfp_toul(dp, 32 - rm);
3168 break;
3169 default: /* undefined */
3170 printf ("rn:%d\n", rn);
3171 return 1;
3173 break;
3174 default: /* undefined */
3175 printf ("op:%d\n", op);
3176 return 1;
3179 /* Write back the result. */
3180 if (op == 15 && (rn >= 8 && rn <= 11))
3181 ; /* Comparison, do nothing. */
3182 else if (op == 15 && rn > 17)
3183 /* Integer result. */
3184 gen_mov_vreg_F0(0, rd);
3185 else if (op == 15 && rn == 15)
3186 /* conversion */
3187 gen_mov_vreg_F0(!dp, rd);
3188 else
3189 gen_mov_vreg_F0(dp, rd);
3191 /* break out of the loop if we have finished */
3192 if (veclen == 0)
3193 break;
3195 if (op == 15 && delta_m == 0) {
3196 /* single source one-many */
3197 while (veclen--) {
3198 rd = ((rd + delta_d) & (bank_mask - 1))
3199 | (rd & bank_mask);
3200 gen_mov_vreg_F0(dp, rd);
3202 break;
3204 /* Setup the next operands. */
3205 veclen--;
3206 rd = ((rd + delta_d) & (bank_mask - 1))
3207 | (rd & bank_mask);
3209 if (op == 15) {
3210 /* One source operand. */
3211 rm = ((rm + delta_m) & (bank_mask - 1))
3212 | (rm & bank_mask);
3213 gen_mov_F0_vreg(dp, rm);
3214 } else {
3215 /* Two source operands. */
3216 rn = ((rn + delta_d) & (bank_mask - 1))
3217 | (rn & bank_mask);
3218 gen_mov_F0_vreg(dp, rn);
3219 if (delta_m) {
3220 rm = ((rm + delta_m) & (bank_mask - 1))
3221 | (rm & bank_mask);
3222 gen_mov_F1_vreg(dp, rm);
3227 break;
3228 case 0xc:
3229 case 0xd:
3230 if (dp && (insn & 0x03e00000) == 0x00400000) {
3231 /* two-register transfer */
3232 rn = (insn >> 16) & 0xf;
3233 rd = (insn >> 12) & 0xf;
3234 if (dp) {
3235 VFP_DREG_M(rm, insn);
3236 } else {
3237 rm = VFP_SREG_M(insn);
3240 if (insn & ARM_CP_RW_BIT) {
3241 /* vfp->arm */
3242 if (dp) {
3243 gen_mov_F0_vreg(0, rm * 2);
3244 tmp = gen_vfp_mrs();
3245 store_reg(s, rd, tmp);
3246 gen_mov_F0_vreg(0, rm * 2 + 1);
3247 tmp = gen_vfp_mrs();
3248 store_reg(s, rn, tmp);
3249 } else {
3250 gen_mov_F0_vreg(0, rm);
3251 tmp = gen_vfp_mrs();
3252 store_reg(s, rn, tmp);
3253 gen_mov_F0_vreg(0, rm + 1);
3254 tmp = gen_vfp_mrs();
3255 store_reg(s, rd, tmp);
3257 } else {
3258 /* arm->vfp */
3259 if (dp) {
3260 tmp = load_reg(s, rd);
3261 gen_vfp_msr(tmp);
3262 gen_mov_vreg_F0(0, rm * 2);
3263 tmp = load_reg(s, rn);
3264 gen_vfp_msr(tmp);
3265 gen_mov_vreg_F0(0, rm * 2 + 1);
3266 } else {
3267 tmp = load_reg(s, rn);
3268 gen_vfp_msr(tmp);
3269 gen_mov_vreg_F0(0, rm);
3270 tmp = load_reg(s, rd);
3271 gen_vfp_msr(tmp);
3272 gen_mov_vreg_F0(0, rm + 1);
3275 } else {
3276 /* Load/store */
3277 rn = (insn >> 16) & 0xf;
3278 if (dp)
3279 VFP_DREG_D(rd, insn);
3280 else
3281 rd = VFP_SREG_D(insn);
3282 if (s->thumb && rn == 15) {
3283 addr = new_tmp();
3284 tcg_gen_movi_i32(addr, s->pc & ~2);
3285 } else {
3286 addr = load_reg(s, rn);
3288 if ((insn & 0x01200000) == 0x01000000) {
3289 /* Single load/store */
3290 offset = (insn & 0xff) << 2;
3291 if ((insn & (1 << 23)) == 0)
3292 offset = -offset;
3293 tcg_gen_addi_i32(addr, addr, offset);
3294 if (insn & (1 << 20)) {
3295 gen_vfp_ld(s, dp, addr);
3296 gen_mov_vreg_F0(dp, rd);
3297 } else {
3298 gen_mov_F0_vreg(dp, rd);
3299 gen_vfp_st(s, dp, addr);
3301 dead_tmp(addr);
3302 } else {
3303 /* load/store multiple */
3304 if (dp)
3305 n = (insn >> 1) & 0x7f;
3306 else
3307 n = insn & 0xff;
3309 if (insn & (1 << 24)) /* pre-decrement */
3310 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3312 if (dp)
3313 offset = 8;
3314 else
3315 offset = 4;
3316 for (i = 0; i < n; i++) {
3317 if (insn & ARM_CP_RW_BIT) {
3318 /* load */
3319 gen_vfp_ld(s, dp, addr);
3320 gen_mov_vreg_F0(dp, rd + i);
3321 } else {
3322 /* store */
3323 gen_mov_F0_vreg(dp, rd + i);
3324 gen_vfp_st(s, dp, addr);
3326 tcg_gen_addi_i32(addr, addr, offset);
3328 if (insn & (1 << 21)) {
3329 /* writeback */
3330 if (insn & (1 << 24))
3331 offset = -offset * n;
3332 else if (dp && (insn & 1))
3333 offset = 4;
3334 else
3335 offset = 0;
3337 if (offset != 0)
3338 tcg_gen_addi_i32(addr, addr, offset);
3339 store_reg(s, rn, addr);
3340 } else {
3341 dead_tmp(addr);
3345 break;
3346 default:
3347 /* Should never happen. */
3348 return 1;
3350 return 0;
3353 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3355 TranslationBlock *tb;
3357 tb = s->tb;
3358 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3359 tcg_gen_goto_tb(n);
3360 gen_set_pc_im(dest);
3361 tcg_gen_exit_tb((long)tb + n);
3362 } else {
3363 gen_set_pc_im(dest);
3364 tcg_gen_exit_tb(0);
3368 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3370 if (unlikely(s->singlestep_enabled)) {
3371 /* An indirect jump so that we still trigger the debug exception. */
3372 if (s->thumb)
3373 dest |= 1;
3374 gen_bx_im(s, dest);
3375 } else {
3376 gen_goto_tb(s, 0, dest);
3377 s->is_jmp = DISAS_TB_JUMP;
3381 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3383 if (x)
3384 tcg_gen_sari_i32(t0, t0, 16);
3385 else
3386 gen_sxth(t0);
3387 if (y)
3388 tcg_gen_sari_i32(t1, t1, 16);
3389 else
3390 gen_sxth(t1);
3391 tcg_gen_mul_i32(t0, t0, t1);
3394 /* Return the mask of PSR bits set by a MSR instruction. */
3395 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3396 uint32_t mask;
3398 mask = 0;
3399 if (flags & (1 << 0))
3400 mask |= 0xff;
3401 if (flags & (1 << 1))
3402 mask |= 0xff00;
3403 if (flags & (1 << 2))
3404 mask |= 0xff0000;
3405 if (flags & (1 << 3))
3406 mask |= 0xff000000;
3408 /* Mask out undefined bits. */
3409 mask &= ~CPSR_RESERVED;
3410 if (!arm_feature(env, ARM_FEATURE_V6))
3411 mask &= ~(CPSR_E | CPSR_GE);
3412 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3413 mask &= ~CPSR_IT;
3414 /* Mask out execution state bits. */
3415 if (!spsr)
3416 mask &= ~CPSR_EXEC;
3417 /* Mask out privileged bits. */
3418 if (IS_USER(s))
3419 mask &= CPSR_USER;
3420 return mask;
3423 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3424 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3426 TCGv tmp;
3427 if (spsr) {
3428 /* ??? This is also undefined in system mode. */
3429 if (IS_USER(s))
3430 return 1;
3432 tmp = load_cpu_field(spsr);
3433 tcg_gen_andi_i32(tmp, tmp, ~mask);
3434 tcg_gen_andi_i32(t0, t0, mask);
3435 tcg_gen_or_i32(tmp, tmp, t0);
3436 store_cpu_field(tmp, spsr);
3437 } else {
3438 gen_set_cpsr(t0, mask);
3440 dead_tmp(t0);
3441 gen_lookup_tb(s);
3442 return 0;
3445 /* Returns nonzero if access to the PSR is not permitted. */
3446 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3448 TCGv tmp;
3449 tmp = new_tmp();
3450 tcg_gen_movi_i32(tmp, val);
3451 return gen_set_psr(s, mask, spsr, tmp);
3454 /* Generate an old-style exception return. Marks pc as dead. */
3455 static void gen_exception_return(DisasContext *s, TCGv pc)
3457 TCGv tmp;
3458 store_reg(s, 15, pc);
3459 tmp = load_cpu_field(spsr);
3460 gen_set_cpsr(tmp, 0xffffffff);
3461 dead_tmp(tmp);
3462 s->is_jmp = DISAS_UPDATE;
3465 /* Generate a v6 exception return. Marks both values as dead. */
3466 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3468 gen_set_cpsr(cpsr, 0xffffffff);
3469 dead_tmp(cpsr);
3470 store_reg(s, 15, pc);
3471 s->is_jmp = DISAS_UPDATE;
3474 static inline void
3475 gen_set_condexec (DisasContext *s)
3477 if (s->condexec_mask) {
3478 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3479 TCGv tmp = new_tmp();
3480 tcg_gen_movi_i32(tmp, val);
3481 store_cpu_field(tmp, condexec_bits);
3485 static void gen_nop_hint(DisasContext *s, int val)
3487 switch (val) {
3488 case 3: /* wfi */
3489 gen_set_pc_im(s->pc);
3490 s->is_jmp = DISAS_WFI;
3491 break;
3492 case 2: /* wfe */
3493 case 4: /* sev */
3494 /* TODO: Implement SEV and WFE. May help SMP performance. */
3495 default: /* nop */
3496 break;
3500 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3502 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3504 switch (size) {
3505 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3506 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3507 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3508 default: return 1;
3510 return 0;
3513 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3515 switch (size) {
3516 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3517 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3518 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3519 default: return;
3523 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3524 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3525 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3526 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3527 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3529 /* FIXME: This is wrong. They set the wrong overflow bit. */
3530 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3531 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3532 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3533 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3535 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3536 switch ((size << 1) | u) { \
3537 case 0: \
3538 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3539 break; \
3540 case 1: \
3541 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3542 break; \
3543 case 2: \
3544 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3545 break; \
3546 case 3: \
3547 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3548 break; \
3549 case 4: \
3550 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3551 break; \
3552 case 5: \
3553 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3554 break; \
3555 default: return 1; \
3556 }} while (0)
3558 #define GEN_NEON_INTEGER_OP(name) do { \
3559 switch ((size << 1) | u) { \
3560 case 0: \
3561 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3562 break; \
3563 case 1: \
3564 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3565 break; \
3566 case 2: \
3567 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3568 break; \
3569 case 3: \
3570 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3571 break; \
3572 case 4: \
3573 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3574 break; \
3575 case 5: \
3576 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3577 break; \
3578 default: return 1; \
3579 }} while (0)
3581 static TCGv neon_load_scratch(int scratch)
3583 TCGv tmp = new_tmp();
3584 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3585 return tmp;
3588 static void neon_store_scratch(int scratch, TCGv var)
3590 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3591 dead_tmp(var);
3594 static inline TCGv neon_get_scalar(int size, int reg)
3596 TCGv tmp;
3597 if (size == 1) {
3598 tmp = neon_load_reg(reg >> 1, reg & 1);
3599 } else {
3600 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3601 if (reg & 1) {
3602 gen_neon_dup_low16(tmp);
3603 } else {
3604 gen_neon_dup_high16(tmp);
3607 return tmp;
3610 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3612 TCGv rd, rm, tmp;
3614 rd = new_tmp();
3615 rm = new_tmp();
3616 tmp = new_tmp();
3618 tcg_gen_andi_i32(rd, t0, 0xff);
3619 tcg_gen_shri_i32(tmp, t0, 8);
3620 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3621 tcg_gen_or_i32(rd, rd, tmp);
3622 tcg_gen_shli_i32(tmp, t1, 16);
3623 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3624 tcg_gen_or_i32(rd, rd, tmp);
3625 tcg_gen_shli_i32(tmp, t1, 8);
3626 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3627 tcg_gen_or_i32(rd, rd, tmp);
3629 tcg_gen_shri_i32(rm, t0, 8);
3630 tcg_gen_andi_i32(rm, rm, 0xff);
3631 tcg_gen_shri_i32(tmp, t0, 16);
3632 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3633 tcg_gen_or_i32(rm, rm, tmp);
3634 tcg_gen_shli_i32(tmp, t1, 8);
3635 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3636 tcg_gen_or_i32(rm, rm, tmp);
3637 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3638 tcg_gen_or_i32(t1, rm, tmp);
3639 tcg_gen_mov_i32(t0, rd);
3641 dead_tmp(tmp);
3642 dead_tmp(rm);
3643 dead_tmp(rd);
3646 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3648 TCGv rd, rm, tmp;
3650 rd = new_tmp();
3651 rm = new_tmp();
3652 tmp = new_tmp();
3654 tcg_gen_andi_i32(rd, t0, 0xff);
3655 tcg_gen_shli_i32(tmp, t1, 8);
3656 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3657 tcg_gen_or_i32(rd, rd, tmp);
3658 tcg_gen_shli_i32(tmp, t0, 16);
3659 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3660 tcg_gen_or_i32(rd, rd, tmp);
3661 tcg_gen_shli_i32(tmp, t1, 24);
3662 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3663 tcg_gen_or_i32(rd, rd, tmp);
3665 tcg_gen_andi_i32(rm, t1, 0xff000000);
3666 tcg_gen_shri_i32(tmp, t0, 8);
3667 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3668 tcg_gen_or_i32(rm, rm, tmp);
3669 tcg_gen_shri_i32(tmp, t1, 8);
3670 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3671 tcg_gen_or_i32(rm, rm, tmp);
3672 tcg_gen_shri_i32(tmp, t0, 16);
3673 tcg_gen_andi_i32(tmp, tmp, 0xff);
3674 tcg_gen_or_i32(t1, rm, tmp);
3675 tcg_gen_mov_i32(t0, rd);
3677 dead_tmp(tmp);
3678 dead_tmp(rm);
3679 dead_tmp(rd);
3682 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3684 TCGv tmp, tmp2;
3686 tmp = new_tmp();
3687 tmp2 = new_tmp();
3689 tcg_gen_andi_i32(tmp, t0, 0xffff);
3690 tcg_gen_shli_i32(tmp2, t1, 16);
3691 tcg_gen_or_i32(tmp, tmp, tmp2);
3692 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3693 tcg_gen_shri_i32(tmp2, t0, 16);
3694 tcg_gen_or_i32(t1, t1, tmp2);
3695 tcg_gen_mov_i32(t0, tmp);
3697 dead_tmp(tmp2);
3698 dead_tmp(tmp);
3701 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3703 int n;
3704 TCGv t0, t1;
3706 for (n = 0; n < q + 1; n += 2) {
3707 t0 = neon_load_reg(reg, n);
3708 t1 = neon_load_reg(reg, n + 1);
3709 switch (size) {
3710 case 0: gen_neon_unzip_u8(t0, t1); break;
3711 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3712 case 2: /* no-op */; break;
3713 default: abort();
3715 neon_store_scratch(tmp + n, t0);
3716 neon_store_scratch(tmp + n + 1, t1);
3720 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3722 TCGv rd, tmp;
3724 rd = new_tmp();
3725 tmp = new_tmp();
3727 tcg_gen_shli_i32(rd, t0, 8);
3728 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3729 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3730 tcg_gen_or_i32(rd, rd, tmp);
3732 tcg_gen_shri_i32(t1, t1, 8);
3733 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3734 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3735 tcg_gen_or_i32(t1, t1, tmp);
3736 tcg_gen_mov_i32(t0, rd);
3738 dead_tmp(tmp);
3739 dead_tmp(rd);
3742 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3744 TCGv rd, tmp;
3746 rd = new_tmp();
3747 tmp = new_tmp();
3749 tcg_gen_shli_i32(rd, t0, 16);
3750 tcg_gen_andi_i32(tmp, t1, 0xffff);
3751 tcg_gen_or_i32(rd, rd, tmp);
3752 tcg_gen_shri_i32(t1, t1, 16);
3753 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3754 tcg_gen_or_i32(t1, t1, tmp);
3755 tcg_gen_mov_i32(t0, rd);
3757 dead_tmp(tmp);
3758 dead_tmp(rd);
3762 static struct {
3763 int nregs;
3764 int interleave;
3765 int spacing;
3766 } neon_ls_element_type[11] = {
3767 {4, 4, 1},
3768 {4, 4, 2},
3769 {4, 1, 1},
3770 {4, 2, 1},
3771 {3, 3, 1},
3772 {3, 3, 2},
3773 {3, 1, 1},
3774 {1, 1, 1},
3775 {2, 2, 1},
3776 {2, 2, 2},
3777 {2, 1, 1}
3780 /* Translate a NEON load/store element instruction. Return nonzero if the
3781 instruction is invalid. */
3782 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3784 int rd, rn, rm;
3785 int op;
3786 int nregs;
3787 int interleave;
3788 int spacing;
3789 int stride;
3790 int size;
3791 int reg;
3792 int pass;
3793 int load;
3794 int shift;
3795 int n;
3796 TCGv addr;
3797 TCGv tmp;
3798 TCGv tmp2;
3799 TCGv_i64 tmp64;
3801 if (!vfp_enabled(env))
3802 return 1;
3803 VFP_DREG_D(rd, insn);
3804 rn = (insn >> 16) & 0xf;
3805 rm = insn & 0xf;
3806 load = (insn & (1 << 21)) != 0;
3807 addr = new_tmp();
3808 if ((insn & (1 << 23)) == 0) {
3809 /* Load store all elements. */
3810 op = (insn >> 8) & 0xf;
3811 size = (insn >> 6) & 3;
3812 if (op > 10)
3813 return 1;
3814 nregs = neon_ls_element_type[op].nregs;
3815 interleave = neon_ls_element_type[op].interleave;
3816 spacing = neon_ls_element_type[op].spacing;
3817 if (size == 3 && (interleave | spacing) != 1)
3818 return 1;
3819 load_reg_var(s, addr, rn);
3820 stride = (1 << size) * interleave;
3821 for (reg = 0; reg < nregs; reg++) {
3822 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3823 load_reg_var(s, addr, rn);
3824 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3825 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3826 load_reg_var(s, addr, rn);
3827 tcg_gen_addi_i32(addr, addr, 1 << size);
3829 if (size == 3) {
3830 if (load) {
3831 tmp64 = gen_ld64(addr, IS_USER(s));
3832 neon_store_reg64(tmp64, rd);
3833 tcg_temp_free_i64(tmp64);
3834 } else {
3835 tmp64 = tcg_temp_new_i64();
3836 neon_load_reg64(tmp64, rd);
3837 gen_st64(tmp64, addr, IS_USER(s));
3839 tcg_gen_addi_i32(addr, addr, stride);
3840 } else {
3841 for (pass = 0; pass < 2; pass++) {
3842 if (size == 2) {
3843 if (load) {
3844 tmp = gen_ld32(addr, IS_USER(s));
3845 neon_store_reg(rd, pass, tmp);
3846 } else {
3847 tmp = neon_load_reg(rd, pass);
3848 gen_st32(tmp, addr, IS_USER(s));
3850 tcg_gen_addi_i32(addr, addr, stride);
3851 } else if (size == 1) {
3852 if (load) {
3853 tmp = gen_ld16u(addr, IS_USER(s));
3854 tcg_gen_addi_i32(addr, addr, stride);
3855 tmp2 = gen_ld16u(addr, IS_USER(s));
3856 tcg_gen_addi_i32(addr, addr, stride);
3857 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3858 dead_tmp(tmp2);
3859 neon_store_reg(rd, pass, tmp);
3860 } else {
3861 tmp = neon_load_reg(rd, pass);
3862 tmp2 = new_tmp();
3863 tcg_gen_shri_i32(tmp2, tmp, 16);
3864 gen_st16(tmp, addr, IS_USER(s));
3865 tcg_gen_addi_i32(addr, addr, stride);
3866 gen_st16(tmp2, addr, IS_USER(s));
3867 tcg_gen_addi_i32(addr, addr, stride);
3869 } else /* size == 0 */ {
3870 if (load) {
3871 TCGV_UNUSED(tmp2);
3872 for (n = 0; n < 4; n++) {
3873 tmp = gen_ld8u(addr, IS_USER(s));
3874 tcg_gen_addi_i32(addr, addr, stride);
3875 if (n == 0) {
3876 tmp2 = tmp;
3877 } else {
3878 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3879 dead_tmp(tmp);
3882 neon_store_reg(rd, pass, tmp2);
3883 } else {
3884 tmp2 = neon_load_reg(rd, pass);
3885 for (n = 0; n < 4; n++) {
3886 tmp = new_tmp();
3887 if (n == 0) {
3888 tcg_gen_mov_i32(tmp, tmp2);
3889 } else {
3890 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3892 gen_st8(tmp, addr, IS_USER(s));
3893 tcg_gen_addi_i32(addr, addr, stride);
3895 dead_tmp(tmp2);
3900 rd += spacing;
3902 stride = nregs * 8;
3903 } else {
3904 size = (insn >> 10) & 3;
3905 if (size == 3) {
3906 /* Load single element to all lanes. */
3907 if (!load)
3908 return 1;
3909 size = (insn >> 6) & 3;
3910 nregs = ((insn >> 8) & 3) + 1;
3911 stride = (insn & (1 << 5)) ? 2 : 1;
3912 load_reg_var(s, addr, rn);
3913 for (reg = 0; reg < nregs; reg++) {
3914 switch (size) {
3915 case 0:
3916 tmp = gen_ld8u(addr, IS_USER(s));
3917 gen_neon_dup_u8(tmp, 0);
3918 break;
3919 case 1:
3920 tmp = gen_ld16u(addr, IS_USER(s));
3921 gen_neon_dup_low16(tmp);
3922 break;
3923 case 2:
3924 tmp = gen_ld32(addr, IS_USER(s));
3925 break;
3926 case 3:
3927 return 1;
3928 default: /* Avoid compiler warnings. */
3929 abort();
3931 tcg_gen_addi_i32(addr, addr, 1 << size);
3932 tmp2 = new_tmp();
3933 tcg_gen_mov_i32(tmp2, tmp);
3934 neon_store_reg(rd, 0, tmp2);
3935 neon_store_reg(rd, 1, tmp);
3936 rd += stride;
3938 stride = (1 << size) * nregs;
3939 } else {
3940 /* Single element. */
3941 pass = (insn >> 7) & 1;
3942 switch (size) {
3943 case 0:
3944 shift = ((insn >> 5) & 3) * 8;
3945 stride = 1;
3946 break;
3947 case 1:
3948 shift = ((insn >> 6) & 1) * 16;
3949 stride = (insn & (1 << 5)) ? 2 : 1;
3950 break;
3951 case 2:
3952 shift = 0;
3953 stride = (insn & (1 << 6)) ? 2 : 1;
3954 break;
3955 default:
3956 abort();
3958 nregs = ((insn >> 8) & 3) + 1;
3959 load_reg_var(s, addr, rn);
3960 for (reg = 0; reg < nregs; reg++) {
3961 if (load) {
3962 switch (size) {
3963 case 0:
3964 tmp = gen_ld8u(addr, IS_USER(s));
3965 break;
3966 case 1:
3967 tmp = gen_ld16u(addr, IS_USER(s));
3968 break;
3969 case 2:
3970 tmp = gen_ld32(addr, IS_USER(s));
3971 break;
3972 default: /* Avoid compiler warnings. */
3973 abort();
3975 if (size != 2) {
3976 tmp2 = neon_load_reg(rd, pass);
3977 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3978 dead_tmp(tmp2);
3980 neon_store_reg(rd, pass, tmp);
3981 } else { /* Store */
3982 tmp = neon_load_reg(rd, pass);
3983 if (shift)
3984 tcg_gen_shri_i32(tmp, tmp, shift);
3985 switch (size) {
3986 case 0:
3987 gen_st8(tmp, addr, IS_USER(s));
3988 break;
3989 case 1:
3990 gen_st16(tmp, addr, IS_USER(s));
3991 break;
3992 case 2:
3993 gen_st32(tmp, addr, IS_USER(s));
3994 break;
3997 rd += stride;
3998 tcg_gen_addi_i32(addr, addr, 1 << size);
4000 stride = nregs * (1 << size);
4003 dead_tmp(addr);
4004 if (rm != 15) {
4005 TCGv base;
4007 base = load_reg(s, rn);
4008 if (rm == 13) {
4009 tcg_gen_addi_i32(base, base, stride);
4010 } else {
4011 TCGv index;
4012 index = load_reg(s, rm);
4013 tcg_gen_add_i32(base, base, index);
4014 dead_tmp(index);
4016 store_reg(s, rn, base);
4018 return 0;
4021 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4022 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4024 tcg_gen_and_i32(t, t, c);
4025 tcg_gen_andc_i32(f, f, c);
4026 tcg_gen_or_i32(dest, t, f);
4029 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4031 switch (size) {
4032 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4033 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4034 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4035 default: abort();
4039 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4041 switch (size) {
4042 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4043 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4044 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4045 default: abort();
4049 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4051 switch (size) {
4052 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4053 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4054 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4055 default: abort();
4059 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4060 int q, int u)
4062 if (q) {
4063 if (u) {
4064 switch (size) {
4065 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4066 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4067 default: abort();
4069 } else {
4070 switch (size) {
4071 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4072 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4073 default: abort();
4076 } else {
4077 if (u) {
4078 switch (size) {
4079 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4080 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4081 default: abort();
4083 } else {
4084 switch (size) {
4085 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4086 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4087 default: abort();
4093 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4095 if (u) {
4096 switch (size) {
4097 case 0: gen_helper_neon_widen_u8(dest, src); break;
4098 case 1: gen_helper_neon_widen_u16(dest, src); break;
4099 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4100 default: abort();
4102 } else {
4103 switch (size) {
4104 case 0: gen_helper_neon_widen_s8(dest, src); break;
4105 case 1: gen_helper_neon_widen_s16(dest, src); break;
4106 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4107 default: abort();
4110 dead_tmp(src);
4113 static inline void gen_neon_addl(int size)
4115 switch (size) {
4116 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4117 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4118 case 2: tcg_gen_add_i64(CPU_V001); break;
4119 default: abort();
4123 static inline void gen_neon_subl(int size)
4125 switch (size) {
4126 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4127 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4128 case 2: tcg_gen_sub_i64(CPU_V001); break;
4129 default: abort();
4133 static inline void gen_neon_negl(TCGv_i64 var, int size)
4135 switch (size) {
4136 case 0: gen_helper_neon_negl_u16(var, var); break;
4137 case 1: gen_helper_neon_negl_u32(var, var); break;
4138 case 2: gen_helper_neon_negl_u64(var, var); break;
4139 default: abort();
4143 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4145 switch (size) {
4146 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4147 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4148 default: abort();
4152 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4154 TCGv_i64 tmp;
4156 switch ((size << 1) | u) {
4157 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4158 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4159 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4160 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4161 case 4:
4162 tmp = gen_muls_i64_i32(a, b);
4163 tcg_gen_mov_i64(dest, tmp);
4164 break;
4165 case 5:
4166 tmp = gen_mulu_i64_i32(a, b);
4167 tcg_gen_mov_i64(dest, tmp);
4168 break;
4169 default: abort();
4173 /* Translate a NEON data processing instruction. Return nonzero if the
4174 instruction is invalid.
4175 We process data in a mixture of 32-bit and 64-bit chunks.
4176 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4178 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4180 int op;
4181 int q;
4182 int rd, rn, rm;
4183 int size;
4184 int shift;
4185 int pass;
4186 int count;
4187 int pairwise;
4188 int u;
4189 int n;
4190 uint32_t imm, mask;
4191 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4192 TCGv_i64 tmp64;
4194 if (!vfp_enabled(env))
4195 return 1;
4196 q = (insn & (1 << 6)) != 0;
4197 u = (insn >> 24) & 1;
4198 VFP_DREG_D(rd, insn);
4199 VFP_DREG_N(rn, insn);
4200 VFP_DREG_M(rm, insn);
4201 size = (insn >> 20) & 3;
4202 if ((insn & (1 << 23)) == 0) {
4203 /* Three register same length. */
4204 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4205 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4206 || op == 10 || op == 11 || op == 16)) {
4207 /* 64-bit element instructions. */
4208 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4209 neon_load_reg64(cpu_V0, rn + pass);
4210 neon_load_reg64(cpu_V1, rm + pass);
4211 switch (op) {
4212 case 1: /* VQADD */
4213 if (u) {
4214 gen_helper_neon_add_saturate_u64(CPU_V001);
4215 } else {
4216 gen_helper_neon_add_saturate_s64(CPU_V001);
4218 break;
4219 case 5: /* VQSUB */
4220 if (u) {
4221 gen_helper_neon_sub_saturate_u64(CPU_V001);
4222 } else {
4223 gen_helper_neon_sub_saturate_s64(CPU_V001);
4225 break;
4226 case 8: /* VSHL */
4227 if (u) {
4228 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4229 } else {
4230 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4232 break;
4233 case 9: /* VQSHL */
4234 if (u) {
4235 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4236 cpu_V0, cpu_V0);
4237 } else {
4238 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4239 cpu_V1, cpu_V0);
4241 break;
4242 case 10: /* VRSHL */
4243 if (u) {
4244 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4245 } else {
4246 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4248 break;
4249 case 11: /* VQRSHL */
4250 if (u) {
4251 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4252 cpu_V1, cpu_V0);
4253 } else {
4254 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4255 cpu_V1, cpu_V0);
4257 break;
4258 case 16:
4259 if (u) {
4260 tcg_gen_sub_i64(CPU_V001);
4261 } else {
4262 tcg_gen_add_i64(CPU_V001);
4264 break;
4265 default:
4266 abort();
4268 neon_store_reg64(cpu_V0, rd + pass);
4270 return 0;
4272 switch (op) {
4273 case 8: /* VSHL */
4274 case 9: /* VQSHL */
4275 case 10: /* VRSHL */
4276 case 11: /* VQRSHL */
4278 int rtmp;
4279 /* Shift instruction operands are reversed. */
4280 rtmp = rn;
4281 rn = rm;
4282 rm = rtmp;
4283 pairwise = 0;
4285 break;
4286 case 20: /* VPMAX */
4287 case 21: /* VPMIN */
4288 case 23: /* VPADD */
4289 pairwise = 1;
4290 break;
4291 case 26: /* VPADD (float) */
4292 pairwise = (u && size < 2);
4293 break;
4294 case 30: /* VPMIN/VPMAX (float) */
4295 pairwise = u;
4296 break;
4297 default:
4298 pairwise = 0;
4299 break;
4302 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4304 if (pairwise) {
4305 /* Pairwise. */
4306 if (q)
4307 n = (pass & 1) * 2;
4308 else
4309 n = 0;
4310 if (pass < q + 1) {
4311 tmp = neon_load_reg(rn, n);
4312 tmp2 = neon_load_reg(rn, n + 1);
4313 } else {
4314 tmp = neon_load_reg(rm, n);
4315 tmp2 = neon_load_reg(rm, n + 1);
4317 } else {
4318 /* Elementwise. */
4319 tmp = neon_load_reg(rn, pass);
4320 tmp2 = neon_load_reg(rm, pass);
4322 switch (op) {
4323 case 0: /* VHADD */
4324 GEN_NEON_INTEGER_OP(hadd);
4325 break;
4326 case 1: /* VQADD */
4327 GEN_NEON_INTEGER_OP_ENV(qadd);
4328 break;
4329 case 2: /* VRHADD */
4330 GEN_NEON_INTEGER_OP(rhadd);
4331 break;
4332 case 3: /* Logic ops. */
4333 switch ((u << 2) | size) {
4334 case 0: /* VAND */
4335 tcg_gen_and_i32(tmp, tmp, tmp2);
4336 break;
4337 case 1: /* BIC */
4338 tcg_gen_andc_i32(tmp, tmp, tmp2);
4339 break;
4340 case 2: /* VORR */
4341 tcg_gen_or_i32(tmp, tmp, tmp2);
4342 break;
4343 case 3: /* VORN */
4344 tcg_gen_orc_i32(tmp, tmp, tmp2);
4345 break;
4346 case 4: /* VEOR */
4347 tcg_gen_xor_i32(tmp, tmp, tmp2);
4348 break;
4349 case 5: /* VBSL */
4350 tmp3 = neon_load_reg(rd, pass);
4351 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4352 dead_tmp(tmp3);
4353 break;
4354 case 6: /* VBIT */
4355 tmp3 = neon_load_reg(rd, pass);
4356 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4357 dead_tmp(tmp3);
4358 break;
4359 case 7: /* VBIF */
4360 tmp3 = neon_load_reg(rd, pass);
4361 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4362 dead_tmp(tmp3);
4363 break;
4365 break;
4366 case 4: /* VHSUB */
4367 GEN_NEON_INTEGER_OP(hsub);
4368 break;
4369 case 5: /* VQSUB */
4370 GEN_NEON_INTEGER_OP_ENV(qsub);
4371 break;
4372 case 6: /* VCGT */
4373 GEN_NEON_INTEGER_OP(cgt);
4374 break;
4375 case 7: /* VCGE */
4376 GEN_NEON_INTEGER_OP(cge);
4377 break;
4378 case 8: /* VSHL */
4379 GEN_NEON_INTEGER_OP(shl);
4380 break;
4381 case 9: /* VQSHL */
4382 GEN_NEON_INTEGER_OP_ENV(qshl);
4383 break;
4384 case 10: /* VRSHL */
4385 GEN_NEON_INTEGER_OP(rshl);
4386 break;
4387 case 11: /* VQRSHL */
4388 GEN_NEON_INTEGER_OP_ENV(qrshl);
4389 break;
4390 case 12: /* VMAX */
4391 GEN_NEON_INTEGER_OP(max);
4392 break;
4393 case 13: /* VMIN */
4394 GEN_NEON_INTEGER_OP(min);
4395 break;
4396 case 14: /* VABD */
4397 GEN_NEON_INTEGER_OP(abd);
4398 break;
4399 case 15: /* VABA */
4400 GEN_NEON_INTEGER_OP(abd);
4401 dead_tmp(tmp2);
4402 tmp2 = neon_load_reg(rd, pass);
4403 gen_neon_add(size, tmp, tmp2);
4404 break;
4405 case 16:
4406 if (!u) { /* VADD */
4407 if (gen_neon_add(size, tmp, tmp2))
4408 return 1;
4409 } else { /* VSUB */
4410 switch (size) {
4411 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4412 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4413 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4414 default: return 1;
4417 break;
4418 case 17:
4419 if (!u) { /* VTST */
4420 switch (size) {
4421 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4422 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4423 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4424 default: return 1;
4426 } else { /* VCEQ */
4427 switch (size) {
4428 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4429 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4430 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4431 default: return 1;
4434 break;
4435 case 18: /* Multiply. */
4436 switch (size) {
4437 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4438 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4439 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4440 default: return 1;
4442 dead_tmp(tmp2);
4443 tmp2 = neon_load_reg(rd, pass);
4444 if (u) { /* VMLS */
4445 gen_neon_rsb(size, tmp, tmp2);
4446 } else { /* VMLA */
4447 gen_neon_add(size, tmp, tmp2);
4449 break;
4450 case 19: /* VMUL */
4451 if (u) { /* polynomial */
4452 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4453 } else { /* Integer */
4454 switch (size) {
4455 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4456 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4457 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4458 default: return 1;
4461 break;
4462 case 20: /* VPMAX */
4463 GEN_NEON_INTEGER_OP(pmax);
4464 break;
4465 case 21: /* VPMIN */
4466 GEN_NEON_INTEGER_OP(pmin);
4467 break;
4468 case 22: /* Hultiply high. */
4469 if (!u) { /* VQDMULH */
4470 switch (size) {
4471 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4472 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4473 default: return 1;
4475 } else { /* VQRDHMUL */
4476 switch (size) {
4477 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4478 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4479 default: return 1;
4482 break;
4483 case 23: /* VPADD */
4484 if (u)
4485 return 1;
4486 switch (size) {
4487 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4488 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4489 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4490 default: return 1;
4492 break;
4493 case 26: /* Floating point arithnetic. */
4494 switch ((u << 2) | size) {
4495 case 0: /* VADD */
4496 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4497 break;
4498 case 2: /* VSUB */
4499 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4500 break;
4501 case 4: /* VPADD */
4502 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4503 break;
4504 case 6: /* VABD */
4505 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4506 break;
4507 default:
4508 return 1;
4510 break;
4511 case 27: /* Float multiply. */
4512 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4513 if (!u) {
4514 dead_tmp(tmp2);
4515 tmp2 = neon_load_reg(rd, pass);
4516 if (size == 0) {
4517 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4518 } else {
4519 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4522 break;
4523 case 28: /* Float compare. */
4524 if (!u) {
4525 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4526 } else {
4527 if (size == 0)
4528 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4529 else
4530 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4532 break;
4533 case 29: /* Float compare absolute. */
4534 if (!u)
4535 return 1;
4536 if (size == 0)
4537 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4538 else
4539 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4540 break;
4541 case 30: /* Float min/max. */
4542 if (size == 0)
4543 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4544 else
4545 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4546 break;
4547 case 31:
4548 if (size == 0)
4549 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4550 else
4551 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4552 break;
4553 default:
4554 abort();
4556 dead_tmp(tmp2);
4558 /* Save the result. For elementwise operations we can put it
4559 straight into the destination register. For pairwise operations
4560 we have to be careful to avoid clobbering the source operands. */
4561 if (pairwise && rd == rm) {
4562 neon_store_scratch(pass, tmp);
4563 } else {
4564 neon_store_reg(rd, pass, tmp);
4567 } /* for pass */
4568 if (pairwise && rd == rm) {
4569 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4570 tmp = neon_load_scratch(pass);
4571 neon_store_reg(rd, pass, tmp);
4574 /* End of 3 register same size operations. */
4575 } else if (insn & (1 << 4)) {
4576 if ((insn & 0x00380080) != 0) {
4577 /* Two registers and shift. */
4578 op = (insn >> 8) & 0xf;
4579 if (insn & (1 << 7)) {
4580 /* 64-bit shift. */
4581 size = 3;
4582 } else {
4583 size = 2;
4584 while ((insn & (1 << (size + 19))) == 0)
4585 size--;
4587 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4588 /* To avoid excessive dumplication of ops we implement shift
4589 by immediate using the variable shift operations. */
4590 if (op < 8) {
4591 /* Shift by immediate:
4592 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4593 /* Right shifts are encoded as N - shift, where N is the
4594 element size in bits. */
4595 if (op <= 4)
4596 shift = shift - (1 << (size + 3));
4597 if (size == 3) {
4598 count = q + 1;
4599 } else {
4600 count = q ? 4: 2;
4602 switch (size) {
4603 case 0:
4604 imm = (uint8_t) shift;
4605 imm |= imm << 8;
4606 imm |= imm << 16;
4607 break;
4608 case 1:
4609 imm = (uint16_t) shift;
4610 imm |= imm << 16;
4611 break;
4612 case 2:
4613 case 3:
4614 imm = shift;
4615 break;
4616 default:
4617 abort();
4620 for (pass = 0; pass < count; pass++) {
4621 if (size == 3) {
4622 neon_load_reg64(cpu_V0, rm + pass);
4623 tcg_gen_movi_i64(cpu_V1, imm);
4624 switch (op) {
4625 case 0: /* VSHR */
4626 case 1: /* VSRA */
4627 if (u)
4628 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4629 else
4630 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4631 break;
4632 case 2: /* VRSHR */
4633 case 3: /* VRSRA */
4634 if (u)
4635 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4636 else
4637 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4638 break;
4639 case 4: /* VSRI */
4640 if (!u)
4641 return 1;
4642 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4643 break;
4644 case 5: /* VSHL, VSLI */
4645 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4646 break;
4647 case 6: /* VQSHL */
4648 if (u)
4649 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4650 else
4651 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4652 break;
4653 case 7: /* VQSHLU */
4654 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4655 break;
4657 if (op == 1 || op == 3) {
4658 /* Accumulate. */
4659 neon_load_reg64(cpu_V0, rd + pass);
4660 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4661 } else if (op == 4 || (op == 5 && u)) {
4662 /* Insert */
4663 cpu_abort(env, "VS[LR]I.64 not implemented");
4665 neon_store_reg64(cpu_V0, rd + pass);
4666 } else { /* size < 3 */
4667 /* Operands in T0 and T1. */
4668 tmp = neon_load_reg(rm, pass);
4669 tmp2 = new_tmp();
4670 tcg_gen_movi_i32(tmp2, imm);
4671 switch (op) {
4672 case 0: /* VSHR */
4673 case 1: /* VSRA */
4674 GEN_NEON_INTEGER_OP(shl);
4675 break;
4676 case 2: /* VRSHR */
4677 case 3: /* VRSRA */
4678 GEN_NEON_INTEGER_OP(rshl);
4679 break;
4680 case 4: /* VSRI */
4681 if (!u)
4682 return 1;
4683 GEN_NEON_INTEGER_OP(shl);
4684 break;
4685 case 5: /* VSHL, VSLI */
4686 switch (size) {
4687 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4688 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4689 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4690 default: return 1;
4692 break;
4693 case 6: /* VQSHL */
4694 GEN_NEON_INTEGER_OP_ENV(qshl);
4695 break;
4696 case 7: /* VQSHLU */
4697 switch (size) {
4698 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4699 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4700 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4701 default: return 1;
4703 break;
4705 dead_tmp(tmp2);
4707 if (op == 1 || op == 3) {
4708 /* Accumulate. */
4709 tmp2 = neon_load_reg(rd, pass);
4710 gen_neon_add(size, tmp2, tmp);
4711 dead_tmp(tmp2);
4712 } else if (op == 4 || (op == 5 && u)) {
4713 /* Insert */
4714 switch (size) {
4715 case 0:
4716 if (op == 4)
4717 mask = 0xff >> -shift;
4718 else
4719 mask = (uint8_t)(0xff << shift);
4720 mask |= mask << 8;
4721 mask |= mask << 16;
4722 break;
4723 case 1:
4724 if (op == 4)
4725 mask = 0xffff >> -shift;
4726 else
4727 mask = (uint16_t)(0xffff << shift);
4728 mask |= mask << 16;
4729 break;
4730 case 2:
4731 if (shift < -31 || shift > 31) {
4732 mask = 0;
4733 } else {
4734 if (op == 4)
4735 mask = 0xffffffffu >> -shift;
4736 else
4737 mask = 0xffffffffu << shift;
4739 break;
4740 default:
4741 abort();
4743 tmp2 = neon_load_reg(rd, pass);
4744 tcg_gen_andi_i32(tmp, tmp, mask);
4745 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4746 tcg_gen_or_i32(tmp, tmp, tmp2);
4747 dead_tmp(tmp2);
4749 neon_store_reg(rd, pass, tmp);
4751 } /* for pass */
4752 } else if (op < 10) {
4753 /* Shift by immediate and narrow:
4754 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4755 shift = shift - (1 << (size + 3));
4756 size++;
4757 switch (size) {
4758 case 1:
4759 imm = (uint16_t)shift;
4760 imm |= imm << 16;
4761 tmp2 = tcg_const_i32(imm);
4762 TCGV_UNUSED_I64(tmp64);
4763 break;
4764 case 2:
4765 imm = (uint32_t)shift;
4766 tmp2 = tcg_const_i32(imm);
4767 TCGV_UNUSED_I64(tmp64);
4768 break;
4769 case 3:
4770 tmp64 = tcg_const_i64(shift);
4771 TCGV_UNUSED(tmp2);
4772 break;
4773 default:
4774 abort();
4777 for (pass = 0; pass < 2; pass++) {
4778 if (size == 3) {
4779 neon_load_reg64(cpu_V0, rm + pass);
4780 if (q) {
4781 if (u)
4782 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4783 else
4784 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4785 } else {
4786 if (u)
4787 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4788 else
4789 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4791 } else {
4792 tmp = neon_load_reg(rm + pass, 0);
4793 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4794 tmp3 = neon_load_reg(rm + pass, 1);
4795 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4796 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4797 dead_tmp(tmp);
4798 dead_tmp(tmp3);
4800 tmp = new_tmp();
4801 if (op == 8 && !u) {
4802 gen_neon_narrow(size - 1, tmp, cpu_V0);
4803 } else {
4804 if (op == 8)
4805 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4806 else
4807 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4809 neon_store_reg(rd, pass, tmp);
4810 } /* for pass */
4811 if (size == 3) {
4812 tcg_temp_free_i64(tmp64);
4813 } else {
4814 dead_tmp(tmp2);
4816 } else if (op == 10) {
4817 /* VSHLL */
4818 if (q || size == 3)
4819 return 1;
4820 tmp = neon_load_reg(rm, 0);
4821 tmp2 = neon_load_reg(rm, 1);
4822 for (pass = 0; pass < 2; pass++) {
4823 if (pass == 1)
4824 tmp = tmp2;
4826 gen_neon_widen(cpu_V0, tmp, size, u);
4828 if (shift != 0) {
4829 /* The shift is less than the width of the source
4830 type, so we can just shift the whole register. */
4831 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4832 if (size < 2 || !u) {
4833 uint64_t imm64;
4834 if (size == 0) {
4835 imm = (0xffu >> (8 - shift));
4836 imm |= imm << 16;
4837 } else {
4838 imm = 0xffff >> (16 - shift);
4840 imm64 = imm | (((uint64_t)imm) << 32);
4841 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4844 neon_store_reg64(cpu_V0, rd + pass);
4846 } else if (op == 15 || op == 16) {
4847 /* VCVT fixed-point. */
4848 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4849 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4850 if (op & 1) {
4851 if (u)
4852 gen_vfp_ulto(0, shift);
4853 else
4854 gen_vfp_slto(0, shift);
4855 } else {
4856 if (u)
4857 gen_vfp_toul(0, shift);
4858 else
4859 gen_vfp_tosl(0, shift);
4861 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4863 } else {
4864 return 1;
4866 } else { /* (insn & 0x00380080) == 0 */
4867 int invert;
4869 op = (insn >> 8) & 0xf;
4870 /* One register and immediate. */
4871 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4872 invert = (insn & (1 << 5)) != 0;
4873 switch (op) {
4874 case 0: case 1:
4875 /* no-op */
4876 break;
4877 case 2: case 3:
4878 imm <<= 8;
4879 break;
4880 case 4: case 5:
4881 imm <<= 16;
4882 break;
4883 case 6: case 7:
4884 imm <<= 24;
4885 break;
4886 case 8: case 9:
4887 imm |= imm << 16;
4888 break;
4889 case 10: case 11:
4890 imm = (imm << 8) | (imm << 24);
4891 break;
4892 case 12:
4893 imm = (imm << 8) | 0xff;
4894 break;
4895 case 13:
4896 imm = (imm << 16) | 0xffff;
4897 break;
4898 case 14:
4899 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4900 if (invert)
4901 imm = ~imm;
4902 break;
4903 case 15:
4904 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4905 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4906 break;
4908 if (invert)
4909 imm = ~imm;
4911 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4912 if (op & 1 && op < 12) {
4913 tmp = neon_load_reg(rd, pass);
4914 if (invert) {
4915 /* The immediate value has already been inverted, so
4916 BIC becomes AND. */
4917 tcg_gen_andi_i32(tmp, tmp, imm);
4918 } else {
4919 tcg_gen_ori_i32(tmp, tmp, imm);
4921 } else {
4922 /* VMOV, VMVN. */
4923 tmp = new_tmp();
4924 if (op == 14 && invert) {
4925 uint32_t val;
4926 val = 0;
4927 for (n = 0; n < 4; n++) {
4928 if (imm & (1 << (n + (pass & 1) * 4)))
4929 val |= 0xff << (n * 8);
4931 tcg_gen_movi_i32(tmp, val);
4932 } else {
4933 tcg_gen_movi_i32(tmp, imm);
4936 neon_store_reg(rd, pass, tmp);
4939 } else { /* (insn & 0x00800010 == 0x00800000) */
4940 if (size != 3) {
4941 op = (insn >> 8) & 0xf;
4942 if ((insn & (1 << 6)) == 0) {
4943 /* Three registers of different lengths. */
4944 int src1_wide;
4945 int src2_wide;
4946 int prewiden;
4947 /* prewiden, src1_wide, src2_wide */
4948 static const int neon_3reg_wide[16][3] = {
4949 {1, 0, 0}, /* VADDL */
4950 {1, 1, 0}, /* VADDW */
4951 {1, 0, 0}, /* VSUBL */
4952 {1, 1, 0}, /* VSUBW */
4953 {0, 1, 1}, /* VADDHN */
4954 {0, 0, 0}, /* VABAL */
4955 {0, 1, 1}, /* VSUBHN */
4956 {0, 0, 0}, /* VABDL */
4957 {0, 0, 0}, /* VMLAL */
4958 {0, 0, 0}, /* VQDMLAL */
4959 {0, 0, 0}, /* VMLSL */
4960 {0, 0, 0}, /* VQDMLSL */
4961 {0, 0, 0}, /* Integer VMULL */
4962 {0, 0, 0}, /* VQDMULL */
4963 {0, 0, 0} /* Polynomial VMULL */
4966 prewiden = neon_3reg_wide[op][0];
4967 src1_wide = neon_3reg_wide[op][1];
4968 src2_wide = neon_3reg_wide[op][2];
4970 if (size == 0 && (op == 9 || op == 11 || op == 13))
4971 return 1;
4973 /* Avoid overlapping operands. Wide source operands are
4974 always aligned so will never overlap with wide
4975 destinations in problematic ways. */
4976 if (rd == rm && !src2_wide) {
4977 tmp = neon_load_reg(rm, 1);
4978 neon_store_scratch(2, tmp);
4979 } else if (rd == rn && !src1_wide) {
4980 tmp = neon_load_reg(rn, 1);
4981 neon_store_scratch(2, tmp);
4983 TCGV_UNUSED(tmp3);
4984 for (pass = 0; pass < 2; pass++) {
4985 if (src1_wide) {
4986 neon_load_reg64(cpu_V0, rn + pass);
4987 TCGV_UNUSED(tmp);
4988 } else {
4989 if (pass == 1 && rd == rn) {
4990 tmp = neon_load_scratch(2);
4991 } else {
4992 tmp = neon_load_reg(rn, pass);
4994 if (prewiden) {
4995 gen_neon_widen(cpu_V0, tmp, size, u);
4998 if (src2_wide) {
4999 neon_load_reg64(cpu_V1, rm + pass);
5000 TCGV_UNUSED(tmp2);
5001 } else {
5002 if (pass == 1 && rd == rm) {
5003 tmp2 = neon_load_scratch(2);
5004 } else {
5005 tmp2 = neon_load_reg(rm, pass);
5007 if (prewiden) {
5008 gen_neon_widen(cpu_V1, tmp2, size, u);
5011 switch (op) {
5012 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5013 gen_neon_addl(size);
5014 break;
5015 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5016 gen_neon_subl(size);
5017 break;
5018 case 5: case 7: /* VABAL, VABDL */
5019 switch ((size << 1) | u) {
5020 case 0:
5021 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5022 break;
5023 case 1:
5024 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5025 break;
5026 case 2:
5027 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5028 break;
5029 case 3:
5030 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5031 break;
5032 case 4:
5033 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5034 break;
5035 case 5:
5036 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5037 break;
5038 default: abort();
5040 dead_tmp(tmp2);
5041 dead_tmp(tmp);
5042 break;
5043 case 8: case 9: case 10: case 11: case 12: case 13:
5044 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5045 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5046 dead_tmp(tmp2);
5047 dead_tmp(tmp);
5048 break;
5049 case 14: /* Polynomial VMULL */
5050 cpu_abort(env, "Polynomial VMULL not implemented");
5052 default: /* 15 is RESERVED. */
5053 return 1;
5055 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
5056 /* Accumulate. */
5057 if (op == 10 || op == 11) {
5058 gen_neon_negl(cpu_V0, size);
5061 if (op != 13) {
5062 neon_load_reg64(cpu_V1, rd + pass);
5065 switch (op) {
5066 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5067 gen_neon_addl(size);
5068 break;
5069 case 9: case 11: /* VQDMLAL, VQDMLSL */
5070 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5071 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5072 break;
5073 /* Fall through. */
5074 case 13: /* VQDMULL */
5075 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5076 break;
5077 default:
5078 abort();
5080 neon_store_reg64(cpu_V0, rd + pass);
5081 } else if (op == 4 || op == 6) {
5082 /* Narrowing operation. */
5083 tmp = new_tmp();
5084 if (!u) {
5085 switch (size) {
5086 case 0:
5087 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5088 break;
5089 case 1:
5090 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5091 break;
5092 case 2:
5093 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5094 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5095 break;
5096 default: abort();
5098 } else {
5099 switch (size) {
5100 case 0:
5101 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5102 break;
5103 case 1:
5104 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5105 break;
5106 case 2:
5107 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5108 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5109 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5110 break;
5111 default: abort();
5114 if (pass == 0) {
5115 tmp3 = tmp;
5116 } else {
5117 neon_store_reg(rd, 0, tmp3);
5118 neon_store_reg(rd, 1, tmp);
5120 } else {
5121 /* Write back the result. */
5122 neon_store_reg64(cpu_V0, rd + pass);
5125 } else {
5126 /* Two registers and a scalar. */
5127 switch (op) {
5128 case 0: /* Integer VMLA scalar */
5129 case 1: /* Float VMLA scalar */
5130 case 4: /* Integer VMLS scalar */
5131 case 5: /* Floating point VMLS scalar */
5132 case 8: /* Integer VMUL scalar */
5133 case 9: /* Floating point VMUL scalar */
5134 case 12: /* VQDMULH scalar */
5135 case 13: /* VQRDMULH scalar */
5136 tmp = neon_get_scalar(size, rm);
5137 neon_store_scratch(0, tmp);
5138 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5139 tmp = neon_load_scratch(0);
5140 tmp2 = neon_load_reg(rn, pass);
5141 if (op == 12) {
5142 if (size == 1) {
5143 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5144 } else {
5145 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5147 } else if (op == 13) {
5148 if (size == 1) {
5149 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5150 } else {
5151 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5153 } else if (op & 1) {
5154 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5155 } else {
5156 switch (size) {
5157 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5158 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5159 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5160 default: return 1;
5163 dead_tmp(tmp2);
5164 if (op < 8) {
5165 /* Accumulate. */
5166 tmp2 = neon_load_reg(rd, pass);
5167 switch (op) {
5168 case 0:
5169 gen_neon_add(size, tmp, tmp2);
5170 break;
5171 case 1:
5172 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5173 break;
5174 case 4:
5175 gen_neon_rsb(size, tmp, tmp2);
5176 break;
5177 case 5:
5178 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5179 break;
5180 default:
5181 abort();
5183 dead_tmp(tmp2);
5185 neon_store_reg(rd, pass, tmp);
5187 break;
5188 case 2: /* VMLAL sclar */
5189 case 3: /* VQDMLAL scalar */
5190 case 6: /* VMLSL scalar */
5191 case 7: /* VQDMLSL scalar */
5192 case 10: /* VMULL scalar */
5193 case 11: /* VQDMULL scalar */
5194 if (size == 0 && (op == 3 || op == 7 || op == 11))
5195 return 1;
5197 tmp2 = neon_get_scalar(size, rm);
5198 tmp3 = neon_load_reg(rn, 1);
5200 for (pass = 0; pass < 2; pass++) {
5201 if (pass == 0) {
5202 tmp = neon_load_reg(rn, 0);
5203 } else {
5204 tmp = tmp3;
5206 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5207 dead_tmp(tmp);
5208 if (op == 6 || op == 7) {
5209 gen_neon_negl(cpu_V0, size);
5211 if (op != 11) {
5212 neon_load_reg64(cpu_V1, rd + pass);
5214 switch (op) {
5215 case 2: case 6:
5216 gen_neon_addl(size);
5217 break;
5218 case 3: case 7:
5219 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5220 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5221 break;
5222 case 10:
5223 /* no-op */
5224 break;
5225 case 11:
5226 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5227 break;
5228 default:
5229 abort();
5231 neon_store_reg64(cpu_V0, rd + pass);
5234 dead_tmp(tmp2);
5236 break;
5237 default: /* 14 and 15 are RESERVED */
5238 return 1;
5241 } else { /* size == 3 */
5242 if (!u) {
5243 /* Extract. */
5244 imm = (insn >> 8) & 0xf;
5245 count = q + 1;
5247 if (imm > 7 && !q)
5248 return 1;
5250 if (imm == 0) {
5251 neon_load_reg64(cpu_V0, rn);
5252 if (q) {
5253 neon_load_reg64(cpu_V1, rn + 1);
5255 } else if (imm == 8) {
5256 neon_load_reg64(cpu_V0, rn + 1);
5257 if (q) {
5258 neon_load_reg64(cpu_V1, rm);
5260 } else if (q) {
5261 tmp64 = tcg_temp_new_i64();
5262 if (imm < 8) {
5263 neon_load_reg64(cpu_V0, rn);
5264 neon_load_reg64(tmp64, rn + 1);
5265 } else {
5266 neon_load_reg64(cpu_V0, rn + 1);
5267 neon_load_reg64(tmp64, rm);
5269 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5270 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5271 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5272 if (imm < 8) {
5273 neon_load_reg64(cpu_V1, rm);
5274 } else {
5275 neon_load_reg64(cpu_V1, rm + 1);
5276 imm -= 8;
5278 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5279 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5280 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5281 tcg_temp_free_i64(tmp64);
5282 } else {
5283 /* BUGFIX */
5284 neon_load_reg64(cpu_V0, rn);
5285 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5286 neon_load_reg64(cpu_V1, rm);
5287 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5288 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5290 neon_store_reg64(cpu_V0, rd);
5291 if (q) {
5292 neon_store_reg64(cpu_V1, rd + 1);
5294 } else if ((insn & (1 << 11)) == 0) {
5295 /* Two register misc. */
5296 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5297 size = (insn >> 18) & 3;
5298 switch (op) {
5299 case 0: /* VREV64 */
5300 if (size == 3)
5301 return 1;
5302 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5303 tmp = neon_load_reg(rm, pass * 2);
5304 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5305 switch (size) {
5306 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5307 case 1: gen_swap_half(tmp); break;
5308 case 2: /* no-op */ break;
5309 default: abort();
5311 neon_store_reg(rd, pass * 2 + 1, tmp);
5312 if (size == 2) {
5313 neon_store_reg(rd, pass * 2, tmp2);
5314 } else {
5315 switch (size) {
5316 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5317 case 1: gen_swap_half(tmp2); break;
5318 default: abort();
5320 neon_store_reg(rd, pass * 2, tmp2);
5323 break;
5324 case 4: case 5: /* VPADDL */
5325 case 12: case 13: /* VPADAL */
5326 if (size == 3)
5327 return 1;
5328 for (pass = 0; pass < q + 1; pass++) {
5329 tmp = neon_load_reg(rm, pass * 2);
5330 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5331 tmp = neon_load_reg(rm, pass * 2 + 1);
5332 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5333 switch (size) {
5334 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5335 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5336 case 2: tcg_gen_add_i64(CPU_V001); break;
5337 default: abort();
5339 if (op >= 12) {
5340 /* Accumulate. */
5341 neon_load_reg64(cpu_V1, rd + pass);
5342 gen_neon_addl(size);
5344 neon_store_reg64(cpu_V0, rd + pass);
5346 break;
5347 case 33: /* VTRN */
5348 if (size == 2) {
5349 for (n = 0; n < (q ? 4 : 2); n += 2) {
5350 tmp = neon_load_reg(rm, n);
5351 tmp2 = neon_load_reg(rd, n + 1);
5352 neon_store_reg(rm, n, tmp2);
5353 neon_store_reg(rd, n + 1, tmp);
5355 } else {
5356 goto elementwise;
5358 break;
5359 case 34: /* VUZP */
5360 /* Reg Before After
5361 Rd A3 A2 A1 A0 B2 B0 A2 A0
5362 Rm B3 B2 B1 B0 B3 B1 A3 A1
5364 if (size == 3)
5365 return 1;
5366 gen_neon_unzip(rd, q, 0, size);
5367 gen_neon_unzip(rm, q, 4, size);
5368 if (q) {
5369 static int unzip_order_q[8] =
5370 {0, 2, 4, 6, 1, 3, 5, 7};
5371 for (n = 0; n < 8; n++) {
5372 int reg = (n < 4) ? rd : rm;
5373 tmp = neon_load_scratch(unzip_order_q[n]);
5374 neon_store_reg(reg, n % 4, tmp);
5376 } else {
5377 static int unzip_order[4] =
5378 {0, 4, 1, 5};
5379 for (n = 0; n < 4; n++) {
5380 int reg = (n < 2) ? rd : rm;
5381 tmp = neon_load_scratch(unzip_order[n]);
5382 neon_store_reg(reg, n % 2, tmp);
5385 break;
5386 case 35: /* VZIP */
5387 /* Reg Before After
5388 Rd A3 A2 A1 A0 B1 A1 B0 A0
5389 Rm B3 B2 B1 B0 B3 A3 B2 A2
5391 if (size == 3)
5392 return 1;
5393 count = (q ? 4 : 2);
5394 for (n = 0; n < count; n++) {
5395 tmp = neon_load_reg(rd, n);
5396 tmp2 = neon_load_reg(rd, n);
5397 switch (size) {
5398 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5399 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5400 case 2: /* no-op */; break;
5401 default: abort();
5403 neon_store_scratch(n * 2, tmp);
5404 neon_store_scratch(n * 2 + 1, tmp2);
5406 for (n = 0; n < count * 2; n++) {
5407 int reg = (n < count) ? rd : rm;
5408 tmp = neon_load_scratch(n);
5409 neon_store_reg(reg, n % count, tmp);
5411 break;
5412 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5413 if (size == 3)
5414 return 1;
5415 TCGV_UNUSED(tmp2);
5416 for (pass = 0; pass < 2; pass++) {
5417 neon_load_reg64(cpu_V0, rm + pass);
5418 tmp = new_tmp();
5419 if (op == 36 && q == 0) {
5420 gen_neon_narrow(size, tmp, cpu_V0);
5421 } else if (q) {
5422 gen_neon_narrow_satu(size, tmp, cpu_V0);
5423 } else {
5424 gen_neon_narrow_sats(size, tmp, cpu_V0);
5426 if (pass == 0) {
5427 tmp2 = tmp;
5428 } else {
5429 neon_store_reg(rd, 0, tmp2);
5430 neon_store_reg(rd, 1, tmp);
5433 break;
5434 case 38: /* VSHLL */
5435 if (q || size == 3)
5436 return 1;
5437 tmp = neon_load_reg(rm, 0);
5438 tmp2 = neon_load_reg(rm, 1);
5439 for (pass = 0; pass < 2; pass++) {
5440 if (pass == 1)
5441 tmp = tmp2;
5442 gen_neon_widen(cpu_V0, tmp, size, 1);
5443 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5444 neon_store_reg64(cpu_V0, rd + pass);
5446 break;
5447 case 44: /* VCVT.F16.F32 */
5448 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5449 return 1;
5450 tmp = new_tmp();
5451 tmp2 = new_tmp();
5452 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5453 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5454 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5455 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5456 tcg_gen_shli_i32(tmp2, tmp2, 16);
5457 tcg_gen_or_i32(tmp2, tmp2, tmp);
5458 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5459 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5460 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5461 neon_store_reg(rd, 0, tmp2);
5462 tmp2 = new_tmp();
5463 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5464 tcg_gen_shli_i32(tmp2, tmp2, 16);
5465 tcg_gen_or_i32(tmp2, tmp2, tmp);
5466 neon_store_reg(rd, 1, tmp2);
5467 dead_tmp(tmp);
5468 break;
5469 case 46: /* VCVT.F32.F16 */
5470 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5471 return 1;
5472 tmp3 = new_tmp();
5473 tmp = neon_load_reg(rm, 0);
5474 tmp2 = neon_load_reg(rm, 1);
5475 tcg_gen_ext16u_i32(tmp3, tmp);
5476 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5477 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5478 tcg_gen_shri_i32(tmp3, tmp, 16);
5479 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5480 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5481 dead_tmp(tmp);
5482 tcg_gen_ext16u_i32(tmp3, tmp2);
5483 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5484 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5485 tcg_gen_shri_i32(tmp3, tmp2, 16);
5486 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5487 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5488 dead_tmp(tmp2);
5489 dead_tmp(tmp3);
5490 break;
5491 default:
5492 elementwise:
5493 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5494 if (op == 30 || op == 31 || op >= 58) {
5495 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5496 neon_reg_offset(rm, pass));
5497 TCGV_UNUSED(tmp);
5498 } else {
5499 tmp = neon_load_reg(rm, pass);
5501 switch (op) {
5502 case 1: /* VREV32 */
5503 switch (size) {
5504 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5505 case 1: gen_swap_half(tmp); break;
5506 default: return 1;
5508 break;
5509 case 2: /* VREV16 */
5510 if (size != 0)
5511 return 1;
5512 gen_rev16(tmp);
5513 break;
5514 case 8: /* CLS */
5515 switch (size) {
5516 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5517 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5518 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5519 default: return 1;
5521 break;
5522 case 9: /* CLZ */
5523 switch (size) {
5524 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5525 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5526 case 2: gen_helper_clz(tmp, tmp); break;
5527 default: return 1;
5529 break;
5530 case 10: /* CNT */
5531 if (size != 0)
5532 return 1;
5533 gen_helper_neon_cnt_u8(tmp, tmp);
5534 break;
5535 case 11: /* VNOT */
5536 if (size != 0)
5537 return 1;
5538 tcg_gen_not_i32(tmp, tmp);
5539 break;
5540 case 14: /* VQABS */
5541 switch (size) {
5542 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5543 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5544 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5545 default: return 1;
5547 break;
5548 case 15: /* VQNEG */
5549 switch (size) {
5550 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5551 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5552 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5553 default: return 1;
5555 break;
5556 case 16: case 19: /* VCGT #0, VCLE #0 */
5557 tmp2 = tcg_const_i32(0);
5558 switch(size) {
5559 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5560 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5561 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5562 default: return 1;
5564 tcg_temp_free(tmp2);
5565 if (op == 19)
5566 tcg_gen_not_i32(tmp, tmp);
5567 break;
5568 case 17: case 20: /* VCGE #0, VCLT #0 */
5569 tmp2 = tcg_const_i32(0);
5570 switch(size) {
5571 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5572 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5573 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5574 default: return 1;
5576 tcg_temp_free(tmp2);
5577 if (op == 20)
5578 tcg_gen_not_i32(tmp, tmp);
5579 break;
5580 case 18: /* VCEQ #0 */
5581 tmp2 = tcg_const_i32(0);
5582 switch(size) {
5583 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5584 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5585 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5586 default: return 1;
5588 tcg_temp_free(tmp2);
5589 break;
5590 case 22: /* VABS */
5591 switch(size) {
5592 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5593 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5594 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5595 default: return 1;
5597 break;
5598 case 23: /* VNEG */
5599 if (size == 3)
5600 return 1;
5601 tmp2 = tcg_const_i32(0);
5602 gen_neon_rsb(size, tmp, tmp2);
5603 tcg_temp_free(tmp2);
5604 break;
5605 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5606 tmp2 = tcg_const_i32(0);
5607 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5608 tcg_temp_free(tmp2);
5609 if (op == 27)
5610 tcg_gen_not_i32(tmp, tmp);
5611 break;
5612 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5613 tmp2 = tcg_const_i32(0);
5614 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5615 tcg_temp_free(tmp2);
5616 if (op == 28)
5617 tcg_gen_not_i32(tmp, tmp);
5618 break;
5619 case 26: /* Float VCEQ #0 */
5620 tmp2 = tcg_const_i32(0);
5621 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5622 tcg_temp_free(tmp2);
5623 break;
5624 case 30: /* Float VABS */
5625 gen_vfp_abs(0);
5626 break;
5627 case 31: /* Float VNEG */
5628 gen_vfp_neg(0);
5629 break;
5630 case 32: /* VSWP */
5631 tmp2 = neon_load_reg(rd, pass);
5632 neon_store_reg(rm, pass, tmp2);
5633 break;
5634 case 33: /* VTRN */
5635 tmp2 = neon_load_reg(rd, pass);
5636 switch (size) {
5637 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5638 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5639 case 2: abort();
5640 default: return 1;
5642 neon_store_reg(rm, pass, tmp2);
5643 break;
5644 case 56: /* Integer VRECPE */
5645 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5646 break;
5647 case 57: /* Integer VRSQRTE */
5648 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5649 break;
5650 case 58: /* Float VRECPE */
5651 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5652 break;
5653 case 59: /* Float VRSQRTE */
5654 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5655 break;
5656 case 60: /* VCVT.F32.S32 */
5657 gen_vfp_tosiz(0);
5658 break;
5659 case 61: /* VCVT.F32.U32 */
5660 gen_vfp_touiz(0);
5661 break;
5662 case 62: /* VCVT.S32.F32 */
5663 gen_vfp_sito(0);
5664 break;
5665 case 63: /* VCVT.U32.F32 */
5666 gen_vfp_uito(0);
5667 break;
5668 default:
5669 /* Reserved: 21, 29, 39-56 */
5670 return 1;
5672 if (op == 30 || op == 31 || op >= 58) {
5673 tcg_gen_st_f32(cpu_F0s, cpu_env,
5674 neon_reg_offset(rd, pass));
5675 } else {
5676 neon_store_reg(rd, pass, tmp);
5679 break;
5681 } else if ((insn & (1 << 10)) == 0) {
5682 /* VTBL, VTBX. */
5683 n = ((insn >> 5) & 0x18) + 8;
5684 if (insn & (1 << 6)) {
5685 tmp = neon_load_reg(rd, 0);
5686 } else {
5687 tmp = new_tmp();
5688 tcg_gen_movi_i32(tmp, 0);
5690 tmp2 = neon_load_reg(rm, 0);
5691 tmp4 = tcg_const_i32(rn);
5692 tmp5 = tcg_const_i32(n);
5693 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5694 dead_tmp(tmp);
5695 if (insn & (1 << 6)) {
5696 tmp = neon_load_reg(rd, 1);
5697 } else {
5698 tmp = new_tmp();
5699 tcg_gen_movi_i32(tmp, 0);
5701 tmp3 = neon_load_reg(rm, 1);
5702 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5703 tcg_temp_free_i32(tmp5);
5704 tcg_temp_free_i32(tmp4);
5705 neon_store_reg(rd, 0, tmp2);
5706 neon_store_reg(rd, 1, tmp3);
5707 dead_tmp(tmp);
5708 } else if ((insn & 0x380) == 0) {
5709 /* VDUP */
5710 if (insn & (1 << 19)) {
5711 tmp = neon_load_reg(rm, 1);
5712 } else {
5713 tmp = neon_load_reg(rm, 0);
5715 if (insn & (1 << 16)) {
5716 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5717 } else if (insn & (1 << 17)) {
5718 if ((insn >> 18) & 1)
5719 gen_neon_dup_high16(tmp);
5720 else
5721 gen_neon_dup_low16(tmp);
5723 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5724 tmp2 = new_tmp();
5725 tcg_gen_mov_i32(tmp2, tmp);
5726 neon_store_reg(rd, pass, tmp2);
5728 dead_tmp(tmp);
5729 } else {
5730 return 1;
5734 return 0;
5737 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5739 int crn = (insn >> 16) & 0xf;
5740 int crm = insn & 0xf;
5741 int op1 = (insn >> 21) & 7;
5742 int op2 = (insn >> 5) & 7;
5743 int rt = (insn >> 12) & 0xf;
5744 TCGv tmp;
5746 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5747 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5748 /* TEECR */
5749 if (IS_USER(s))
5750 return 1;
5751 tmp = load_cpu_field(teecr);
5752 store_reg(s, rt, tmp);
5753 return 0;
5755 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5756 /* TEEHBR */
5757 if (IS_USER(s) && (env->teecr & 1))
5758 return 1;
5759 tmp = load_cpu_field(teehbr);
5760 store_reg(s, rt, tmp);
5761 return 0;
5764 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5765 op1, crn, crm, op2);
5766 return 1;
5769 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5771 int crn = (insn >> 16) & 0xf;
5772 int crm = insn & 0xf;
5773 int op1 = (insn >> 21) & 7;
5774 int op2 = (insn >> 5) & 7;
5775 int rt = (insn >> 12) & 0xf;
5776 TCGv tmp;
5778 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5779 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5780 /* TEECR */
5781 if (IS_USER(s))
5782 return 1;
5783 tmp = load_reg(s, rt);
5784 gen_helper_set_teecr(cpu_env, tmp);
5785 dead_tmp(tmp);
5786 return 0;
5788 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5789 /* TEEHBR */
5790 if (IS_USER(s) && (env->teecr & 1))
5791 return 1;
5792 tmp = load_reg(s, rt);
5793 store_cpu_field(tmp, teehbr);
5794 return 0;
5797 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5798 op1, crn, crm, op2);
5799 return 1;
5802 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5804 int cpnum;
5806 cpnum = (insn >> 8) & 0xf;
5807 if (arm_feature(env, ARM_FEATURE_XSCALE)
5808 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5809 return 1;
5811 switch (cpnum) {
5812 case 0:
5813 case 1:
5814 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5815 return disas_iwmmxt_insn(env, s, insn);
5816 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5817 return disas_dsp_insn(env, s, insn);
5819 return 1;
5820 case 10:
5821 case 11:
5822 return disas_vfp_insn (env, s, insn);
5823 case 14:
5824 /* Coprocessors 7-15 are architecturally reserved by ARM.
5825 Unfortunately Intel decided to ignore this. */
5826 if (arm_feature(env, ARM_FEATURE_XSCALE))
5827 goto board;
5828 if (insn & (1 << 20))
5829 return disas_cp14_read(env, s, insn);
5830 else
5831 return disas_cp14_write(env, s, insn);
5832 case 15:
5833 return disas_cp15_insn (env, s, insn);
5834 default:
5835 board:
5836 /* Unknown coprocessor. See if the board has hooked it. */
5837 return disas_cp_insn (env, s, insn);
5842 /* Store a 64-bit value to a register pair. Clobbers val. */
5843 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5845 TCGv tmp;
5846 tmp = new_tmp();
5847 tcg_gen_trunc_i64_i32(tmp, val);
5848 store_reg(s, rlow, tmp);
5849 tmp = new_tmp();
5850 tcg_gen_shri_i64(val, val, 32);
5851 tcg_gen_trunc_i64_i32(tmp, val);
5852 store_reg(s, rhigh, tmp);
5855 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5856 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5858 TCGv_i64 tmp;
5859 TCGv tmp2;
5861 /* Load value and extend to 64 bits. */
5862 tmp = tcg_temp_new_i64();
5863 tmp2 = load_reg(s, rlow);
5864 tcg_gen_extu_i32_i64(tmp, tmp2);
5865 dead_tmp(tmp2);
5866 tcg_gen_add_i64(val, val, tmp);
5867 tcg_temp_free_i64(tmp);
5870 /* load and add a 64-bit value from a register pair. */
5871 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5873 TCGv_i64 tmp;
5874 TCGv tmpl;
5875 TCGv tmph;
5877 /* Load 64-bit value rd:rn. */
5878 tmpl = load_reg(s, rlow);
5879 tmph = load_reg(s, rhigh);
5880 tmp = tcg_temp_new_i64();
5881 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5882 dead_tmp(tmpl);
5883 dead_tmp(tmph);
5884 tcg_gen_add_i64(val, val, tmp);
5885 tcg_temp_free_i64(tmp);
5888 /* Set N and Z flags from a 64-bit value. */
5889 static void gen_logicq_cc(TCGv_i64 val)
5891 TCGv tmp = new_tmp();
5892 gen_helper_logicq_cc(tmp, val);
5893 gen_logic_CC(tmp);
5894 dead_tmp(tmp);
5897 /* Load/Store exclusive instructions are implemented by remembering
5898 the value/address loaded, and seeing if these are the same
5899 when the store is performed. This should be is sufficient to implement
5900 the architecturally mandated semantics, and avoids having to monitor
5901 regular stores.
5903 In system emulation mode only one CPU will be running at once, so
5904 this sequence is effectively atomic. In user emulation mode we
5905 throw an exception and handle the atomic operation elsewhere. */
5906 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
5907 TCGv addr, int size)
5909 TCGv tmp;
5911 switch (size) {
5912 case 0:
5913 tmp = gen_ld8u(addr, IS_USER(s));
5914 break;
5915 case 1:
5916 tmp = gen_ld16u(addr, IS_USER(s));
5917 break;
5918 case 2:
5919 case 3:
5920 tmp = gen_ld32(addr, IS_USER(s));
5921 break;
5922 default:
5923 abort();
5925 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
5926 store_reg(s, rt, tmp);
5927 if (size == 3) {
5928 tcg_gen_addi_i32(addr, addr, 4);
5929 tmp = gen_ld32(addr, IS_USER(s));
5930 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
5931 store_reg(s, rt2, tmp);
5933 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
5936 static void gen_clrex(DisasContext *s)
5938 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
5941 #ifdef CONFIG_USER_ONLY
5942 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5943 TCGv addr, int size)
5945 tcg_gen_mov_i32(cpu_exclusive_test, addr);
5946 tcg_gen_movi_i32(cpu_exclusive_info,
5947 size | (rd << 4) | (rt << 8) | (rt2 << 12));
5948 gen_set_condexec(s);
5949 gen_set_pc_im(s->pc - 4);
5950 gen_exception(EXCP_STREX);
5951 s->is_jmp = DISAS_JUMP;
5953 #else
5954 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5955 TCGv addr, int size)
5957 TCGv tmp;
5958 int done_label;
5959 int fail_label;
5961 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5962 [addr] = {Rt};
5963 {Rd} = 0;
5964 } else {
5965 {Rd} = 1;
5966 } */
5967 fail_label = gen_new_label();
5968 done_label = gen_new_label();
5969 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
5970 switch (size) {
5971 case 0:
5972 tmp = gen_ld8u(addr, IS_USER(s));
5973 break;
5974 case 1:
5975 tmp = gen_ld16u(addr, IS_USER(s));
5976 break;
5977 case 2:
5978 case 3:
5979 tmp = gen_ld32(addr, IS_USER(s));
5980 break;
5981 default:
5982 abort();
5984 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
5985 dead_tmp(tmp);
5986 if (size == 3) {
5987 TCGv tmp2 = new_tmp();
5988 tcg_gen_addi_i32(tmp2, addr, 4);
5989 tmp = gen_ld32(addr, IS_USER(s));
5990 dead_tmp(tmp2);
5991 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
5992 dead_tmp(tmp);
5994 tmp = load_reg(s, rt);
5995 switch (size) {
5996 case 0:
5997 gen_st8(tmp, addr, IS_USER(s));
5998 break;
5999 case 1:
6000 gen_st16(tmp, addr, IS_USER(s));
6001 break;
6002 case 2:
6003 case 3:
6004 gen_st32(tmp, addr, IS_USER(s));
6005 break;
6006 default:
6007 abort();
6009 if (size == 3) {
6010 tcg_gen_addi_i32(addr, addr, 4);
6011 tmp = load_reg(s, rt2);
6012 gen_st32(tmp, addr, IS_USER(s));
6014 tcg_gen_movi_i32(cpu_R[rd], 0);
6015 tcg_gen_br(done_label);
6016 gen_set_label(fail_label);
6017 tcg_gen_movi_i32(cpu_R[rd], 1);
6018 gen_set_label(done_label);
6019 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6021 #endif
6023 static void disas_arm_insn(CPUState * env, DisasContext *s)
6025 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6026 TCGv tmp;
6027 TCGv tmp2;
6028 TCGv tmp3;
6029 TCGv addr;
6030 TCGv_i64 tmp64;
6032 insn = ldl_code(s->pc);
6033 s->pc += 4;
6035 /* M variants do not implement ARM mode. */
6036 if (IS_M(env))
6037 goto illegal_op;
6038 cond = insn >> 28;
6039 if (cond == 0xf){
6040 /* Unconditional instructions. */
6041 if (((insn >> 25) & 7) == 1) {
6042 /* NEON Data processing. */
6043 if (!arm_feature(env, ARM_FEATURE_NEON))
6044 goto illegal_op;
6046 if (disas_neon_data_insn(env, s, insn))
6047 goto illegal_op;
6048 return;
6050 if ((insn & 0x0f100000) == 0x04000000) {
6051 /* NEON load/store. */
6052 if (!arm_feature(env, ARM_FEATURE_NEON))
6053 goto illegal_op;
6055 if (disas_neon_ls_insn(env, s, insn))
6056 goto illegal_op;
6057 return;
6059 if ((insn & 0x0d70f000) == 0x0550f000)
6060 return; /* PLD */
6061 else if ((insn & 0x0ffffdff) == 0x01010000) {
6062 ARCH(6);
6063 /* setend */
6064 if (insn & (1 << 9)) {
6065 /* BE8 mode not implemented. */
6066 goto illegal_op;
6068 return;
6069 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6070 switch ((insn >> 4) & 0xf) {
6071 case 1: /* clrex */
6072 ARCH(6K);
6073 gen_clrex(s);
6074 return;
6075 case 4: /* dsb */
6076 case 5: /* dmb */
6077 case 6: /* isb */
6078 ARCH(7);
6079 /* We don't emulate caches so these are a no-op. */
6080 return;
6081 default:
6082 goto illegal_op;
6084 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6085 /* srs */
6086 int32_t offset;
6087 if (IS_USER(s))
6088 goto illegal_op;
6089 ARCH(6);
6090 op1 = (insn & 0x1f);
6091 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6092 addr = load_reg(s, 13);
6093 } else {
6094 addr = new_tmp();
6095 tmp = tcg_const_i32(op1);
6096 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6097 tcg_temp_free_i32(tmp);
6099 i = (insn >> 23) & 3;
6100 switch (i) {
6101 case 0: offset = -4; break; /* DA */
6102 case 1: offset = 0; break; /* IA */
6103 case 2: offset = -8; break; /* DB */
6104 case 3: offset = 4; break; /* IB */
6105 default: abort();
6107 if (offset)
6108 tcg_gen_addi_i32(addr, addr, offset);
6109 tmp = load_reg(s, 14);
6110 gen_st32(tmp, addr, 0);
6111 tmp = load_cpu_field(spsr);
6112 tcg_gen_addi_i32(addr, addr, 4);
6113 gen_st32(tmp, addr, 0);
6114 if (insn & (1 << 21)) {
6115 /* Base writeback. */
6116 switch (i) {
6117 case 0: offset = -8; break;
6118 case 1: offset = 4; break;
6119 case 2: offset = -4; break;
6120 case 3: offset = 0; break;
6121 default: abort();
6123 if (offset)
6124 tcg_gen_addi_i32(addr, addr, offset);
6125 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6126 store_reg(s, 13, addr);
6127 } else {
6128 tmp = tcg_const_i32(op1);
6129 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6130 tcg_temp_free_i32(tmp);
6131 dead_tmp(addr);
6133 } else {
6134 dead_tmp(addr);
6136 return;
6137 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6138 /* rfe */
6139 int32_t offset;
6140 if (IS_USER(s))
6141 goto illegal_op;
6142 ARCH(6);
6143 rn = (insn >> 16) & 0xf;
6144 addr = load_reg(s, rn);
6145 i = (insn >> 23) & 3;
6146 switch (i) {
6147 case 0: offset = -4; break; /* DA */
6148 case 1: offset = 0; break; /* IA */
6149 case 2: offset = -8; break; /* DB */
6150 case 3: offset = 4; break; /* IB */
6151 default: abort();
6153 if (offset)
6154 tcg_gen_addi_i32(addr, addr, offset);
6155 /* Load PC into tmp and CPSR into tmp2. */
6156 tmp = gen_ld32(addr, 0);
6157 tcg_gen_addi_i32(addr, addr, 4);
6158 tmp2 = gen_ld32(addr, 0);
6159 if (insn & (1 << 21)) {
6160 /* Base writeback. */
6161 switch (i) {
6162 case 0: offset = -8; break;
6163 case 1: offset = 4; break;
6164 case 2: offset = -4; break;
6165 case 3: offset = 0; break;
6166 default: abort();
6168 if (offset)
6169 tcg_gen_addi_i32(addr, addr, offset);
6170 store_reg(s, rn, addr);
6171 } else {
6172 dead_tmp(addr);
6174 gen_rfe(s, tmp, tmp2);
6175 return;
6176 } else if ((insn & 0x0e000000) == 0x0a000000) {
6177 /* branch link and change to thumb (blx <offset>) */
6178 int32_t offset;
6180 val = (uint32_t)s->pc;
6181 tmp = new_tmp();
6182 tcg_gen_movi_i32(tmp, val);
6183 store_reg(s, 14, tmp);
6184 /* Sign-extend the 24-bit offset */
6185 offset = (((int32_t)insn) << 8) >> 8;
6186 /* offset * 4 + bit24 * 2 + (thumb bit) */
6187 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6188 /* pipeline offset */
6189 val += 4;
6190 gen_bx_im(s, val);
6191 return;
6192 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6193 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6194 /* iWMMXt register transfer. */
6195 if (env->cp15.c15_cpar & (1 << 1))
6196 if (!disas_iwmmxt_insn(env, s, insn))
6197 return;
6199 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6200 /* Coprocessor double register transfer. */
6201 } else if ((insn & 0x0f000010) == 0x0e000010) {
6202 /* Additional coprocessor register transfer. */
6203 } else if ((insn & 0x0ff10020) == 0x01000000) {
6204 uint32_t mask;
6205 uint32_t val;
6206 /* cps (privileged) */
6207 if (IS_USER(s))
6208 return;
6209 mask = val = 0;
6210 if (insn & (1 << 19)) {
6211 if (insn & (1 << 8))
6212 mask |= CPSR_A;
6213 if (insn & (1 << 7))
6214 mask |= CPSR_I;
6215 if (insn & (1 << 6))
6216 mask |= CPSR_F;
6217 if (insn & (1 << 18))
6218 val |= mask;
6220 if (insn & (1 << 17)) {
6221 mask |= CPSR_M;
6222 val |= (insn & 0x1f);
6224 if (mask) {
6225 gen_set_psr_im(s, mask, 0, val);
6227 return;
6229 goto illegal_op;
6231 if (cond != 0xe) {
6232 /* if not always execute, we generate a conditional jump to
6233 next instruction */
6234 s->condlabel = gen_new_label();
6235 gen_test_cc(cond ^ 1, s->condlabel);
6236 s->condjmp = 1;
6238 if ((insn & 0x0f900000) == 0x03000000) {
6239 if ((insn & (1 << 21)) == 0) {
6240 ARCH(6T2);
6241 rd = (insn >> 12) & 0xf;
6242 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6243 if ((insn & (1 << 22)) == 0) {
6244 /* MOVW */
6245 tmp = new_tmp();
6246 tcg_gen_movi_i32(tmp, val);
6247 } else {
6248 /* MOVT */
6249 tmp = load_reg(s, rd);
6250 tcg_gen_ext16u_i32(tmp, tmp);
6251 tcg_gen_ori_i32(tmp, tmp, val << 16);
6253 store_reg(s, rd, tmp);
6254 } else {
6255 if (((insn >> 12) & 0xf) != 0xf)
6256 goto illegal_op;
6257 if (((insn >> 16) & 0xf) == 0) {
6258 gen_nop_hint(s, insn & 0xff);
6259 } else {
6260 /* CPSR = immediate */
6261 val = insn & 0xff;
6262 shift = ((insn >> 8) & 0xf) * 2;
6263 if (shift)
6264 val = (val >> shift) | (val << (32 - shift));
6265 i = ((insn & (1 << 22)) != 0);
6266 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6267 goto illegal_op;
6270 } else if ((insn & 0x0f900000) == 0x01000000
6271 && (insn & 0x00000090) != 0x00000090) {
6272 /* miscellaneous instructions */
6273 op1 = (insn >> 21) & 3;
6274 sh = (insn >> 4) & 0xf;
6275 rm = insn & 0xf;
6276 switch (sh) {
6277 case 0x0: /* move program status register */
6278 if (op1 & 1) {
6279 /* PSR = reg */
6280 tmp = load_reg(s, rm);
6281 i = ((op1 & 2) != 0);
6282 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6283 goto illegal_op;
6284 } else {
6285 /* reg = PSR */
6286 rd = (insn >> 12) & 0xf;
6287 if (op1 & 2) {
6288 if (IS_USER(s))
6289 goto illegal_op;
6290 tmp = load_cpu_field(spsr);
6291 } else {
6292 tmp = new_tmp();
6293 gen_helper_cpsr_read(tmp);
6295 store_reg(s, rd, tmp);
6297 break;
6298 case 0x1:
6299 if (op1 == 1) {
6300 /* branch/exchange thumb (bx). */
6301 tmp = load_reg(s, rm);
6302 gen_bx(s, tmp);
6303 } else if (op1 == 3) {
6304 /* clz */
6305 rd = (insn >> 12) & 0xf;
6306 tmp = load_reg(s, rm);
6307 gen_helper_clz(tmp, tmp);
6308 store_reg(s, rd, tmp);
6309 } else {
6310 goto illegal_op;
6312 break;
6313 case 0x2:
6314 if (op1 == 1) {
6315 ARCH(5J); /* bxj */
6316 /* Trivial implementation equivalent to bx. */
6317 tmp = load_reg(s, rm);
6318 gen_bx(s, tmp);
6319 } else {
6320 goto illegal_op;
6322 break;
6323 case 0x3:
6324 if (op1 != 1)
6325 goto illegal_op;
6327 /* branch link/exchange thumb (blx) */
6328 tmp = load_reg(s, rm);
6329 tmp2 = new_tmp();
6330 tcg_gen_movi_i32(tmp2, s->pc);
6331 store_reg(s, 14, tmp2);
6332 gen_bx(s, tmp);
6333 break;
6334 case 0x5: /* saturating add/subtract */
6335 rd = (insn >> 12) & 0xf;
6336 rn = (insn >> 16) & 0xf;
6337 tmp = load_reg(s, rm);
6338 tmp2 = load_reg(s, rn);
6339 if (op1 & 2)
6340 gen_helper_double_saturate(tmp2, tmp2);
6341 if (op1 & 1)
6342 gen_helper_sub_saturate(tmp, tmp, tmp2);
6343 else
6344 gen_helper_add_saturate(tmp, tmp, tmp2);
6345 dead_tmp(tmp2);
6346 store_reg(s, rd, tmp);
6347 break;
6348 case 7: /* bkpt */
6349 gen_set_condexec(s);
6350 gen_set_pc_im(s->pc - 4);
6351 gen_exception(EXCP_BKPT);
6352 s->is_jmp = DISAS_JUMP;
6353 break;
6354 case 0x8: /* signed multiply */
6355 case 0xa:
6356 case 0xc:
6357 case 0xe:
6358 rs = (insn >> 8) & 0xf;
6359 rn = (insn >> 12) & 0xf;
6360 rd = (insn >> 16) & 0xf;
6361 if (op1 == 1) {
6362 /* (32 * 16) >> 16 */
6363 tmp = load_reg(s, rm);
6364 tmp2 = load_reg(s, rs);
6365 if (sh & 4)
6366 tcg_gen_sari_i32(tmp2, tmp2, 16);
6367 else
6368 gen_sxth(tmp2);
6369 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6370 tcg_gen_shri_i64(tmp64, tmp64, 16);
6371 tmp = new_tmp();
6372 tcg_gen_trunc_i64_i32(tmp, tmp64);
6373 tcg_temp_free_i64(tmp64);
6374 if ((sh & 2) == 0) {
6375 tmp2 = load_reg(s, rn);
6376 gen_helper_add_setq(tmp, tmp, tmp2);
6377 dead_tmp(tmp2);
6379 store_reg(s, rd, tmp);
6380 } else {
6381 /* 16 * 16 */
6382 tmp = load_reg(s, rm);
6383 tmp2 = load_reg(s, rs);
6384 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6385 dead_tmp(tmp2);
6386 if (op1 == 2) {
6387 tmp64 = tcg_temp_new_i64();
6388 tcg_gen_ext_i32_i64(tmp64, tmp);
6389 dead_tmp(tmp);
6390 gen_addq(s, tmp64, rn, rd);
6391 gen_storeq_reg(s, rn, rd, tmp64);
6392 tcg_temp_free_i64(tmp64);
6393 } else {
6394 if (op1 == 0) {
6395 tmp2 = load_reg(s, rn);
6396 gen_helper_add_setq(tmp, tmp, tmp2);
6397 dead_tmp(tmp2);
6399 store_reg(s, rd, tmp);
6402 break;
6403 default:
6404 goto illegal_op;
6406 } else if (((insn & 0x0e000000) == 0 &&
6407 (insn & 0x00000090) != 0x90) ||
6408 ((insn & 0x0e000000) == (1 << 25))) {
6409 int set_cc, logic_cc, shiftop;
6411 op1 = (insn >> 21) & 0xf;
6412 set_cc = (insn >> 20) & 1;
6413 logic_cc = table_logic_cc[op1] & set_cc;
6415 /* data processing instruction */
6416 if (insn & (1 << 25)) {
6417 /* immediate operand */
6418 val = insn & 0xff;
6419 shift = ((insn >> 8) & 0xf) * 2;
6420 if (shift) {
6421 val = (val >> shift) | (val << (32 - shift));
6423 tmp2 = new_tmp();
6424 tcg_gen_movi_i32(tmp2, val);
6425 if (logic_cc && shift) {
6426 gen_set_CF_bit31(tmp2);
6428 } else {
6429 /* register */
6430 rm = (insn) & 0xf;
6431 tmp2 = load_reg(s, rm);
6432 shiftop = (insn >> 5) & 3;
6433 if (!(insn & (1 << 4))) {
6434 shift = (insn >> 7) & 0x1f;
6435 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6436 } else {
6437 rs = (insn >> 8) & 0xf;
6438 tmp = load_reg(s, rs);
6439 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6442 if (op1 != 0x0f && op1 != 0x0d) {
6443 rn = (insn >> 16) & 0xf;
6444 tmp = load_reg(s, rn);
6445 } else {
6446 TCGV_UNUSED(tmp);
6448 rd = (insn >> 12) & 0xf;
6449 switch(op1) {
6450 case 0x00:
6451 tcg_gen_and_i32(tmp, tmp, tmp2);
6452 if (logic_cc) {
6453 gen_logic_CC(tmp);
6455 store_reg_bx(env, s, rd, tmp);
6456 break;
6457 case 0x01:
6458 tcg_gen_xor_i32(tmp, tmp, tmp2);
6459 if (logic_cc) {
6460 gen_logic_CC(tmp);
6462 store_reg_bx(env, s, rd, tmp);
6463 break;
6464 case 0x02:
6465 if (set_cc && rd == 15) {
6466 /* SUBS r15, ... is used for exception return. */
6467 if (IS_USER(s)) {
6468 goto illegal_op;
6470 gen_helper_sub_cc(tmp, tmp, tmp2);
6471 gen_exception_return(s, tmp);
6472 } else {
6473 if (set_cc) {
6474 gen_helper_sub_cc(tmp, tmp, tmp2);
6475 } else {
6476 tcg_gen_sub_i32(tmp, tmp, tmp2);
6478 store_reg_bx(env, s, rd, tmp);
6480 break;
6481 case 0x03:
6482 if (set_cc) {
6483 gen_helper_sub_cc(tmp, tmp2, tmp);
6484 } else {
6485 tcg_gen_sub_i32(tmp, tmp2, tmp);
6487 store_reg_bx(env, s, rd, tmp);
6488 break;
6489 case 0x04:
6490 if (set_cc) {
6491 gen_helper_add_cc(tmp, tmp, tmp2);
6492 } else {
6493 tcg_gen_add_i32(tmp, tmp, tmp2);
6495 store_reg_bx(env, s, rd, tmp);
6496 break;
6497 case 0x05:
6498 if (set_cc) {
6499 gen_helper_adc_cc(tmp, tmp, tmp2);
6500 } else {
6501 gen_add_carry(tmp, tmp, tmp2);
6503 store_reg_bx(env, s, rd, tmp);
6504 break;
6505 case 0x06:
6506 if (set_cc) {
6507 gen_helper_sbc_cc(tmp, tmp, tmp2);
6508 } else {
6509 gen_sub_carry(tmp, tmp, tmp2);
6511 store_reg_bx(env, s, rd, tmp);
6512 break;
6513 case 0x07:
6514 if (set_cc) {
6515 gen_helper_sbc_cc(tmp, tmp2, tmp);
6516 } else {
6517 gen_sub_carry(tmp, tmp2, tmp);
6519 store_reg_bx(env, s, rd, tmp);
6520 break;
6521 case 0x08:
6522 if (set_cc) {
6523 tcg_gen_and_i32(tmp, tmp, tmp2);
6524 gen_logic_CC(tmp);
6526 dead_tmp(tmp);
6527 break;
6528 case 0x09:
6529 if (set_cc) {
6530 tcg_gen_xor_i32(tmp, tmp, tmp2);
6531 gen_logic_CC(tmp);
6533 dead_tmp(tmp);
6534 break;
6535 case 0x0a:
6536 if (set_cc) {
6537 gen_helper_sub_cc(tmp, tmp, tmp2);
6539 dead_tmp(tmp);
6540 break;
6541 case 0x0b:
6542 if (set_cc) {
6543 gen_helper_add_cc(tmp, tmp, tmp2);
6545 dead_tmp(tmp);
6546 break;
6547 case 0x0c:
6548 tcg_gen_or_i32(tmp, tmp, tmp2);
6549 if (logic_cc) {
6550 gen_logic_CC(tmp);
6552 store_reg_bx(env, s, rd, tmp);
6553 break;
6554 case 0x0d:
6555 if (logic_cc && rd == 15) {
6556 /* MOVS r15, ... is used for exception return. */
6557 if (IS_USER(s)) {
6558 goto illegal_op;
6560 gen_exception_return(s, tmp2);
6561 } else {
6562 if (logic_cc) {
6563 gen_logic_CC(tmp2);
6565 store_reg_bx(env, s, rd, tmp2);
6567 break;
6568 case 0x0e:
6569 tcg_gen_andc_i32(tmp, tmp, tmp2);
6570 if (logic_cc) {
6571 gen_logic_CC(tmp);
6573 store_reg_bx(env, s, rd, tmp);
6574 break;
6575 default:
6576 case 0x0f:
6577 tcg_gen_not_i32(tmp2, tmp2);
6578 if (logic_cc) {
6579 gen_logic_CC(tmp2);
6581 store_reg_bx(env, s, rd, tmp2);
6582 break;
6584 if (op1 != 0x0f && op1 != 0x0d) {
6585 dead_tmp(tmp2);
6587 } else {
6588 /* other instructions */
6589 op1 = (insn >> 24) & 0xf;
6590 switch(op1) {
6591 case 0x0:
6592 case 0x1:
6593 /* multiplies, extra load/stores */
6594 sh = (insn >> 5) & 3;
6595 if (sh == 0) {
6596 if (op1 == 0x0) {
6597 rd = (insn >> 16) & 0xf;
6598 rn = (insn >> 12) & 0xf;
6599 rs = (insn >> 8) & 0xf;
6600 rm = (insn) & 0xf;
6601 op1 = (insn >> 20) & 0xf;
6602 switch (op1) {
6603 case 0: case 1: case 2: case 3: case 6:
6604 /* 32 bit mul */
6605 tmp = load_reg(s, rs);
6606 tmp2 = load_reg(s, rm);
6607 tcg_gen_mul_i32(tmp, tmp, tmp2);
6608 dead_tmp(tmp2);
6609 if (insn & (1 << 22)) {
6610 /* Subtract (mls) */
6611 ARCH(6T2);
6612 tmp2 = load_reg(s, rn);
6613 tcg_gen_sub_i32(tmp, tmp2, tmp);
6614 dead_tmp(tmp2);
6615 } else if (insn & (1 << 21)) {
6616 /* Add */
6617 tmp2 = load_reg(s, rn);
6618 tcg_gen_add_i32(tmp, tmp, tmp2);
6619 dead_tmp(tmp2);
6621 if (insn & (1 << 20))
6622 gen_logic_CC(tmp);
6623 store_reg(s, rd, tmp);
6624 break;
6625 default:
6626 /* 64 bit mul */
6627 tmp = load_reg(s, rs);
6628 tmp2 = load_reg(s, rm);
6629 if (insn & (1 << 22))
6630 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6631 else
6632 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6633 if (insn & (1 << 21)) /* mult accumulate */
6634 gen_addq(s, tmp64, rn, rd);
6635 if (!(insn & (1 << 23))) { /* double accumulate */
6636 ARCH(6);
6637 gen_addq_lo(s, tmp64, rn);
6638 gen_addq_lo(s, tmp64, rd);
6640 if (insn & (1 << 20))
6641 gen_logicq_cc(tmp64);
6642 gen_storeq_reg(s, rn, rd, tmp64);
6643 tcg_temp_free_i64(tmp64);
6644 break;
6646 } else {
6647 rn = (insn >> 16) & 0xf;
6648 rd = (insn >> 12) & 0xf;
6649 if (insn & (1 << 23)) {
6650 /* load/store exclusive */
6651 op1 = (insn >> 21) & 0x3;
6652 if (op1)
6653 ARCH(6K);
6654 else
6655 ARCH(6);
6656 addr = tcg_temp_local_new_i32();
6657 load_reg_var(s, addr, rn);
6658 if (insn & (1 << 20)) {
6659 switch (op1) {
6660 case 0: /* ldrex */
6661 gen_load_exclusive(s, rd, 15, addr, 2);
6662 break;
6663 case 1: /* ldrexd */
6664 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6665 break;
6666 case 2: /* ldrexb */
6667 gen_load_exclusive(s, rd, 15, addr, 0);
6668 break;
6669 case 3: /* ldrexh */
6670 gen_load_exclusive(s, rd, 15, addr, 1);
6671 break;
6672 default:
6673 abort();
6675 } else {
6676 rm = insn & 0xf;
6677 switch (op1) {
6678 case 0: /* strex */
6679 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6680 break;
6681 case 1: /* strexd */
6682 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6683 break;
6684 case 2: /* strexb */
6685 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6686 break;
6687 case 3: /* strexh */
6688 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6689 break;
6690 default:
6691 abort();
6694 tcg_temp_free(addr);
6695 } else {
6696 /* SWP instruction */
6697 rm = (insn) & 0xf;
6699 /* ??? This is not really atomic. However we know
6700 we never have multiple CPUs running in parallel,
6701 so it is good enough. */
6702 addr = load_reg(s, rn);
6703 tmp = load_reg(s, rm);
6704 if (insn & (1 << 22)) {
6705 tmp2 = gen_ld8u(addr, IS_USER(s));
6706 gen_st8(tmp, addr, IS_USER(s));
6707 } else {
6708 tmp2 = gen_ld32(addr, IS_USER(s));
6709 gen_st32(tmp, addr, IS_USER(s));
6711 dead_tmp(addr);
6712 store_reg(s, rd, tmp2);
6715 } else {
6716 int address_offset;
6717 int load;
6718 /* Misc load/store */
6719 rn = (insn >> 16) & 0xf;
6720 rd = (insn >> 12) & 0xf;
6721 addr = load_reg(s, rn);
6722 if (insn & (1 << 24))
6723 gen_add_datah_offset(s, insn, 0, addr);
6724 address_offset = 0;
6725 if (insn & (1 << 20)) {
6726 /* load */
6727 switch(sh) {
6728 case 1:
6729 tmp = gen_ld16u(addr, IS_USER(s));
6730 break;
6731 case 2:
6732 tmp = gen_ld8s(addr, IS_USER(s));
6733 break;
6734 default:
6735 case 3:
6736 tmp = gen_ld16s(addr, IS_USER(s));
6737 break;
6739 load = 1;
6740 } else if (sh & 2) {
6741 /* doubleword */
6742 if (sh & 1) {
6743 /* store */
6744 tmp = load_reg(s, rd);
6745 gen_st32(tmp, addr, IS_USER(s));
6746 tcg_gen_addi_i32(addr, addr, 4);
6747 tmp = load_reg(s, rd + 1);
6748 gen_st32(tmp, addr, IS_USER(s));
6749 load = 0;
6750 } else {
6751 /* load */
6752 tmp = gen_ld32(addr, IS_USER(s));
6753 store_reg(s, rd, tmp);
6754 tcg_gen_addi_i32(addr, addr, 4);
6755 tmp = gen_ld32(addr, IS_USER(s));
6756 rd++;
6757 load = 1;
6759 address_offset = -4;
6760 } else {
6761 /* store */
6762 tmp = load_reg(s, rd);
6763 gen_st16(tmp, addr, IS_USER(s));
6764 load = 0;
6766 /* Perform base writeback before the loaded value to
6767 ensure correct behavior with overlapping index registers.
6768 ldrd with base writeback is is undefined if the
6769 destination and index registers overlap. */
6770 if (!(insn & (1 << 24))) {
6771 gen_add_datah_offset(s, insn, address_offset, addr);
6772 store_reg(s, rn, addr);
6773 } else if (insn & (1 << 21)) {
6774 if (address_offset)
6775 tcg_gen_addi_i32(addr, addr, address_offset);
6776 store_reg(s, rn, addr);
6777 } else {
6778 dead_tmp(addr);
6780 if (load) {
6781 /* Complete the load. */
6782 store_reg(s, rd, tmp);
6785 break;
6786 case 0x4:
6787 case 0x5:
6788 goto do_ldst;
6789 case 0x6:
6790 case 0x7:
6791 if (insn & (1 << 4)) {
6792 ARCH(6);
6793 /* Armv6 Media instructions. */
6794 rm = insn & 0xf;
6795 rn = (insn >> 16) & 0xf;
6796 rd = (insn >> 12) & 0xf;
6797 rs = (insn >> 8) & 0xf;
6798 switch ((insn >> 23) & 3) {
6799 case 0: /* Parallel add/subtract. */
6800 op1 = (insn >> 20) & 7;
6801 tmp = load_reg(s, rn);
6802 tmp2 = load_reg(s, rm);
6803 sh = (insn >> 5) & 7;
6804 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6805 goto illegal_op;
6806 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6807 dead_tmp(tmp2);
6808 store_reg(s, rd, tmp);
6809 break;
6810 case 1:
6811 if ((insn & 0x00700020) == 0) {
6812 /* Halfword pack. */
6813 tmp = load_reg(s, rn);
6814 tmp2 = load_reg(s, rm);
6815 shift = (insn >> 7) & 0x1f;
6816 if (insn & (1 << 6)) {
6817 /* pkhtb */
6818 if (shift == 0)
6819 shift = 31;
6820 tcg_gen_sari_i32(tmp2, tmp2, shift);
6821 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6822 tcg_gen_ext16u_i32(tmp2, tmp2);
6823 } else {
6824 /* pkhbt */
6825 if (shift)
6826 tcg_gen_shli_i32(tmp2, tmp2, shift);
6827 tcg_gen_ext16u_i32(tmp, tmp);
6828 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6830 tcg_gen_or_i32(tmp, tmp, tmp2);
6831 dead_tmp(tmp2);
6832 store_reg(s, rd, tmp);
6833 } else if ((insn & 0x00200020) == 0x00200000) {
6834 /* [us]sat */
6835 tmp = load_reg(s, rm);
6836 shift = (insn >> 7) & 0x1f;
6837 if (insn & (1 << 6)) {
6838 if (shift == 0)
6839 shift = 31;
6840 tcg_gen_sari_i32(tmp, tmp, shift);
6841 } else {
6842 tcg_gen_shli_i32(tmp, tmp, shift);
6844 sh = (insn >> 16) & 0x1f;
6845 if (sh != 0) {
6846 tmp2 = tcg_const_i32(sh);
6847 if (insn & (1 << 22))
6848 gen_helper_usat(tmp, tmp, tmp2);
6849 else
6850 gen_helper_ssat(tmp, tmp, tmp2);
6851 tcg_temp_free_i32(tmp2);
6853 store_reg(s, rd, tmp);
6854 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6855 /* [us]sat16 */
6856 tmp = load_reg(s, rm);
6857 sh = (insn >> 16) & 0x1f;
6858 if (sh != 0) {
6859 tmp2 = tcg_const_i32(sh);
6860 if (insn & (1 << 22))
6861 gen_helper_usat16(tmp, tmp, tmp2);
6862 else
6863 gen_helper_ssat16(tmp, tmp, tmp2);
6864 tcg_temp_free_i32(tmp2);
6866 store_reg(s, rd, tmp);
6867 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6868 /* Select bytes. */
6869 tmp = load_reg(s, rn);
6870 tmp2 = load_reg(s, rm);
6871 tmp3 = new_tmp();
6872 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6873 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6874 dead_tmp(tmp3);
6875 dead_tmp(tmp2);
6876 store_reg(s, rd, tmp);
6877 } else if ((insn & 0x000003e0) == 0x00000060) {
6878 tmp = load_reg(s, rm);
6879 shift = (insn >> 10) & 3;
6880 /* ??? In many cases it's not neccessary to do a
6881 rotate, a shift is sufficient. */
6882 if (shift != 0)
6883 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6884 op1 = (insn >> 20) & 7;
6885 switch (op1) {
6886 case 0: gen_sxtb16(tmp); break;
6887 case 2: gen_sxtb(tmp); break;
6888 case 3: gen_sxth(tmp); break;
6889 case 4: gen_uxtb16(tmp); break;
6890 case 6: gen_uxtb(tmp); break;
6891 case 7: gen_uxth(tmp); break;
6892 default: goto illegal_op;
6894 if (rn != 15) {
6895 tmp2 = load_reg(s, rn);
6896 if ((op1 & 3) == 0) {
6897 gen_add16(tmp, tmp2);
6898 } else {
6899 tcg_gen_add_i32(tmp, tmp, tmp2);
6900 dead_tmp(tmp2);
6903 store_reg(s, rd, tmp);
6904 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6905 /* rev */
6906 tmp = load_reg(s, rm);
6907 if (insn & (1 << 22)) {
6908 if (insn & (1 << 7)) {
6909 gen_revsh(tmp);
6910 } else {
6911 ARCH(6T2);
6912 gen_helper_rbit(tmp, tmp);
6914 } else {
6915 if (insn & (1 << 7))
6916 gen_rev16(tmp);
6917 else
6918 tcg_gen_bswap32_i32(tmp, tmp);
6920 store_reg(s, rd, tmp);
6921 } else {
6922 goto illegal_op;
6924 break;
6925 case 2: /* Multiplies (Type 3). */
6926 tmp = load_reg(s, rm);
6927 tmp2 = load_reg(s, rs);
6928 if (insn & (1 << 20)) {
6929 /* Signed multiply most significant [accumulate]. */
6930 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6931 if (insn & (1 << 5))
6932 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6933 tcg_gen_shri_i64(tmp64, tmp64, 32);
6934 tmp = new_tmp();
6935 tcg_gen_trunc_i64_i32(tmp, tmp64);
6936 tcg_temp_free_i64(tmp64);
6937 if (rd != 15) {
6938 tmp2 = load_reg(s, rd);
6939 if (insn & (1 << 6)) {
6940 tcg_gen_sub_i32(tmp, tmp, tmp2);
6941 } else {
6942 tcg_gen_add_i32(tmp, tmp, tmp2);
6944 dead_tmp(tmp2);
6946 store_reg(s, rn, tmp);
6947 } else {
6948 if (insn & (1 << 5))
6949 gen_swap_half(tmp2);
6950 gen_smul_dual(tmp, tmp2);
6951 /* This addition cannot overflow. */
6952 if (insn & (1 << 6)) {
6953 tcg_gen_sub_i32(tmp, tmp, tmp2);
6954 } else {
6955 tcg_gen_add_i32(tmp, tmp, tmp2);
6957 dead_tmp(tmp2);
6958 if (insn & (1 << 22)) {
6959 /* smlald, smlsld */
6960 tmp64 = tcg_temp_new_i64();
6961 tcg_gen_ext_i32_i64(tmp64, tmp);
6962 dead_tmp(tmp);
6963 gen_addq(s, tmp64, rd, rn);
6964 gen_storeq_reg(s, rd, rn, tmp64);
6965 tcg_temp_free_i64(tmp64);
6966 } else {
6967 /* smuad, smusd, smlad, smlsd */
6968 if (rd != 15)
6970 tmp2 = load_reg(s, rd);
6971 gen_helper_add_setq(tmp, tmp, tmp2);
6972 dead_tmp(tmp2);
6974 store_reg(s, rn, tmp);
6977 break;
6978 case 3:
6979 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6980 switch (op1) {
6981 case 0: /* Unsigned sum of absolute differences. */
6982 ARCH(6);
6983 tmp = load_reg(s, rm);
6984 tmp2 = load_reg(s, rs);
6985 gen_helper_usad8(tmp, tmp, tmp2);
6986 dead_tmp(tmp2);
6987 if (rd != 15) {
6988 tmp2 = load_reg(s, rd);
6989 tcg_gen_add_i32(tmp, tmp, tmp2);
6990 dead_tmp(tmp2);
6992 store_reg(s, rn, tmp);
6993 break;
6994 case 0x20: case 0x24: case 0x28: case 0x2c:
6995 /* Bitfield insert/clear. */
6996 ARCH(6T2);
6997 shift = (insn >> 7) & 0x1f;
6998 i = (insn >> 16) & 0x1f;
6999 i = i + 1 - shift;
7000 if (rm == 15) {
7001 tmp = new_tmp();
7002 tcg_gen_movi_i32(tmp, 0);
7003 } else {
7004 tmp = load_reg(s, rm);
7006 if (i != 32) {
7007 tmp2 = load_reg(s, rd);
7008 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7009 dead_tmp(tmp2);
7011 store_reg(s, rd, tmp);
7012 break;
7013 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7014 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7015 ARCH(6T2);
7016 tmp = load_reg(s, rm);
7017 shift = (insn >> 7) & 0x1f;
7018 i = ((insn >> 16) & 0x1f) + 1;
7019 if (shift + i > 32)
7020 goto illegal_op;
7021 if (i < 32) {
7022 if (op1 & 0x20) {
7023 gen_ubfx(tmp, shift, (1u << i) - 1);
7024 } else {
7025 gen_sbfx(tmp, shift, i);
7028 store_reg(s, rd, tmp);
7029 break;
7030 default:
7031 goto illegal_op;
7033 break;
7035 break;
7037 do_ldst:
7038 /* Check for undefined extension instructions
7039 * per the ARM Bible IE:
7040 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7042 sh = (0xf << 20) | (0xf << 4);
7043 if (op1 == 0x7 && ((insn & sh) == sh))
7045 goto illegal_op;
7047 /* load/store byte/word */
7048 rn = (insn >> 16) & 0xf;
7049 rd = (insn >> 12) & 0xf;
7050 tmp2 = load_reg(s, rn);
7051 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7052 if (insn & (1 << 24))
7053 gen_add_data_offset(s, insn, tmp2);
7054 if (insn & (1 << 20)) {
7055 /* load */
7056 if (insn & (1 << 22)) {
7057 tmp = gen_ld8u(tmp2, i);
7058 } else {
7059 tmp = gen_ld32(tmp2, i);
7061 } else {
7062 /* store */
7063 tmp = load_reg(s, rd);
7064 if (insn & (1 << 22))
7065 gen_st8(tmp, tmp2, i);
7066 else
7067 gen_st32(tmp, tmp2, i);
7069 if (!(insn & (1 << 24))) {
7070 gen_add_data_offset(s, insn, tmp2);
7071 store_reg(s, rn, tmp2);
7072 } else if (insn & (1 << 21)) {
7073 store_reg(s, rn, tmp2);
7074 } else {
7075 dead_tmp(tmp2);
7077 if (insn & (1 << 20)) {
7078 /* Complete the load. */
7079 if (rd == 15)
7080 gen_bx(s, tmp);
7081 else
7082 store_reg(s, rd, tmp);
7084 break;
7085 case 0x08:
7086 case 0x09:
7088 int j, n, user, loaded_base;
7089 TCGv loaded_var;
7090 /* load/store multiple words */
7091 /* XXX: store correct base if write back */
7092 user = 0;
7093 if (insn & (1 << 22)) {
7094 if (IS_USER(s))
7095 goto illegal_op; /* only usable in supervisor mode */
7097 if ((insn & (1 << 15)) == 0)
7098 user = 1;
7100 rn = (insn >> 16) & 0xf;
7101 addr = load_reg(s, rn);
7103 /* compute total size */
7104 loaded_base = 0;
7105 TCGV_UNUSED(loaded_var);
7106 n = 0;
7107 for(i=0;i<16;i++) {
7108 if (insn & (1 << i))
7109 n++;
7111 /* XXX: test invalid n == 0 case ? */
7112 if (insn & (1 << 23)) {
7113 if (insn & (1 << 24)) {
7114 /* pre increment */
7115 tcg_gen_addi_i32(addr, addr, 4);
7116 } else {
7117 /* post increment */
7119 } else {
7120 if (insn & (1 << 24)) {
7121 /* pre decrement */
7122 tcg_gen_addi_i32(addr, addr, -(n * 4));
7123 } else {
7124 /* post decrement */
7125 if (n != 1)
7126 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7129 j = 0;
7130 for(i=0;i<16;i++) {
7131 if (insn & (1 << i)) {
7132 if (insn & (1 << 20)) {
7133 /* load */
7134 tmp = gen_ld32(addr, IS_USER(s));
7135 if (i == 15) {
7136 gen_bx(s, tmp);
7137 } else if (user) {
7138 tmp2 = tcg_const_i32(i);
7139 gen_helper_set_user_reg(tmp2, tmp);
7140 tcg_temp_free_i32(tmp2);
7141 dead_tmp(tmp);
7142 } else if (i == rn) {
7143 loaded_var = tmp;
7144 loaded_base = 1;
7145 } else {
7146 store_reg(s, i, tmp);
7148 } else {
7149 /* store */
7150 if (i == 15) {
7151 /* special case: r15 = PC + 8 */
7152 val = (long)s->pc + 4;
7153 tmp = new_tmp();
7154 tcg_gen_movi_i32(tmp, val);
7155 } else if (user) {
7156 tmp = new_tmp();
7157 tmp2 = tcg_const_i32(i);
7158 gen_helper_get_user_reg(tmp, tmp2);
7159 tcg_temp_free_i32(tmp2);
7160 } else {
7161 tmp = load_reg(s, i);
7163 gen_st32(tmp, addr, IS_USER(s));
7165 j++;
7166 /* no need to add after the last transfer */
7167 if (j != n)
7168 tcg_gen_addi_i32(addr, addr, 4);
7171 if (insn & (1 << 21)) {
7172 /* write back */
7173 if (insn & (1 << 23)) {
7174 if (insn & (1 << 24)) {
7175 /* pre increment */
7176 } else {
7177 /* post increment */
7178 tcg_gen_addi_i32(addr, addr, 4);
7180 } else {
7181 if (insn & (1 << 24)) {
7182 /* pre decrement */
7183 if (n != 1)
7184 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7185 } else {
7186 /* post decrement */
7187 tcg_gen_addi_i32(addr, addr, -(n * 4));
7190 store_reg(s, rn, addr);
7191 } else {
7192 dead_tmp(addr);
7194 if (loaded_base) {
7195 store_reg(s, rn, loaded_var);
7197 if ((insn & (1 << 22)) && !user) {
7198 /* Restore CPSR from SPSR. */
7199 tmp = load_cpu_field(spsr);
7200 gen_set_cpsr(tmp, 0xffffffff);
7201 dead_tmp(tmp);
7202 s->is_jmp = DISAS_UPDATE;
7205 break;
7206 case 0xa:
7207 case 0xb:
7209 int32_t offset;
7211 /* branch (and link) */
7212 val = (int32_t)s->pc;
7213 if (insn & (1 << 24)) {
7214 tmp = new_tmp();
7215 tcg_gen_movi_i32(tmp, val);
7216 store_reg(s, 14, tmp);
7218 offset = (((int32_t)insn << 8) >> 8);
7219 val += (offset << 2) + 4;
7220 gen_jmp(s, val);
7222 break;
7223 case 0xc:
7224 case 0xd:
7225 case 0xe:
7226 /* Coprocessor. */
7227 if (disas_coproc_insn(env, s, insn))
7228 goto illegal_op;
7229 break;
7230 case 0xf:
7231 /* swi */
7232 gen_set_pc_im(s->pc);
7233 s->is_jmp = DISAS_SWI;
7234 break;
7235 default:
7236 illegal_op:
7237 gen_set_condexec(s);
7238 gen_set_pc_im(s->pc - 4);
7239 gen_exception(EXCP_UDEF);
7240 s->is_jmp = DISAS_JUMP;
7241 break;
7246 /* Return true if this is a Thumb-2 logical op. */
7247 static int
7248 thumb2_logic_op(int op)
7250 return (op < 8);
7253 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7254 then set condition code flags based on the result of the operation.
7255 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7256 to the high bit of T1.
7257 Returns zero if the opcode is valid. */
7259 static int
7260 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7262 int logic_cc;
7264 logic_cc = 0;
7265 switch (op) {
7266 case 0: /* and */
7267 tcg_gen_and_i32(t0, t0, t1);
7268 logic_cc = conds;
7269 break;
7270 case 1: /* bic */
7271 tcg_gen_andc_i32(t0, t0, t1);
7272 logic_cc = conds;
7273 break;
7274 case 2: /* orr */
7275 tcg_gen_or_i32(t0, t0, t1);
7276 logic_cc = conds;
7277 break;
7278 case 3: /* orn */
7279 tcg_gen_not_i32(t1, t1);
7280 tcg_gen_or_i32(t0, t0, t1);
7281 logic_cc = conds;
7282 break;
7283 case 4: /* eor */
7284 tcg_gen_xor_i32(t0, t0, t1);
7285 logic_cc = conds;
7286 break;
7287 case 8: /* add */
7288 if (conds)
7289 gen_helper_add_cc(t0, t0, t1);
7290 else
7291 tcg_gen_add_i32(t0, t0, t1);
7292 break;
7293 case 10: /* adc */
7294 if (conds)
7295 gen_helper_adc_cc(t0, t0, t1);
7296 else
7297 gen_adc(t0, t1);
7298 break;
7299 case 11: /* sbc */
7300 if (conds)
7301 gen_helper_sbc_cc(t0, t0, t1);
7302 else
7303 gen_sub_carry(t0, t0, t1);
7304 break;
7305 case 13: /* sub */
7306 if (conds)
7307 gen_helper_sub_cc(t0, t0, t1);
7308 else
7309 tcg_gen_sub_i32(t0, t0, t1);
7310 break;
7311 case 14: /* rsb */
7312 if (conds)
7313 gen_helper_sub_cc(t0, t1, t0);
7314 else
7315 tcg_gen_sub_i32(t0, t1, t0);
7316 break;
7317 default: /* 5, 6, 7, 9, 12, 15. */
7318 return 1;
7320 if (logic_cc) {
7321 gen_logic_CC(t0);
7322 if (shifter_out)
7323 gen_set_CF_bit31(t1);
7325 return 0;
7328 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7329 is not legal. */
7330 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7332 uint32_t insn, imm, shift, offset;
7333 uint32_t rd, rn, rm, rs;
7334 TCGv tmp;
7335 TCGv tmp2;
7336 TCGv tmp3;
7337 TCGv addr;
7338 TCGv_i64 tmp64;
7339 int op;
7340 int shiftop;
7341 int conds;
7342 int logic_cc;
7344 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7345 || arm_feature (env, ARM_FEATURE_M))) {
7346 /* Thumb-1 cores may need to treat bl and blx as a pair of
7347 16-bit instructions to get correct prefetch abort behavior. */
7348 insn = insn_hw1;
7349 if ((insn & (1 << 12)) == 0) {
7350 /* Second half of blx. */
7351 offset = ((insn & 0x7ff) << 1);
7352 tmp = load_reg(s, 14);
7353 tcg_gen_addi_i32(tmp, tmp, offset);
7354 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7356 tmp2 = new_tmp();
7357 tcg_gen_movi_i32(tmp2, s->pc | 1);
7358 store_reg(s, 14, tmp2);
7359 gen_bx(s, tmp);
7360 return 0;
7362 if (insn & (1 << 11)) {
7363 /* Second half of bl. */
7364 offset = ((insn & 0x7ff) << 1) | 1;
7365 tmp = load_reg(s, 14);
7366 tcg_gen_addi_i32(tmp, tmp, offset);
7368 tmp2 = new_tmp();
7369 tcg_gen_movi_i32(tmp2, s->pc | 1);
7370 store_reg(s, 14, tmp2);
7371 gen_bx(s, tmp);
7372 return 0;
7374 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7375 /* Instruction spans a page boundary. Implement it as two
7376 16-bit instructions in case the second half causes an
7377 prefetch abort. */
7378 offset = ((int32_t)insn << 21) >> 9;
7379 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7380 return 0;
7382 /* Fall through to 32-bit decode. */
7385 insn = lduw_code(s->pc);
7386 s->pc += 2;
7387 insn |= (uint32_t)insn_hw1 << 16;
7389 if ((insn & 0xf800e800) != 0xf000e800) {
7390 ARCH(6T2);
7393 rn = (insn >> 16) & 0xf;
7394 rs = (insn >> 12) & 0xf;
7395 rd = (insn >> 8) & 0xf;
7396 rm = insn & 0xf;
7397 switch ((insn >> 25) & 0xf) {
7398 case 0: case 1: case 2: case 3:
7399 /* 16-bit instructions. Should never happen. */
7400 abort();
7401 case 4:
7402 if (insn & (1 << 22)) {
7403 /* Other load/store, table branch. */
7404 if (insn & 0x01200000) {
7405 /* Load/store doubleword. */
7406 if (rn == 15) {
7407 addr = new_tmp();
7408 tcg_gen_movi_i32(addr, s->pc & ~3);
7409 } else {
7410 addr = load_reg(s, rn);
7412 offset = (insn & 0xff) * 4;
7413 if ((insn & (1 << 23)) == 0)
7414 offset = -offset;
7415 if (insn & (1 << 24)) {
7416 tcg_gen_addi_i32(addr, addr, offset);
7417 offset = 0;
7419 if (insn & (1 << 20)) {
7420 /* ldrd */
7421 tmp = gen_ld32(addr, IS_USER(s));
7422 store_reg(s, rs, tmp);
7423 tcg_gen_addi_i32(addr, addr, 4);
7424 tmp = gen_ld32(addr, IS_USER(s));
7425 store_reg(s, rd, tmp);
7426 } else {
7427 /* strd */
7428 tmp = load_reg(s, rs);
7429 gen_st32(tmp, addr, IS_USER(s));
7430 tcg_gen_addi_i32(addr, addr, 4);
7431 tmp = load_reg(s, rd);
7432 gen_st32(tmp, addr, IS_USER(s));
7434 if (insn & (1 << 21)) {
7435 /* Base writeback. */
7436 if (rn == 15)
7437 goto illegal_op;
7438 tcg_gen_addi_i32(addr, addr, offset - 4);
7439 store_reg(s, rn, addr);
7440 } else {
7441 dead_tmp(addr);
7443 } else if ((insn & (1 << 23)) == 0) {
7444 /* Load/store exclusive word. */
7445 addr = tcg_temp_local_new();
7446 load_reg_var(s, addr, rn);
7447 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7448 if (insn & (1 << 20)) {
7449 gen_load_exclusive(s, rs, 15, addr, 2);
7450 } else {
7451 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7453 tcg_temp_free(addr);
7454 } else if ((insn & (1 << 6)) == 0) {
7455 /* Table Branch. */
7456 if (rn == 15) {
7457 addr = new_tmp();
7458 tcg_gen_movi_i32(addr, s->pc);
7459 } else {
7460 addr = load_reg(s, rn);
7462 tmp = load_reg(s, rm);
7463 tcg_gen_add_i32(addr, addr, tmp);
7464 if (insn & (1 << 4)) {
7465 /* tbh */
7466 tcg_gen_add_i32(addr, addr, tmp);
7467 dead_tmp(tmp);
7468 tmp = gen_ld16u(addr, IS_USER(s));
7469 } else { /* tbb */
7470 dead_tmp(tmp);
7471 tmp = gen_ld8u(addr, IS_USER(s));
7473 dead_tmp(addr);
7474 tcg_gen_shli_i32(tmp, tmp, 1);
7475 tcg_gen_addi_i32(tmp, tmp, s->pc);
7476 store_reg(s, 15, tmp);
7477 } else {
7478 /* Load/store exclusive byte/halfword/doubleword. */
7479 ARCH(7);
7480 op = (insn >> 4) & 0x3;
7481 if (op == 2) {
7482 goto illegal_op;
7484 addr = tcg_temp_local_new();
7485 load_reg_var(s, addr, rn);
7486 if (insn & (1 << 20)) {
7487 gen_load_exclusive(s, rs, rd, addr, op);
7488 } else {
7489 gen_store_exclusive(s, rm, rs, rd, addr, op);
7491 tcg_temp_free(addr);
7493 } else {
7494 /* Load/store multiple, RFE, SRS. */
7495 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7496 /* Not available in user mode. */
7497 if (IS_USER(s))
7498 goto illegal_op;
7499 if (insn & (1 << 20)) {
7500 /* rfe */
7501 addr = load_reg(s, rn);
7502 if ((insn & (1 << 24)) == 0)
7503 tcg_gen_addi_i32(addr, addr, -8);
7504 /* Load PC into tmp and CPSR into tmp2. */
7505 tmp = gen_ld32(addr, 0);
7506 tcg_gen_addi_i32(addr, addr, 4);
7507 tmp2 = gen_ld32(addr, 0);
7508 if (insn & (1 << 21)) {
7509 /* Base writeback. */
7510 if (insn & (1 << 24)) {
7511 tcg_gen_addi_i32(addr, addr, 4);
7512 } else {
7513 tcg_gen_addi_i32(addr, addr, -4);
7515 store_reg(s, rn, addr);
7516 } else {
7517 dead_tmp(addr);
7519 gen_rfe(s, tmp, tmp2);
7520 } else {
7521 /* srs */
7522 op = (insn & 0x1f);
7523 if (op == (env->uncached_cpsr & CPSR_M)) {
7524 addr = load_reg(s, 13);
7525 } else {
7526 addr = new_tmp();
7527 tmp = tcg_const_i32(op);
7528 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7529 tcg_temp_free_i32(tmp);
7531 if ((insn & (1 << 24)) == 0) {
7532 tcg_gen_addi_i32(addr, addr, -8);
7534 tmp = load_reg(s, 14);
7535 gen_st32(tmp, addr, 0);
7536 tcg_gen_addi_i32(addr, addr, 4);
7537 tmp = new_tmp();
7538 gen_helper_cpsr_read(tmp);
7539 gen_st32(tmp, addr, 0);
7540 if (insn & (1 << 21)) {
7541 if ((insn & (1 << 24)) == 0) {
7542 tcg_gen_addi_i32(addr, addr, -4);
7543 } else {
7544 tcg_gen_addi_i32(addr, addr, 4);
7546 if (op == (env->uncached_cpsr & CPSR_M)) {
7547 store_reg(s, 13, addr);
7548 } else {
7549 tmp = tcg_const_i32(op);
7550 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7551 tcg_temp_free_i32(tmp);
7553 } else {
7554 dead_tmp(addr);
7557 } else {
7558 int i;
7559 /* Load/store multiple. */
7560 addr = load_reg(s, rn);
7561 offset = 0;
7562 for (i = 0; i < 16; i++) {
7563 if (insn & (1 << i))
7564 offset += 4;
7566 if (insn & (1 << 24)) {
7567 tcg_gen_addi_i32(addr, addr, -offset);
7570 for (i = 0; i < 16; i++) {
7571 if ((insn & (1 << i)) == 0)
7572 continue;
7573 if (insn & (1 << 20)) {
7574 /* Load. */
7575 tmp = gen_ld32(addr, IS_USER(s));
7576 if (i == 15) {
7577 gen_bx(s, tmp);
7578 } else {
7579 store_reg(s, i, tmp);
7581 } else {
7582 /* Store. */
7583 tmp = load_reg(s, i);
7584 gen_st32(tmp, addr, IS_USER(s));
7586 tcg_gen_addi_i32(addr, addr, 4);
7588 if (insn & (1 << 21)) {
7589 /* Base register writeback. */
7590 if (insn & (1 << 24)) {
7591 tcg_gen_addi_i32(addr, addr, -offset);
7593 /* Fault if writeback register is in register list. */
7594 if (insn & (1 << rn))
7595 goto illegal_op;
7596 store_reg(s, rn, addr);
7597 } else {
7598 dead_tmp(addr);
7602 break;
7603 case 5: /* Data processing register constant shift. */
7604 if (rn == 15) {
7605 tmp = new_tmp();
7606 tcg_gen_movi_i32(tmp, 0);
7607 } else {
7608 tmp = load_reg(s, rn);
7610 tmp2 = load_reg(s, rm);
7611 op = (insn >> 21) & 0xf;
7612 shiftop = (insn >> 4) & 3;
7613 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7614 conds = (insn & (1 << 20)) != 0;
7615 logic_cc = (conds && thumb2_logic_op(op));
7616 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7617 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7618 goto illegal_op;
7619 dead_tmp(tmp2);
7620 if (rd != 15) {
7621 store_reg(s, rd, tmp);
7622 } else {
7623 dead_tmp(tmp);
7625 break;
7626 case 13: /* Misc data processing. */
7627 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7628 if (op < 4 && (insn & 0xf000) != 0xf000)
7629 goto illegal_op;
7630 switch (op) {
7631 case 0: /* Register controlled shift. */
7632 tmp = load_reg(s, rn);
7633 tmp2 = load_reg(s, rm);
7634 if ((insn & 0x70) != 0)
7635 goto illegal_op;
7636 op = (insn >> 21) & 3;
7637 logic_cc = (insn & (1 << 20)) != 0;
7638 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7639 if (logic_cc)
7640 gen_logic_CC(tmp);
7641 store_reg_bx(env, s, rd, tmp);
7642 break;
7643 case 1: /* Sign/zero extend. */
7644 tmp = load_reg(s, rm);
7645 shift = (insn >> 4) & 3;
7646 /* ??? In many cases it's not neccessary to do a
7647 rotate, a shift is sufficient. */
7648 if (shift != 0)
7649 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7650 op = (insn >> 20) & 7;
7651 switch (op) {
7652 case 0: gen_sxth(tmp); break;
7653 case 1: gen_uxth(tmp); break;
7654 case 2: gen_sxtb16(tmp); break;
7655 case 3: gen_uxtb16(tmp); break;
7656 case 4: gen_sxtb(tmp); break;
7657 case 5: gen_uxtb(tmp); break;
7658 default: goto illegal_op;
7660 if (rn != 15) {
7661 tmp2 = load_reg(s, rn);
7662 if ((op >> 1) == 1) {
7663 gen_add16(tmp, tmp2);
7664 } else {
7665 tcg_gen_add_i32(tmp, tmp, tmp2);
7666 dead_tmp(tmp2);
7669 store_reg(s, rd, tmp);
7670 break;
7671 case 2: /* SIMD add/subtract. */
7672 op = (insn >> 20) & 7;
7673 shift = (insn >> 4) & 7;
7674 if ((op & 3) == 3 || (shift & 3) == 3)
7675 goto illegal_op;
7676 tmp = load_reg(s, rn);
7677 tmp2 = load_reg(s, rm);
7678 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7679 dead_tmp(tmp2);
7680 store_reg(s, rd, tmp);
7681 break;
7682 case 3: /* Other data processing. */
7683 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7684 if (op < 4) {
7685 /* Saturating add/subtract. */
7686 tmp = load_reg(s, rn);
7687 tmp2 = load_reg(s, rm);
7688 if (op & 2)
7689 gen_helper_double_saturate(tmp, tmp);
7690 if (op & 1)
7691 gen_helper_sub_saturate(tmp, tmp2, tmp);
7692 else
7693 gen_helper_add_saturate(tmp, tmp, tmp2);
7694 dead_tmp(tmp2);
7695 } else {
7696 tmp = load_reg(s, rn);
7697 switch (op) {
7698 case 0x0a: /* rbit */
7699 gen_helper_rbit(tmp, tmp);
7700 break;
7701 case 0x08: /* rev */
7702 tcg_gen_bswap32_i32(tmp, tmp);
7703 break;
7704 case 0x09: /* rev16 */
7705 gen_rev16(tmp);
7706 break;
7707 case 0x0b: /* revsh */
7708 gen_revsh(tmp);
7709 break;
7710 case 0x10: /* sel */
7711 tmp2 = load_reg(s, rm);
7712 tmp3 = new_tmp();
7713 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7714 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7715 dead_tmp(tmp3);
7716 dead_tmp(tmp2);
7717 break;
7718 case 0x18: /* clz */
7719 gen_helper_clz(tmp, tmp);
7720 break;
7721 default:
7722 goto illegal_op;
7725 store_reg(s, rd, tmp);
7726 break;
7727 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7728 op = (insn >> 4) & 0xf;
7729 tmp = load_reg(s, rn);
7730 tmp2 = load_reg(s, rm);
7731 switch ((insn >> 20) & 7) {
7732 case 0: /* 32 x 32 -> 32 */
7733 tcg_gen_mul_i32(tmp, tmp, tmp2);
7734 dead_tmp(tmp2);
7735 if (rs != 15) {
7736 tmp2 = load_reg(s, rs);
7737 if (op)
7738 tcg_gen_sub_i32(tmp, tmp2, tmp);
7739 else
7740 tcg_gen_add_i32(tmp, tmp, tmp2);
7741 dead_tmp(tmp2);
7743 break;
7744 case 1: /* 16 x 16 -> 32 */
7745 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7746 dead_tmp(tmp2);
7747 if (rs != 15) {
7748 tmp2 = load_reg(s, rs);
7749 gen_helper_add_setq(tmp, tmp, tmp2);
7750 dead_tmp(tmp2);
7752 break;
7753 case 2: /* Dual multiply add. */
7754 case 4: /* Dual multiply subtract. */
7755 if (op)
7756 gen_swap_half(tmp2);
7757 gen_smul_dual(tmp, tmp2);
7758 /* This addition cannot overflow. */
7759 if (insn & (1 << 22)) {
7760 tcg_gen_sub_i32(tmp, tmp, tmp2);
7761 } else {
7762 tcg_gen_add_i32(tmp, tmp, tmp2);
7764 dead_tmp(tmp2);
7765 if (rs != 15)
7767 tmp2 = load_reg(s, rs);
7768 gen_helper_add_setq(tmp, tmp, tmp2);
7769 dead_tmp(tmp2);
7771 break;
7772 case 3: /* 32 * 16 -> 32msb */
7773 if (op)
7774 tcg_gen_sari_i32(tmp2, tmp2, 16);
7775 else
7776 gen_sxth(tmp2);
7777 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7778 tcg_gen_shri_i64(tmp64, tmp64, 16);
7779 tmp = new_tmp();
7780 tcg_gen_trunc_i64_i32(tmp, tmp64);
7781 tcg_temp_free_i64(tmp64);
7782 if (rs != 15)
7784 tmp2 = load_reg(s, rs);
7785 gen_helper_add_setq(tmp, tmp, tmp2);
7786 dead_tmp(tmp2);
7788 break;
7789 case 5: case 6: /* 32 * 32 -> 32msb */
7790 gen_imull(tmp, tmp2);
7791 if (insn & (1 << 5)) {
7792 gen_roundqd(tmp, tmp2);
7793 dead_tmp(tmp2);
7794 } else {
7795 dead_tmp(tmp);
7796 tmp = tmp2;
7798 if (rs != 15) {
7799 tmp2 = load_reg(s, rs);
7800 if (insn & (1 << 21)) {
7801 tcg_gen_add_i32(tmp, tmp, tmp2);
7802 } else {
7803 tcg_gen_sub_i32(tmp, tmp2, tmp);
7805 dead_tmp(tmp2);
7807 break;
7808 case 7: /* Unsigned sum of absolute differences. */
7809 gen_helper_usad8(tmp, tmp, tmp2);
7810 dead_tmp(tmp2);
7811 if (rs != 15) {
7812 tmp2 = load_reg(s, rs);
7813 tcg_gen_add_i32(tmp, tmp, tmp2);
7814 dead_tmp(tmp2);
7816 break;
7818 store_reg(s, rd, tmp);
7819 break;
7820 case 6: case 7: /* 64-bit multiply, Divide. */
7821 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7822 tmp = load_reg(s, rn);
7823 tmp2 = load_reg(s, rm);
7824 if ((op & 0x50) == 0x10) {
7825 /* sdiv, udiv */
7826 if (!arm_feature(env, ARM_FEATURE_DIV))
7827 goto illegal_op;
7828 if (op & 0x20)
7829 gen_helper_udiv(tmp, tmp, tmp2);
7830 else
7831 gen_helper_sdiv(tmp, tmp, tmp2);
7832 dead_tmp(tmp2);
7833 store_reg(s, rd, tmp);
7834 } else if ((op & 0xe) == 0xc) {
7835 /* Dual multiply accumulate long. */
7836 if (op & 1)
7837 gen_swap_half(tmp2);
7838 gen_smul_dual(tmp, tmp2);
7839 if (op & 0x10) {
7840 tcg_gen_sub_i32(tmp, tmp, tmp2);
7841 } else {
7842 tcg_gen_add_i32(tmp, tmp, tmp2);
7844 dead_tmp(tmp2);
7845 /* BUGFIX */
7846 tmp64 = tcg_temp_new_i64();
7847 tcg_gen_ext_i32_i64(tmp64, tmp);
7848 dead_tmp(tmp);
7849 gen_addq(s, tmp64, rs, rd);
7850 gen_storeq_reg(s, rs, rd, tmp64);
7851 tcg_temp_free_i64(tmp64);
7852 } else {
7853 if (op & 0x20) {
7854 /* Unsigned 64-bit multiply */
7855 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7856 } else {
7857 if (op & 8) {
7858 /* smlalxy */
7859 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7860 dead_tmp(tmp2);
7861 tmp64 = tcg_temp_new_i64();
7862 tcg_gen_ext_i32_i64(tmp64, tmp);
7863 dead_tmp(tmp);
7864 } else {
7865 /* Signed 64-bit multiply */
7866 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7869 if (op & 4) {
7870 /* umaal */
7871 gen_addq_lo(s, tmp64, rs);
7872 gen_addq_lo(s, tmp64, rd);
7873 } else if (op & 0x40) {
7874 /* 64-bit accumulate. */
7875 gen_addq(s, tmp64, rs, rd);
7877 gen_storeq_reg(s, rs, rd, tmp64);
7878 tcg_temp_free_i64(tmp64);
7880 break;
7882 break;
7883 case 6: case 7: case 14: case 15:
7884 /* Coprocessor. */
7885 if (((insn >> 24) & 3) == 3) {
7886 /* Translate into the equivalent ARM encoding. */
7887 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7888 if (disas_neon_data_insn(env, s, insn))
7889 goto illegal_op;
7890 } else {
7891 if (insn & (1 << 28))
7892 goto illegal_op;
7893 if (disas_coproc_insn (env, s, insn))
7894 goto illegal_op;
7896 break;
7897 case 8: case 9: case 10: case 11:
7898 if (insn & (1 << 15)) {
7899 /* Branches, misc control. */
7900 if (insn & 0x5000) {
7901 /* Unconditional branch. */
7902 /* signextend(hw1[10:0]) -> offset[:12]. */
7903 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7904 /* hw1[10:0] -> offset[11:1]. */
7905 offset |= (insn & 0x7ff) << 1;
7906 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7907 offset[24:22] already have the same value because of the
7908 sign extension above. */
7909 offset ^= ((~insn) & (1 << 13)) << 10;
7910 offset ^= ((~insn) & (1 << 11)) << 11;
7912 if (insn & (1 << 14)) {
7913 /* Branch and link. */
7914 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7917 offset += s->pc;
7918 if (insn & (1 << 12)) {
7919 /* b/bl */
7920 gen_jmp(s, offset);
7921 } else {
7922 /* blx */
7923 offset &= ~(uint32_t)2;
7924 gen_bx_im(s, offset);
7926 } else if (((insn >> 23) & 7) == 7) {
7927 /* Misc control */
7928 if (insn & (1 << 13))
7929 goto illegal_op;
7931 if (insn & (1 << 26)) {
7932 /* Secure monitor call (v6Z) */
7933 goto illegal_op; /* not implemented. */
7934 } else {
7935 op = (insn >> 20) & 7;
7936 switch (op) {
7937 case 0: /* msr cpsr. */
7938 if (IS_M(env)) {
7939 tmp = load_reg(s, rn);
7940 addr = tcg_const_i32(insn & 0xff);
7941 gen_helper_v7m_msr(cpu_env, addr, tmp);
7942 tcg_temp_free_i32(addr);
7943 dead_tmp(tmp);
7944 gen_lookup_tb(s);
7945 break;
7947 /* fall through */
7948 case 1: /* msr spsr. */
7949 if (IS_M(env))
7950 goto illegal_op;
7951 tmp = load_reg(s, rn);
7952 if (gen_set_psr(s,
7953 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7954 op == 1, tmp))
7955 goto illegal_op;
7956 break;
7957 case 2: /* cps, nop-hint. */
7958 if (((insn >> 8) & 7) == 0) {
7959 gen_nop_hint(s, insn & 0xff);
7961 /* Implemented as NOP in user mode. */
7962 if (IS_USER(s))
7963 break;
7964 offset = 0;
7965 imm = 0;
7966 if (insn & (1 << 10)) {
7967 if (insn & (1 << 7))
7968 offset |= CPSR_A;
7969 if (insn & (1 << 6))
7970 offset |= CPSR_I;
7971 if (insn & (1 << 5))
7972 offset |= CPSR_F;
7973 if (insn & (1 << 9))
7974 imm = CPSR_A | CPSR_I | CPSR_F;
7976 if (insn & (1 << 8)) {
7977 offset |= 0x1f;
7978 imm |= (insn & 0x1f);
7980 if (offset) {
7981 gen_set_psr_im(s, offset, 0, imm);
7983 break;
7984 case 3: /* Special control operations. */
7985 ARCH(7);
7986 op = (insn >> 4) & 0xf;
7987 switch (op) {
7988 case 2: /* clrex */
7989 gen_clrex(s);
7990 break;
7991 case 4: /* dsb */
7992 case 5: /* dmb */
7993 case 6: /* isb */
7994 /* These execute as NOPs. */
7995 break;
7996 default:
7997 goto illegal_op;
7999 break;
8000 case 4: /* bxj */
8001 /* Trivial implementation equivalent to bx. */
8002 tmp = load_reg(s, rn);
8003 gen_bx(s, tmp);
8004 break;
8005 case 5: /* Exception return. */
8006 if (IS_USER(s)) {
8007 goto illegal_op;
8009 if (rn != 14 || rd != 15) {
8010 goto illegal_op;
8012 tmp = load_reg(s, rn);
8013 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8014 gen_exception_return(s, tmp);
8015 break;
8016 case 6: /* mrs cpsr. */
8017 tmp = new_tmp();
8018 if (IS_M(env)) {
8019 addr = tcg_const_i32(insn & 0xff);
8020 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8021 tcg_temp_free_i32(addr);
8022 } else {
8023 gen_helper_cpsr_read(tmp);
8025 store_reg(s, rd, tmp);
8026 break;
8027 case 7: /* mrs spsr. */
8028 /* Not accessible in user mode. */
8029 if (IS_USER(s) || IS_M(env))
8030 goto illegal_op;
8031 tmp = load_cpu_field(spsr);
8032 store_reg(s, rd, tmp);
8033 break;
8036 } else {
8037 /* Conditional branch. */
8038 op = (insn >> 22) & 0xf;
8039 /* Generate a conditional jump to next instruction. */
8040 s->condlabel = gen_new_label();
8041 gen_test_cc(op ^ 1, s->condlabel);
8042 s->condjmp = 1;
8044 /* offset[11:1] = insn[10:0] */
8045 offset = (insn & 0x7ff) << 1;
8046 /* offset[17:12] = insn[21:16]. */
8047 offset |= (insn & 0x003f0000) >> 4;
8048 /* offset[31:20] = insn[26]. */
8049 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8050 /* offset[18] = insn[13]. */
8051 offset |= (insn & (1 << 13)) << 5;
8052 /* offset[19] = insn[11]. */
8053 offset |= (insn & (1 << 11)) << 8;
8055 /* jump to the offset */
8056 gen_jmp(s, s->pc + offset);
8058 } else {
8059 /* Data processing immediate. */
8060 if (insn & (1 << 25)) {
8061 if (insn & (1 << 24)) {
8062 if (insn & (1 << 20))
8063 goto illegal_op;
8064 /* Bitfield/Saturate. */
8065 op = (insn >> 21) & 7;
8066 imm = insn & 0x1f;
8067 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8068 if (rn == 15) {
8069 tmp = new_tmp();
8070 tcg_gen_movi_i32(tmp, 0);
8071 } else {
8072 tmp = load_reg(s, rn);
8074 switch (op) {
8075 case 2: /* Signed bitfield extract. */
8076 imm++;
8077 if (shift + imm > 32)
8078 goto illegal_op;
8079 if (imm < 32)
8080 gen_sbfx(tmp, shift, imm);
8081 break;
8082 case 6: /* Unsigned bitfield extract. */
8083 imm++;
8084 if (shift + imm > 32)
8085 goto illegal_op;
8086 if (imm < 32)
8087 gen_ubfx(tmp, shift, (1u << imm) - 1);
8088 break;
8089 case 3: /* Bitfield insert/clear. */
8090 if (imm < shift)
8091 goto illegal_op;
8092 imm = imm + 1 - shift;
8093 if (imm != 32) {
8094 tmp2 = load_reg(s, rd);
8095 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8096 dead_tmp(tmp2);
8098 break;
8099 case 7:
8100 goto illegal_op;
8101 default: /* Saturate. */
8102 if (shift) {
8103 if (op & 1)
8104 tcg_gen_sari_i32(tmp, tmp, shift);
8105 else
8106 tcg_gen_shli_i32(tmp, tmp, shift);
8108 tmp2 = tcg_const_i32(imm);
8109 if (op & 4) {
8110 /* Unsigned. */
8111 if ((op & 1) && shift == 0)
8112 gen_helper_usat16(tmp, tmp, tmp2);
8113 else
8114 gen_helper_usat(tmp, tmp, tmp2);
8115 } else {
8116 /* Signed. */
8117 if ((op & 1) && shift == 0)
8118 gen_helper_ssat16(tmp, tmp, tmp2);
8119 else
8120 gen_helper_ssat(tmp, tmp, tmp2);
8122 tcg_temp_free_i32(tmp2);
8123 break;
8125 store_reg(s, rd, tmp);
8126 } else {
8127 imm = ((insn & 0x04000000) >> 15)
8128 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8129 if (insn & (1 << 22)) {
8130 /* 16-bit immediate. */
8131 imm |= (insn >> 4) & 0xf000;
8132 if (insn & (1 << 23)) {
8133 /* movt */
8134 tmp = load_reg(s, rd);
8135 tcg_gen_ext16u_i32(tmp, tmp);
8136 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8137 } else {
8138 /* movw */
8139 tmp = new_tmp();
8140 tcg_gen_movi_i32(tmp, imm);
8142 } else {
8143 /* Add/sub 12-bit immediate. */
8144 if (rn == 15) {
8145 offset = s->pc & ~(uint32_t)3;
8146 if (insn & (1 << 23))
8147 offset -= imm;
8148 else
8149 offset += imm;
8150 tmp = new_tmp();
8151 tcg_gen_movi_i32(tmp, offset);
8152 } else {
8153 tmp = load_reg(s, rn);
8154 if (insn & (1 << 23))
8155 tcg_gen_subi_i32(tmp, tmp, imm);
8156 else
8157 tcg_gen_addi_i32(tmp, tmp, imm);
8160 store_reg(s, rd, tmp);
8162 } else {
8163 int shifter_out = 0;
8164 /* modified 12-bit immediate. */
8165 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8166 imm = (insn & 0xff);
8167 switch (shift) {
8168 case 0: /* XY */
8169 /* Nothing to do. */
8170 break;
8171 case 1: /* 00XY00XY */
8172 imm |= imm << 16;
8173 break;
8174 case 2: /* XY00XY00 */
8175 imm |= imm << 16;
8176 imm <<= 8;
8177 break;
8178 case 3: /* XYXYXYXY */
8179 imm |= imm << 16;
8180 imm |= imm << 8;
8181 break;
8182 default: /* Rotated constant. */
8183 shift = (shift << 1) | (imm >> 7);
8184 imm |= 0x80;
8185 imm = imm << (32 - shift);
8186 shifter_out = 1;
8187 break;
8189 tmp2 = new_tmp();
8190 tcg_gen_movi_i32(tmp2, imm);
8191 rn = (insn >> 16) & 0xf;
8192 if (rn == 15) {
8193 tmp = new_tmp();
8194 tcg_gen_movi_i32(tmp, 0);
8195 } else {
8196 tmp = load_reg(s, rn);
8198 op = (insn >> 21) & 0xf;
8199 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8200 shifter_out, tmp, tmp2))
8201 goto illegal_op;
8202 dead_tmp(tmp2);
8203 rd = (insn >> 8) & 0xf;
8204 if (rd != 15) {
8205 store_reg(s, rd, tmp);
8206 } else {
8207 dead_tmp(tmp);
8211 break;
8212 case 12: /* Load/store single data item. */
8214 int postinc = 0;
8215 int writeback = 0;
8216 int user;
8217 if ((insn & 0x01100000) == 0x01000000) {
8218 if (disas_neon_ls_insn(env, s, insn))
8219 goto illegal_op;
8220 break;
8222 user = IS_USER(s);
8223 if (rn == 15) {
8224 addr = new_tmp();
8225 /* PC relative. */
8226 /* s->pc has already been incremented by 4. */
8227 imm = s->pc & 0xfffffffc;
8228 if (insn & (1 << 23))
8229 imm += insn & 0xfff;
8230 else
8231 imm -= insn & 0xfff;
8232 tcg_gen_movi_i32(addr, imm);
8233 } else {
8234 addr = load_reg(s, rn);
8235 if (insn & (1 << 23)) {
8236 /* Positive offset. */
8237 imm = insn & 0xfff;
8238 tcg_gen_addi_i32(addr, addr, imm);
8239 } else {
8240 op = (insn >> 8) & 7;
8241 imm = insn & 0xff;
8242 switch (op) {
8243 case 0: case 8: /* Shifted Register. */
8244 shift = (insn >> 4) & 0xf;
8245 if (shift > 3)
8246 goto illegal_op;
8247 tmp = load_reg(s, rm);
8248 if (shift)
8249 tcg_gen_shli_i32(tmp, tmp, shift);
8250 tcg_gen_add_i32(addr, addr, tmp);
8251 dead_tmp(tmp);
8252 break;
8253 case 4: /* Negative offset. */
8254 tcg_gen_addi_i32(addr, addr, -imm);
8255 break;
8256 case 6: /* User privilege. */
8257 tcg_gen_addi_i32(addr, addr, imm);
8258 user = 1;
8259 break;
8260 case 1: /* Post-decrement. */
8261 imm = -imm;
8262 /* Fall through. */
8263 case 3: /* Post-increment. */
8264 postinc = 1;
8265 writeback = 1;
8266 break;
8267 case 5: /* Pre-decrement. */
8268 imm = -imm;
8269 /* Fall through. */
8270 case 7: /* Pre-increment. */
8271 tcg_gen_addi_i32(addr, addr, imm);
8272 writeback = 1;
8273 break;
8274 default:
8275 goto illegal_op;
8279 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8280 if (insn & (1 << 20)) {
8281 /* Load. */
8282 if (rs == 15 && op != 2) {
8283 if (op & 2)
8284 goto illegal_op;
8285 /* Memory hint. Implemented as NOP. */
8286 } else {
8287 switch (op) {
8288 case 0: tmp = gen_ld8u(addr, user); break;
8289 case 4: tmp = gen_ld8s(addr, user); break;
8290 case 1: tmp = gen_ld16u(addr, user); break;
8291 case 5: tmp = gen_ld16s(addr, user); break;
8292 case 2: tmp = gen_ld32(addr, user); break;
8293 default: goto illegal_op;
8295 if (rs == 15) {
8296 gen_bx(s, tmp);
8297 } else {
8298 store_reg(s, rs, tmp);
8301 } else {
8302 /* Store. */
8303 if (rs == 15)
8304 goto illegal_op;
8305 tmp = load_reg(s, rs);
8306 switch (op) {
8307 case 0: gen_st8(tmp, addr, user); break;
8308 case 1: gen_st16(tmp, addr, user); break;
8309 case 2: gen_st32(tmp, addr, user); break;
8310 default: goto illegal_op;
8313 if (postinc)
8314 tcg_gen_addi_i32(addr, addr, imm);
8315 if (writeback) {
8316 store_reg(s, rn, addr);
8317 } else {
8318 dead_tmp(addr);
8321 break;
8322 default:
8323 goto illegal_op;
8325 return 0;
8326 illegal_op:
8327 return 1;
8330 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8332 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8333 int32_t offset;
8334 int i;
8335 TCGv tmp;
8336 TCGv tmp2;
8337 TCGv addr;
8339 if (s->condexec_mask) {
8340 cond = s->condexec_cond;
8341 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
8342 s->condlabel = gen_new_label();
8343 gen_test_cc(cond ^ 1, s->condlabel);
8344 s->condjmp = 1;
8348 insn = lduw_code(s->pc);
8349 s->pc += 2;
8351 switch (insn >> 12) {
8352 case 0: case 1:
8354 rd = insn & 7;
8355 op = (insn >> 11) & 3;
8356 if (op == 3) {
8357 /* add/subtract */
8358 rn = (insn >> 3) & 7;
8359 tmp = load_reg(s, rn);
8360 if (insn & (1 << 10)) {
8361 /* immediate */
8362 tmp2 = new_tmp();
8363 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8364 } else {
8365 /* reg */
8366 rm = (insn >> 6) & 7;
8367 tmp2 = load_reg(s, rm);
8369 if (insn & (1 << 9)) {
8370 if (s->condexec_mask)
8371 tcg_gen_sub_i32(tmp, tmp, tmp2);
8372 else
8373 gen_helper_sub_cc(tmp, tmp, tmp2);
8374 } else {
8375 if (s->condexec_mask)
8376 tcg_gen_add_i32(tmp, tmp, tmp2);
8377 else
8378 gen_helper_add_cc(tmp, tmp, tmp2);
8380 dead_tmp(tmp2);
8381 store_reg(s, rd, tmp);
8382 } else {
8383 /* shift immediate */
8384 rm = (insn >> 3) & 7;
8385 shift = (insn >> 6) & 0x1f;
8386 tmp = load_reg(s, rm);
8387 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8388 if (!s->condexec_mask)
8389 gen_logic_CC(tmp);
8390 store_reg(s, rd, tmp);
8392 break;
8393 case 2: case 3:
8394 /* arithmetic large immediate */
8395 op = (insn >> 11) & 3;
8396 rd = (insn >> 8) & 0x7;
8397 if (op == 0) { /* mov */
8398 tmp = new_tmp();
8399 tcg_gen_movi_i32(tmp, insn & 0xff);
8400 if (!s->condexec_mask)
8401 gen_logic_CC(tmp);
8402 store_reg(s, rd, tmp);
8403 } else {
8404 tmp = load_reg(s, rd);
8405 tmp2 = new_tmp();
8406 tcg_gen_movi_i32(tmp2, insn & 0xff);
8407 switch (op) {
8408 case 1: /* cmp */
8409 gen_helper_sub_cc(tmp, tmp, tmp2);
8410 dead_tmp(tmp);
8411 dead_tmp(tmp2);
8412 break;
8413 case 2: /* add */
8414 if (s->condexec_mask)
8415 tcg_gen_add_i32(tmp, tmp, tmp2);
8416 else
8417 gen_helper_add_cc(tmp, tmp, tmp2);
8418 dead_tmp(tmp2);
8419 store_reg(s, rd, tmp);
8420 break;
8421 case 3: /* sub */
8422 if (s->condexec_mask)
8423 tcg_gen_sub_i32(tmp, tmp, tmp2);
8424 else
8425 gen_helper_sub_cc(tmp, tmp, tmp2);
8426 dead_tmp(tmp2);
8427 store_reg(s, rd, tmp);
8428 break;
8431 break;
8432 case 4:
8433 if (insn & (1 << 11)) {
8434 rd = (insn >> 8) & 7;
8435 /* load pc-relative. Bit 1 of PC is ignored. */
8436 val = s->pc + 2 + ((insn & 0xff) * 4);
8437 val &= ~(uint32_t)2;
8438 addr = new_tmp();
8439 tcg_gen_movi_i32(addr, val);
8440 tmp = gen_ld32(addr, IS_USER(s));
8441 dead_tmp(addr);
8442 store_reg(s, rd, tmp);
8443 break;
8445 if (insn & (1 << 10)) {
8446 /* data processing extended or blx */
8447 rd = (insn & 7) | ((insn >> 4) & 8);
8448 rm = (insn >> 3) & 0xf;
8449 op = (insn >> 8) & 3;
8450 switch (op) {
8451 case 0: /* add */
8452 tmp = load_reg(s, rd);
8453 tmp2 = load_reg(s, rm);
8454 tcg_gen_add_i32(tmp, tmp, tmp2);
8455 dead_tmp(tmp2);
8456 store_reg(s, rd, tmp);
8457 break;
8458 case 1: /* cmp */
8459 tmp = load_reg(s, rd);
8460 tmp2 = load_reg(s, rm);
8461 gen_helper_sub_cc(tmp, tmp, tmp2);
8462 dead_tmp(tmp2);
8463 dead_tmp(tmp);
8464 break;
8465 case 2: /* mov/cpy */
8466 tmp = load_reg(s, rm);
8467 store_reg(s, rd, tmp);
8468 break;
8469 case 3:/* branch [and link] exchange thumb register */
8470 tmp = load_reg(s, rm);
8471 if (insn & (1 << 7)) {
8472 val = (uint32_t)s->pc | 1;
8473 tmp2 = new_tmp();
8474 tcg_gen_movi_i32(tmp2, val);
8475 store_reg(s, 14, tmp2);
8477 gen_bx(s, tmp);
8478 break;
8480 break;
8483 /* data processing register */
8484 rd = insn & 7;
8485 rm = (insn >> 3) & 7;
8486 op = (insn >> 6) & 0xf;
8487 if (op == 2 || op == 3 || op == 4 || op == 7) {
8488 /* the shift/rotate ops want the operands backwards */
8489 val = rm;
8490 rm = rd;
8491 rd = val;
8492 val = 1;
8493 } else {
8494 val = 0;
8497 if (op == 9) { /* neg */
8498 tmp = new_tmp();
8499 tcg_gen_movi_i32(tmp, 0);
8500 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8501 tmp = load_reg(s, rd);
8502 } else {
8503 TCGV_UNUSED(tmp);
8506 tmp2 = load_reg(s, rm);
8507 switch (op) {
8508 case 0x0: /* and */
8509 tcg_gen_and_i32(tmp, tmp, tmp2);
8510 if (!s->condexec_mask)
8511 gen_logic_CC(tmp);
8512 break;
8513 case 0x1: /* eor */
8514 tcg_gen_xor_i32(tmp, tmp, tmp2);
8515 if (!s->condexec_mask)
8516 gen_logic_CC(tmp);
8517 break;
8518 case 0x2: /* lsl */
8519 if (s->condexec_mask) {
8520 gen_helper_shl(tmp2, tmp2, tmp);
8521 } else {
8522 gen_helper_shl_cc(tmp2, tmp2, tmp);
8523 gen_logic_CC(tmp2);
8525 break;
8526 case 0x3: /* lsr */
8527 if (s->condexec_mask) {
8528 gen_helper_shr(tmp2, tmp2, tmp);
8529 } else {
8530 gen_helper_shr_cc(tmp2, tmp2, tmp);
8531 gen_logic_CC(tmp2);
8533 break;
8534 case 0x4: /* asr */
8535 if (s->condexec_mask) {
8536 gen_helper_sar(tmp2, tmp2, tmp);
8537 } else {
8538 gen_helper_sar_cc(tmp2, tmp2, tmp);
8539 gen_logic_CC(tmp2);
8541 break;
8542 case 0x5: /* adc */
8543 if (s->condexec_mask)
8544 gen_adc(tmp, tmp2);
8545 else
8546 gen_helper_adc_cc(tmp, tmp, tmp2);
8547 break;
8548 case 0x6: /* sbc */
8549 if (s->condexec_mask)
8550 gen_sub_carry(tmp, tmp, tmp2);
8551 else
8552 gen_helper_sbc_cc(tmp, tmp, tmp2);
8553 break;
8554 case 0x7: /* ror */
8555 if (s->condexec_mask) {
8556 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8557 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8558 } else {
8559 gen_helper_ror_cc(tmp2, tmp2, tmp);
8560 gen_logic_CC(tmp2);
8562 break;
8563 case 0x8: /* tst */
8564 tcg_gen_and_i32(tmp, tmp, tmp2);
8565 gen_logic_CC(tmp);
8566 rd = 16;
8567 break;
8568 case 0x9: /* neg */
8569 if (s->condexec_mask)
8570 tcg_gen_neg_i32(tmp, tmp2);
8571 else
8572 gen_helper_sub_cc(tmp, tmp, tmp2);
8573 break;
8574 case 0xa: /* cmp */
8575 gen_helper_sub_cc(tmp, tmp, tmp2);
8576 rd = 16;
8577 break;
8578 case 0xb: /* cmn */
8579 gen_helper_add_cc(tmp, tmp, tmp2);
8580 rd = 16;
8581 break;
8582 case 0xc: /* orr */
8583 tcg_gen_or_i32(tmp, tmp, tmp2);
8584 if (!s->condexec_mask)
8585 gen_logic_CC(tmp);
8586 break;
8587 case 0xd: /* mul */
8588 tcg_gen_mul_i32(tmp, tmp, tmp2);
8589 if (!s->condexec_mask)
8590 gen_logic_CC(tmp);
8591 break;
8592 case 0xe: /* bic */
8593 tcg_gen_andc_i32(tmp, tmp, tmp2);
8594 if (!s->condexec_mask)
8595 gen_logic_CC(tmp);
8596 break;
8597 case 0xf: /* mvn */
8598 tcg_gen_not_i32(tmp2, tmp2);
8599 if (!s->condexec_mask)
8600 gen_logic_CC(tmp2);
8601 val = 1;
8602 rm = rd;
8603 break;
8605 if (rd != 16) {
8606 if (val) {
8607 store_reg(s, rm, tmp2);
8608 if (op != 0xf)
8609 dead_tmp(tmp);
8610 } else {
8611 store_reg(s, rd, tmp);
8612 dead_tmp(tmp2);
8614 } else {
8615 dead_tmp(tmp);
8616 dead_tmp(tmp2);
8618 break;
8620 case 5:
8621 /* load/store register offset. */
8622 rd = insn & 7;
8623 rn = (insn >> 3) & 7;
8624 rm = (insn >> 6) & 7;
8625 op = (insn >> 9) & 7;
8626 addr = load_reg(s, rn);
8627 tmp = load_reg(s, rm);
8628 tcg_gen_add_i32(addr, addr, tmp);
8629 dead_tmp(tmp);
8631 if (op < 3) /* store */
8632 tmp = load_reg(s, rd);
8634 switch (op) {
8635 case 0: /* str */
8636 gen_st32(tmp, addr, IS_USER(s));
8637 break;
8638 case 1: /* strh */
8639 gen_st16(tmp, addr, IS_USER(s));
8640 break;
8641 case 2: /* strb */
8642 gen_st8(tmp, addr, IS_USER(s));
8643 break;
8644 case 3: /* ldrsb */
8645 tmp = gen_ld8s(addr, IS_USER(s));
8646 break;
8647 case 4: /* ldr */
8648 tmp = gen_ld32(addr, IS_USER(s));
8649 break;
8650 case 5: /* ldrh */
8651 tmp = gen_ld16u(addr, IS_USER(s));
8652 break;
8653 case 6: /* ldrb */
8654 tmp = gen_ld8u(addr, IS_USER(s));
8655 break;
8656 case 7: /* ldrsh */
8657 tmp = gen_ld16s(addr, IS_USER(s));
8658 break;
8660 if (op >= 3) /* load */
8661 store_reg(s, rd, tmp);
8662 dead_tmp(addr);
8663 break;
8665 case 6:
8666 /* load/store word immediate offset */
8667 rd = insn & 7;
8668 rn = (insn >> 3) & 7;
8669 addr = load_reg(s, rn);
8670 val = (insn >> 4) & 0x7c;
8671 tcg_gen_addi_i32(addr, addr, val);
8673 if (insn & (1 << 11)) {
8674 /* load */
8675 tmp = gen_ld32(addr, IS_USER(s));
8676 store_reg(s, rd, tmp);
8677 } else {
8678 /* store */
8679 tmp = load_reg(s, rd);
8680 gen_st32(tmp, addr, IS_USER(s));
8682 dead_tmp(addr);
8683 break;
8685 case 7:
8686 /* load/store byte immediate offset */
8687 rd = insn & 7;
8688 rn = (insn >> 3) & 7;
8689 addr = load_reg(s, rn);
8690 val = (insn >> 6) & 0x1f;
8691 tcg_gen_addi_i32(addr, addr, val);
8693 if (insn & (1 << 11)) {
8694 /* load */
8695 tmp = gen_ld8u(addr, IS_USER(s));
8696 store_reg(s, rd, tmp);
8697 } else {
8698 /* store */
8699 tmp = load_reg(s, rd);
8700 gen_st8(tmp, addr, IS_USER(s));
8702 dead_tmp(addr);
8703 break;
8705 case 8:
8706 /* load/store halfword immediate offset */
8707 rd = insn & 7;
8708 rn = (insn >> 3) & 7;
8709 addr = load_reg(s, rn);
8710 val = (insn >> 5) & 0x3e;
8711 tcg_gen_addi_i32(addr, addr, val);
8713 if (insn & (1 << 11)) {
8714 /* load */
8715 tmp = gen_ld16u(addr, IS_USER(s));
8716 store_reg(s, rd, tmp);
8717 } else {
8718 /* store */
8719 tmp = load_reg(s, rd);
8720 gen_st16(tmp, addr, IS_USER(s));
8722 dead_tmp(addr);
8723 break;
8725 case 9:
8726 /* load/store from stack */
8727 rd = (insn >> 8) & 7;
8728 addr = load_reg(s, 13);
8729 val = (insn & 0xff) * 4;
8730 tcg_gen_addi_i32(addr, addr, val);
8732 if (insn & (1 << 11)) {
8733 /* load */
8734 tmp = gen_ld32(addr, IS_USER(s));
8735 store_reg(s, rd, tmp);
8736 } else {
8737 /* store */
8738 tmp = load_reg(s, rd);
8739 gen_st32(tmp, addr, IS_USER(s));
8741 dead_tmp(addr);
8742 break;
8744 case 10:
8745 /* add to high reg */
8746 rd = (insn >> 8) & 7;
8747 if (insn & (1 << 11)) {
8748 /* SP */
8749 tmp = load_reg(s, 13);
8750 } else {
8751 /* PC. bit 1 is ignored. */
8752 tmp = new_tmp();
8753 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8755 val = (insn & 0xff) * 4;
8756 tcg_gen_addi_i32(tmp, tmp, val);
8757 store_reg(s, rd, tmp);
8758 break;
8760 case 11:
8761 /* misc */
8762 op = (insn >> 8) & 0xf;
8763 switch (op) {
8764 case 0:
8765 /* adjust stack pointer */
8766 tmp = load_reg(s, 13);
8767 val = (insn & 0x7f) * 4;
8768 if (insn & (1 << 7))
8769 val = -(int32_t)val;
8770 tcg_gen_addi_i32(tmp, tmp, val);
8771 store_reg(s, 13, tmp);
8772 break;
8774 case 2: /* sign/zero extend. */
8775 ARCH(6);
8776 rd = insn & 7;
8777 rm = (insn >> 3) & 7;
8778 tmp = load_reg(s, rm);
8779 switch ((insn >> 6) & 3) {
8780 case 0: gen_sxth(tmp); break;
8781 case 1: gen_sxtb(tmp); break;
8782 case 2: gen_uxth(tmp); break;
8783 case 3: gen_uxtb(tmp); break;
8785 store_reg(s, rd, tmp);
8786 break;
8787 case 4: case 5: case 0xc: case 0xd:
8788 /* push/pop */
8789 addr = load_reg(s, 13);
8790 if (insn & (1 << 8))
8791 offset = 4;
8792 else
8793 offset = 0;
8794 for (i = 0; i < 8; i++) {
8795 if (insn & (1 << i))
8796 offset += 4;
8798 if ((insn & (1 << 11)) == 0) {
8799 tcg_gen_addi_i32(addr, addr, -offset);
8801 for (i = 0; i < 8; i++) {
8802 if (insn & (1 << i)) {
8803 if (insn & (1 << 11)) {
8804 /* pop */
8805 tmp = gen_ld32(addr, IS_USER(s));
8806 store_reg(s, i, tmp);
8807 } else {
8808 /* push */
8809 tmp = load_reg(s, i);
8810 gen_st32(tmp, addr, IS_USER(s));
8812 /* advance to the next address. */
8813 tcg_gen_addi_i32(addr, addr, 4);
8816 TCGV_UNUSED(tmp);
8817 if (insn & (1 << 8)) {
8818 if (insn & (1 << 11)) {
8819 /* pop pc */
8820 tmp = gen_ld32(addr, IS_USER(s));
8821 /* don't set the pc until the rest of the instruction
8822 has completed */
8823 } else {
8824 /* push lr */
8825 tmp = load_reg(s, 14);
8826 gen_st32(tmp, addr, IS_USER(s));
8828 tcg_gen_addi_i32(addr, addr, 4);
8830 if ((insn & (1 << 11)) == 0) {
8831 tcg_gen_addi_i32(addr, addr, -offset);
8833 /* write back the new stack pointer */
8834 store_reg(s, 13, addr);
8835 /* set the new PC value */
8836 if ((insn & 0x0900) == 0x0900)
8837 gen_bx(s, tmp);
8838 break;
8840 case 1: case 3: case 9: case 11: /* czb */
8841 rm = insn & 7;
8842 tmp = load_reg(s, rm);
8843 s->condlabel = gen_new_label();
8844 s->condjmp = 1;
8845 if (insn & (1 << 11))
8846 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8847 else
8848 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8849 dead_tmp(tmp);
8850 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8851 val = (uint32_t)s->pc + 2;
8852 val += offset;
8853 gen_jmp(s, val);
8854 break;
8856 case 15: /* IT, nop-hint. */
8857 if ((insn & 0xf) == 0) {
8858 gen_nop_hint(s, (insn >> 4) & 0xf);
8859 break;
8861 /* If Then. */
8862 s->condexec_cond = (insn >> 4) & 0xe;
8863 s->condexec_mask = insn & 0x1f;
8864 /* No actual code generated for this insn, just setup state. */
8865 break;
8867 case 0xe: /* bkpt */
8868 gen_set_condexec(s);
8869 gen_set_pc_im(s->pc - 2);
8870 gen_exception(EXCP_BKPT);
8871 s->is_jmp = DISAS_JUMP;
8872 break;
8874 case 0xa: /* rev */
8875 ARCH(6);
8876 rn = (insn >> 3) & 0x7;
8877 rd = insn & 0x7;
8878 tmp = load_reg(s, rn);
8879 switch ((insn >> 6) & 3) {
8880 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8881 case 1: gen_rev16(tmp); break;
8882 case 3: gen_revsh(tmp); break;
8883 default: goto illegal_op;
8885 store_reg(s, rd, tmp);
8886 break;
8888 case 6: /* cps */
8889 ARCH(6);
8890 if (IS_USER(s))
8891 break;
8892 if (IS_M(env)) {
8893 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8894 /* PRIMASK */
8895 if (insn & 1) {
8896 addr = tcg_const_i32(16);
8897 gen_helper_v7m_msr(cpu_env, addr, tmp);
8898 tcg_temp_free_i32(addr);
8900 /* FAULTMASK */
8901 if (insn & 2) {
8902 addr = tcg_const_i32(17);
8903 gen_helper_v7m_msr(cpu_env, addr, tmp);
8904 tcg_temp_free_i32(addr);
8906 tcg_temp_free_i32(tmp);
8907 gen_lookup_tb(s);
8908 } else {
8909 if (insn & (1 << 4))
8910 shift = CPSR_A | CPSR_I | CPSR_F;
8911 else
8912 shift = 0;
8913 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8915 break;
8917 default:
8918 goto undef;
8920 break;
8922 case 12:
8923 /* load/store multiple */
8924 rn = (insn >> 8) & 0x7;
8925 addr = load_reg(s, rn);
8926 for (i = 0; i < 8; i++) {
8927 if (insn & (1 << i)) {
8928 if (insn & (1 << 11)) {
8929 /* load */
8930 tmp = gen_ld32(addr, IS_USER(s));
8931 store_reg(s, i, tmp);
8932 } else {
8933 /* store */
8934 tmp = load_reg(s, i);
8935 gen_st32(tmp, addr, IS_USER(s));
8937 /* advance to the next address */
8938 tcg_gen_addi_i32(addr, addr, 4);
8941 /* Base register writeback. */
8942 if ((insn & (1 << rn)) == 0) {
8943 store_reg(s, rn, addr);
8944 } else {
8945 dead_tmp(addr);
8947 break;
8949 case 13:
8950 /* conditional branch or swi */
8951 cond = (insn >> 8) & 0xf;
8952 if (cond == 0xe)
8953 goto undef;
8955 if (cond == 0xf) {
8956 /* swi */
8957 gen_set_condexec(s);
8958 gen_set_pc_im(s->pc);
8959 s->is_jmp = DISAS_SWI;
8960 break;
8962 /* generate a conditional jump to next instruction */
8963 s->condlabel = gen_new_label();
8964 gen_test_cc(cond ^ 1, s->condlabel);
8965 s->condjmp = 1;
8967 /* jump to the offset */
8968 val = (uint32_t)s->pc + 2;
8969 offset = ((int32_t)insn << 24) >> 24;
8970 val += offset << 1;
8971 gen_jmp(s, val);
8972 break;
8974 case 14:
8975 if (insn & (1 << 11)) {
8976 if (disas_thumb2_insn(env, s, insn))
8977 goto undef32;
8978 break;
8980 /* unconditional branch */
8981 val = (uint32_t)s->pc;
8982 offset = ((int32_t)insn << 21) >> 21;
8983 val += (offset << 1) + 2;
8984 gen_jmp(s, val);
8985 break;
8987 case 15:
8988 if (disas_thumb2_insn(env, s, insn))
8989 goto undef32;
8990 break;
8992 return;
8993 undef32:
8994 gen_set_condexec(s);
8995 gen_set_pc_im(s->pc - 4);
8996 gen_exception(EXCP_UDEF);
8997 s->is_jmp = DISAS_JUMP;
8998 return;
8999 illegal_op:
9000 undef:
9001 gen_set_condexec(s);
9002 gen_set_pc_im(s->pc - 2);
9003 gen_exception(EXCP_UDEF);
9004 s->is_jmp = DISAS_JUMP;
9007 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9008 basic block 'tb'. If search_pc is TRUE, also generate PC
9009 information for each intermediate instruction. */
9010 static inline void gen_intermediate_code_internal(CPUState *env,
9011 TranslationBlock *tb,
9012 int search_pc)
9014 DisasContext dc1, *dc = &dc1;
9015 CPUBreakpoint *bp;
9016 uint16_t *gen_opc_end;
9017 int j, lj;
9018 target_ulong pc_start;
9019 uint32_t next_page_start;
9020 int num_insns;
9021 int max_insns;
9023 /* generate intermediate code */
9024 num_temps = 0;
9026 pc_start = tb->pc;
9028 dc->tb = tb;
9030 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9032 dc->is_jmp = DISAS_NEXT;
9033 dc->pc = pc_start;
9034 dc->singlestep_enabled = env->singlestep_enabled;
9035 dc->condjmp = 0;
9036 dc->thumb = env->thumb;
9037 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
9038 dc->condexec_cond = env->condexec_bits >> 4;
9039 #if !defined(CONFIG_USER_ONLY)
9040 if (IS_M(env)) {
9041 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
9042 } else {
9043 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
9045 #endif
9046 cpu_F0s = tcg_temp_new_i32();
9047 cpu_F1s = tcg_temp_new_i32();
9048 cpu_F0d = tcg_temp_new_i64();
9049 cpu_F1d = tcg_temp_new_i64();
9050 cpu_V0 = cpu_F0d;
9051 cpu_V1 = cpu_F1d;
9052 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9053 cpu_M0 = tcg_temp_new_i64();
9054 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9055 lj = -1;
9056 num_insns = 0;
9057 max_insns = tb->cflags & CF_COUNT_MASK;
9058 if (max_insns == 0)
9059 max_insns = CF_COUNT_MASK;
9061 gen_icount_start();
9062 /* Reset the conditional execution bits immediately. This avoids
9063 complications trying to do it at the end of the block. */
9064 if (env->condexec_bits)
9066 TCGv tmp = new_tmp();
9067 tcg_gen_movi_i32(tmp, 0);
9068 store_cpu_field(tmp, condexec_bits);
9070 do {
9071 #ifdef CONFIG_USER_ONLY
9072 /* Intercept jump to the magic kernel page. */
9073 if (dc->pc >= 0xffff0000) {
9074 /* We always get here via a jump, so know we are not in a
9075 conditional execution block. */
9076 gen_exception(EXCP_KERNEL_TRAP);
9077 dc->is_jmp = DISAS_UPDATE;
9078 break;
9080 #else
9081 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9082 /* We always get here via a jump, so know we are not in a
9083 conditional execution block. */
9084 gen_exception(EXCP_EXCEPTION_EXIT);
9085 dc->is_jmp = DISAS_UPDATE;
9086 break;
9088 #endif
9090 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9091 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9092 if (bp->pc == dc->pc) {
9093 gen_set_condexec(dc);
9094 gen_set_pc_im(dc->pc);
9095 gen_exception(EXCP_DEBUG);
9096 dc->is_jmp = DISAS_JUMP;
9097 /* Advance PC so that clearing the breakpoint will
9098 invalidate this TB. */
9099 dc->pc += 2;
9100 goto done_generating;
9101 break;
9105 if (search_pc) {
9106 j = gen_opc_ptr - gen_opc_buf;
9107 if (lj < j) {
9108 lj++;
9109 while (lj < j)
9110 gen_opc_instr_start[lj++] = 0;
9112 gen_opc_pc[lj] = dc->pc;
9113 gen_opc_instr_start[lj] = 1;
9114 gen_opc_icount[lj] = num_insns;
9117 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9118 gen_io_start();
9120 if (env->thumb) {
9121 disas_thumb_insn(env, dc);
9122 if (dc->condexec_mask) {
9123 dc->condexec_cond = (dc->condexec_cond & 0xe)
9124 | ((dc->condexec_mask >> 4) & 1);
9125 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9126 if (dc->condexec_mask == 0) {
9127 dc->condexec_cond = 0;
9130 } else {
9131 disas_arm_insn(env, dc);
9133 if (num_temps) {
9134 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
9135 num_temps = 0;
9138 if (dc->condjmp && !dc->is_jmp) {
9139 gen_set_label(dc->condlabel);
9140 dc->condjmp = 0;
9142 /* Translation stops when a conditional branch is encountered.
9143 * Otherwise the subsequent code could get translated several times.
9144 * Also stop translation when a page boundary is reached. This
9145 * ensures prefetch aborts occur at the right place. */
9146 num_insns ++;
9147 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9148 !env->singlestep_enabled &&
9149 !singlestep &&
9150 dc->pc < next_page_start &&
9151 num_insns < max_insns);
9153 if (tb->cflags & CF_LAST_IO) {
9154 if (dc->condjmp) {
9155 /* FIXME: This can theoretically happen with self-modifying
9156 code. */
9157 cpu_abort(env, "IO on conditional branch instruction");
9159 gen_io_end();
9162 /* At this stage dc->condjmp will only be set when the skipped
9163 instruction was a conditional branch or trap, and the PC has
9164 already been written. */
9165 if (unlikely(env->singlestep_enabled)) {
9166 /* Make sure the pc is updated, and raise a debug exception. */
9167 if (dc->condjmp) {
9168 gen_set_condexec(dc);
9169 if (dc->is_jmp == DISAS_SWI) {
9170 gen_exception(EXCP_SWI);
9171 } else {
9172 gen_exception(EXCP_DEBUG);
9174 gen_set_label(dc->condlabel);
9176 if (dc->condjmp || !dc->is_jmp) {
9177 gen_set_pc_im(dc->pc);
9178 dc->condjmp = 0;
9180 gen_set_condexec(dc);
9181 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9182 gen_exception(EXCP_SWI);
9183 } else {
9184 /* FIXME: Single stepping a WFI insn will not halt
9185 the CPU. */
9186 gen_exception(EXCP_DEBUG);
9188 } else {
9189 /* While branches must always occur at the end of an IT block,
9190 there are a few other things that can cause us to terminate
9191 the TB in the middel of an IT block:
9192 - Exception generating instructions (bkpt, swi, undefined).
9193 - Page boundaries.
9194 - Hardware watchpoints.
9195 Hardware breakpoints have already been handled and skip this code.
9197 gen_set_condexec(dc);
9198 switch(dc->is_jmp) {
9199 case DISAS_NEXT:
9200 gen_goto_tb(dc, 1, dc->pc);
9201 break;
9202 default:
9203 case DISAS_JUMP:
9204 case DISAS_UPDATE:
9205 /* indicate that the hash table must be used to find the next TB */
9206 tcg_gen_exit_tb(0);
9207 break;
9208 case DISAS_TB_JUMP:
9209 /* nothing more to generate */
9210 break;
9211 case DISAS_WFI:
9212 gen_helper_wfi();
9213 break;
9214 case DISAS_SWI:
9215 gen_exception(EXCP_SWI);
9216 break;
9218 if (dc->condjmp) {
9219 gen_set_label(dc->condlabel);
9220 gen_set_condexec(dc);
9221 gen_goto_tb(dc, 1, dc->pc);
9222 dc->condjmp = 0;
9226 done_generating:
9227 gen_icount_end(tb, num_insns);
9228 *gen_opc_ptr = INDEX_op_end;
9230 #ifdef DEBUG_DISAS
9231 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9232 qemu_log("----------------\n");
9233 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9234 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9235 qemu_log("\n");
9237 #endif
9238 if (search_pc) {
9239 j = gen_opc_ptr - gen_opc_buf;
9240 lj++;
9241 while (lj <= j)
9242 gen_opc_instr_start[lj++] = 0;
9243 } else {
9244 tb->size = dc->pc - pc_start;
9245 tb->icount = num_insns;
9249 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9251 gen_intermediate_code_internal(env, tb, 0);
9254 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9256 gen_intermediate_code_internal(env, tb, 1);
9259 static const char *cpu_mode_names[16] = {
9260 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9261 "???", "???", "???", "und", "???", "???", "???", "sys"
9264 void cpu_dump_state(CPUState *env, FILE *f,
9265 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9266 int flags)
9268 int i;
9269 #if 0
9270 union {
9271 uint32_t i;
9272 float s;
9273 } s0, s1;
9274 CPU_DoubleU d;
9275 /* ??? This assumes float64 and double have the same layout.
9276 Oh well, it's only debug dumps. */
9277 union {
9278 float64 f64;
9279 double d;
9280 } d0;
9281 #endif
9282 uint32_t psr;
9284 for(i=0;i<16;i++) {
9285 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9286 if ((i % 4) == 3)
9287 cpu_fprintf(f, "\n");
9288 else
9289 cpu_fprintf(f, " ");
9291 psr = cpsr_read(env);
9292 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9293 psr,
9294 psr & (1 << 31) ? 'N' : '-',
9295 psr & (1 << 30) ? 'Z' : '-',
9296 psr & (1 << 29) ? 'C' : '-',
9297 psr & (1 << 28) ? 'V' : '-',
9298 psr & CPSR_T ? 'T' : 'A',
9299 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9301 #if 0
9302 for (i = 0; i < 16; i++) {
9303 d.d = env->vfp.regs[i];
9304 s0.i = d.l.lower;
9305 s1.i = d.l.upper;
9306 d0.f64 = d.d;
9307 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9308 i * 2, (int)s0.i, s0.s,
9309 i * 2 + 1, (int)s1.i, s1.s,
9310 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9311 d0.d);
9313 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9314 #endif
9317 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9318 unsigned long searched_pc, int pc_pos, void *puc)
9320 env->regs[15] = gen_opc_pc[pc_pos];