Merge remote branch 'qemu-kvm/uq/master' into staging
[qemu/aliguori-queue.git] / target-arm / translate.c
blob8b3b12d67e4f674b7d78a460156202947f03a9e9
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]));
1136 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1138 iwmmxt_store_reg(cpu_M0, rn);
1141 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1143 iwmmxt_load_reg(cpu_M0, rn);
1146 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1148 iwmmxt_load_reg(cpu_V1, rn);
1149 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1152 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1154 iwmmxt_load_reg(cpu_V1, rn);
1155 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1158 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1160 iwmmxt_load_reg(cpu_V1, rn);
1161 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1164 #define IWMMXT_OP(name) \
1165 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1167 iwmmxt_load_reg(cpu_V1, rn); \
1168 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1171 #define IWMMXT_OP_ENV(name) \
1172 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1174 iwmmxt_load_reg(cpu_V1, rn); \
1175 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1178 #define IWMMXT_OP_ENV_SIZE(name) \
1179 IWMMXT_OP_ENV(name##b) \
1180 IWMMXT_OP_ENV(name##w) \
1181 IWMMXT_OP_ENV(name##l)
1183 #define IWMMXT_OP_ENV1(name) \
1184 static inline void gen_op_iwmmxt_##name##_M0(void) \
1186 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1189 IWMMXT_OP(maddsq)
1190 IWMMXT_OP(madduq)
1191 IWMMXT_OP(sadb)
1192 IWMMXT_OP(sadw)
1193 IWMMXT_OP(mulslw)
1194 IWMMXT_OP(mulshw)
1195 IWMMXT_OP(mululw)
1196 IWMMXT_OP(muluhw)
1197 IWMMXT_OP(macsw)
1198 IWMMXT_OP(macuw)
1200 IWMMXT_OP_ENV_SIZE(unpackl)
1201 IWMMXT_OP_ENV_SIZE(unpackh)
1203 IWMMXT_OP_ENV1(unpacklub)
1204 IWMMXT_OP_ENV1(unpackluw)
1205 IWMMXT_OP_ENV1(unpacklul)
1206 IWMMXT_OP_ENV1(unpackhub)
1207 IWMMXT_OP_ENV1(unpackhuw)
1208 IWMMXT_OP_ENV1(unpackhul)
1209 IWMMXT_OP_ENV1(unpacklsb)
1210 IWMMXT_OP_ENV1(unpacklsw)
1211 IWMMXT_OP_ENV1(unpacklsl)
1212 IWMMXT_OP_ENV1(unpackhsb)
1213 IWMMXT_OP_ENV1(unpackhsw)
1214 IWMMXT_OP_ENV1(unpackhsl)
1216 IWMMXT_OP_ENV_SIZE(cmpeq)
1217 IWMMXT_OP_ENV_SIZE(cmpgtu)
1218 IWMMXT_OP_ENV_SIZE(cmpgts)
1220 IWMMXT_OP_ENV_SIZE(mins)
1221 IWMMXT_OP_ENV_SIZE(minu)
1222 IWMMXT_OP_ENV_SIZE(maxs)
1223 IWMMXT_OP_ENV_SIZE(maxu)
1225 IWMMXT_OP_ENV_SIZE(subn)
1226 IWMMXT_OP_ENV_SIZE(addn)
1227 IWMMXT_OP_ENV_SIZE(subu)
1228 IWMMXT_OP_ENV_SIZE(addu)
1229 IWMMXT_OP_ENV_SIZE(subs)
1230 IWMMXT_OP_ENV_SIZE(adds)
1232 IWMMXT_OP_ENV(avgb0)
1233 IWMMXT_OP_ENV(avgb1)
1234 IWMMXT_OP_ENV(avgw0)
1235 IWMMXT_OP_ENV(avgw1)
1237 IWMMXT_OP(msadb)
1239 IWMMXT_OP_ENV(packuw)
1240 IWMMXT_OP_ENV(packul)
1241 IWMMXT_OP_ENV(packuq)
1242 IWMMXT_OP_ENV(packsw)
1243 IWMMXT_OP_ENV(packsl)
1244 IWMMXT_OP_ENV(packsq)
1246 static void gen_op_iwmmxt_set_mup(void)
1248 TCGv tmp;
1249 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1250 tcg_gen_ori_i32(tmp, tmp, 2);
1251 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1254 static void gen_op_iwmmxt_set_cup(void)
1256 TCGv tmp;
1257 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1258 tcg_gen_ori_i32(tmp, tmp, 1);
1259 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1262 static void gen_op_iwmmxt_setpsr_nz(void)
1264 TCGv tmp = new_tmp();
1265 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1266 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1269 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1271 iwmmxt_load_reg(cpu_V1, rn);
1272 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1273 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1276 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1278 int rd;
1279 uint32_t offset;
1280 TCGv tmp;
1282 rd = (insn >> 16) & 0xf;
1283 tmp = load_reg(s, rd);
1285 offset = (insn & 0xff) << ((insn >> 7) & 2);
1286 if (insn & (1 << 24)) {
1287 /* Pre indexed */
1288 if (insn & (1 << 23))
1289 tcg_gen_addi_i32(tmp, tmp, offset);
1290 else
1291 tcg_gen_addi_i32(tmp, tmp, -offset);
1292 tcg_gen_mov_i32(dest, tmp);
1293 if (insn & (1 << 21))
1294 store_reg(s, rd, tmp);
1295 else
1296 dead_tmp(tmp);
1297 } else if (insn & (1 << 21)) {
1298 /* Post indexed */
1299 tcg_gen_mov_i32(dest, tmp);
1300 if (insn & (1 << 23))
1301 tcg_gen_addi_i32(tmp, tmp, offset);
1302 else
1303 tcg_gen_addi_i32(tmp, tmp, -offset);
1304 store_reg(s, rd, tmp);
1305 } else if (!(insn & (1 << 23)))
1306 return 1;
1307 return 0;
1310 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1312 int rd = (insn >> 0) & 0xf;
1313 TCGv tmp;
1315 if (insn & (1 << 8)) {
1316 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1317 return 1;
1318 } else {
1319 tmp = iwmmxt_load_creg(rd);
1321 } else {
1322 tmp = new_tmp();
1323 iwmmxt_load_reg(cpu_V0, rd);
1324 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1326 tcg_gen_andi_i32(tmp, tmp, mask);
1327 tcg_gen_mov_i32(dest, tmp);
1328 dead_tmp(tmp);
1329 return 0;
1332 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1333 (ie. an undefined instruction). */
1334 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1336 int rd, wrd;
1337 int rdhi, rdlo, rd0, rd1, i;
1338 TCGv addr;
1339 TCGv tmp, tmp2, tmp3;
1341 if ((insn & 0x0e000e00) == 0x0c000000) {
1342 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1343 wrd = insn & 0xf;
1344 rdlo = (insn >> 12) & 0xf;
1345 rdhi = (insn >> 16) & 0xf;
1346 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1347 iwmmxt_load_reg(cpu_V0, wrd);
1348 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1349 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1350 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1351 } else { /* TMCRR */
1352 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1353 iwmmxt_store_reg(cpu_V0, wrd);
1354 gen_op_iwmmxt_set_mup();
1356 return 0;
1359 wrd = (insn >> 12) & 0xf;
1360 addr = new_tmp();
1361 if (gen_iwmmxt_address(s, insn, addr)) {
1362 dead_tmp(addr);
1363 return 1;
1365 if (insn & ARM_CP_RW_BIT) {
1366 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1367 tmp = new_tmp();
1368 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1369 iwmmxt_store_creg(wrd, tmp);
1370 } else {
1371 i = 1;
1372 if (insn & (1 << 8)) {
1373 if (insn & (1 << 22)) { /* WLDRD */
1374 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1375 i = 0;
1376 } else { /* WLDRW wRd */
1377 tmp = gen_ld32(addr, IS_USER(s));
1379 } else {
1380 if (insn & (1 << 22)) { /* WLDRH */
1381 tmp = gen_ld16u(addr, IS_USER(s));
1382 } else { /* WLDRB */
1383 tmp = gen_ld8u(addr, IS_USER(s));
1386 if (i) {
1387 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1388 dead_tmp(tmp);
1390 gen_op_iwmmxt_movq_wRn_M0(wrd);
1392 } else {
1393 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1394 tmp = iwmmxt_load_creg(wrd);
1395 gen_st32(tmp, addr, IS_USER(s));
1396 } else {
1397 gen_op_iwmmxt_movq_M0_wRn(wrd);
1398 tmp = new_tmp();
1399 if (insn & (1 << 8)) {
1400 if (insn & (1 << 22)) { /* WSTRD */
1401 dead_tmp(tmp);
1402 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1403 } else { /* WSTRW wRd */
1404 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1405 gen_st32(tmp, addr, IS_USER(s));
1407 } else {
1408 if (insn & (1 << 22)) { /* WSTRH */
1409 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1410 gen_st16(tmp, addr, IS_USER(s));
1411 } else { /* WSTRB */
1412 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1413 gen_st8(tmp, addr, IS_USER(s));
1418 return 0;
1421 if ((insn & 0x0f000000) != 0x0e000000)
1422 return 1;
1424 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1425 case 0x000: /* WOR */
1426 wrd = (insn >> 12) & 0xf;
1427 rd0 = (insn >> 0) & 0xf;
1428 rd1 = (insn >> 16) & 0xf;
1429 gen_op_iwmmxt_movq_M0_wRn(rd0);
1430 gen_op_iwmmxt_orq_M0_wRn(rd1);
1431 gen_op_iwmmxt_setpsr_nz();
1432 gen_op_iwmmxt_movq_wRn_M0(wrd);
1433 gen_op_iwmmxt_set_mup();
1434 gen_op_iwmmxt_set_cup();
1435 break;
1436 case 0x011: /* TMCR */
1437 if (insn & 0xf)
1438 return 1;
1439 rd = (insn >> 12) & 0xf;
1440 wrd = (insn >> 16) & 0xf;
1441 switch (wrd) {
1442 case ARM_IWMMXT_wCID:
1443 case ARM_IWMMXT_wCASF:
1444 break;
1445 case ARM_IWMMXT_wCon:
1446 gen_op_iwmmxt_set_cup();
1447 /* Fall through. */
1448 case ARM_IWMMXT_wCSSF:
1449 tmp = iwmmxt_load_creg(wrd);
1450 tmp2 = load_reg(s, rd);
1451 tcg_gen_andc_i32(tmp, tmp, tmp2);
1452 dead_tmp(tmp2);
1453 iwmmxt_store_creg(wrd, tmp);
1454 break;
1455 case ARM_IWMMXT_wCGR0:
1456 case ARM_IWMMXT_wCGR1:
1457 case ARM_IWMMXT_wCGR2:
1458 case ARM_IWMMXT_wCGR3:
1459 gen_op_iwmmxt_set_cup();
1460 tmp = load_reg(s, rd);
1461 iwmmxt_store_creg(wrd, tmp);
1462 break;
1463 default:
1464 return 1;
1466 break;
1467 case 0x100: /* WXOR */
1468 wrd = (insn >> 12) & 0xf;
1469 rd0 = (insn >> 0) & 0xf;
1470 rd1 = (insn >> 16) & 0xf;
1471 gen_op_iwmmxt_movq_M0_wRn(rd0);
1472 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1473 gen_op_iwmmxt_setpsr_nz();
1474 gen_op_iwmmxt_movq_wRn_M0(wrd);
1475 gen_op_iwmmxt_set_mup();
1476 gen_op_iwmmxt_set_cup();
1477 break;
1478 case 0x111: /* TMRC */
1479 if (insn & 0xf)
1480 return 1;
1481 rd = (insn >> 12) & 0xf;
1482 wrd = (insn >> 16) & 0xf;
1483 tmp = iwmmxt_load_creg(wrd);
1484 store_reg(s, rd, tmp);
1485 break;
1486 case 0x300: /* WANDN */
1487 wrd = (insn >> 12) & 0xf;
1488 rd0 = (insn >> 0) & 0xf;
1489 rd1 = (insn >> 16) & 0xf;
1490 gen_op_iwmmxt_movq_M0_wRn(rd0);
1491 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1492 gen_op_iwmmxt_andq_M0_wRn(rd1);
1493 gen_op_iwmmxt_setpsr_nz();
1494 gen_op_iwmmxt_movq_wRn_M0(wrd);
1495 gen_op_iwmmxt_set_mup();
1496 gen_op_iwmmxt_set_cup();
1497 break;
1498 case 0x200: /* WAND */
1499 wrd = (insn >> 12) & 0xf;
1500 rd0 = (insn >> 0) & 0xf;
1501 rd1 = (insn >> 16) & 0xf;
1502 gen_op_iwmmxt_movq_M0_wRn(rd0);
1503 gen_op_iwmmxt_andq_M0_wRn(rd1);
1504 gen_op_iwmmxt_setpsr_nz();
1505 gen_op_iwmmxt_movq_wRn_M0(wrd);
1506 gen_op_iwmmxt_set_mup();
1507 gen_op_iwmmxt_set_cup();
1508 break;
1509 case 0x810: case 0xa10: /* WMADD */
1510 wrd = (insn >> 12) & 0xf;
1511 rd0 = (insn >> 0) & 0xf;
1512 rd1 = (insn >> 16) & 0xf;
1513 gen_op_iwmmxt_movq_M0_wRn(rd0);
1514 if (insn & (1 << 21))
1515 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1516 else
1517 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1518 gen_op_iwmmxt_movq_wRn_M0(wrd);
1519 gen_op_iwmmxt_set_mup();
1520 break;
1521 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1522 wrd = (insn >> 12) & 0xf;
1523 rd0 = (insn >> 16) & 0xf;
1524 rd1 = (insn >> 0) & 0xf;
1525 gen_op_iwmmxt_movq_M0_wRn(rd0);
1526 switch ((insn >> 22) & 3) {
1527 case 0:
1528 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1529 break;
1530 case 1:
1531 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1532 break;
1533 case 2:
1534 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1535 break;
1536 case 3:
1537 return 1;
1539 gen_op_iwmmxt_movq_wRn_M0(wrd);
1540 gen_op_iwmmxt_set_mup();
1541 gen_op_iwmmxt_set_cup();
1542 break;
1543 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1544 wrd = (insn >> 12) & 0xf;
1545 rd0 = (insn >> 16) & 0xf;
1546 rd1 = (insn >> 0) & 0xf;
1547 gen_op_iwmmxt_movq_M0_wRn(rd0);
1548 switch ((insn >> 22) & 3) {
1549 case 0:
1550 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1551 break;
1552 case 1:
1553 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1554 break;
1555 case 2:
1556 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1557 break;
1558 case 3:
1559 return 1;
1561 gen_op_iwmmxt_movq_wRn_M0(wrd);
1562 gen_op_iwmmxt_set_mup();
1563 gen_op_iwmmxt_set_cup();
1564 break;
1565 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1566 wrd = (insn >> 12) & 0xf;
1567 rd0 = (insn >> 16) & 0xf;
1568 rd1 = (insn >> 0) & 0xf;
1569 gen_op_iwmmxt_movq_M0_wRn(rd0);
1570 if (insn & (1 << 22))
1571 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1572 else
1573 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1574 if (!(insn & (1 << 20)))
1575 gen_op_iwmmxt_addl_M0_wRn(wrd);
1576 gen_op_iwmmxt_movq_wRn_M0(wrd);
1577 gen_op_iwmmxt_set_mup();
1578 break;
1579 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1580 wrd = (insn >> 12) & 0xf;
1581 rd0 = (insn >> 16) & 0xf;
1582 rd1 = (insn >> 0) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0);
1584 if (insn & (1 << 21)) {
1585 if (insn & (1 << 20))
1586 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1587 else
1588 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1589 } else {
1590 if (insn & (1 << 20))
1591 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1592 else
1593 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1595 gen_op_iwmmxt_movq_wRn_M0(wrd);
1596 gen_op_iwmmxt_set_mup();
1597 break;
1598 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1599 wrd = (insn >> 12) & 0xf;
1600 rd0 = (insn >> 16) & 0xf;
1601 rd1 = (insn >> 0) & 0xf;
1602 gen_op_iwmmxt_movq_M0_wRn(rd0);
1603 if (insn & (1 << 21))
1604 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1605 else
1606 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1607 if (!(insn & (1 << 20))) {
1608 iwmmxt_load_reg(cpu_V1, wrd);
1609 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1611 gen_op_iwmmxt_movq_wRn_M0(wrd);
1612 gen_op_iwmmxt_set_mup();
1613 break;
1614 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1615 wrd = (insn >> 12) & 0xf;
1616 rd0 = (insn >> 16) & 0xf;
1617 rd1 = (insn >> 0) & 0xf;
1618 gen_op_iwmmxt_movq_M0_wRn(rd0);
1619 switch ((insn >> 22) & 3) {
1620 case 0:
1621 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1622 break;
1623 case 1:
1624 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1625 break;
1626 case 2:
1627 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1628 break;
1629 case 3:
1630 return 1;
1632 gen_op_iwmmxt_movq_wRn_M0(wrd);
1633 gen_op_iwmmxt_set_mup();
1634 gen_op_iwmmxt_set_cup();
1635 break;
1636 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1637 wrd = (insn >> 12) & 0xf;
1638 rd0 = (insn >> 16) & 0xf;
1639 rd1 = (insn >> 0) & 0xf;
1640 gen_op_iwmmxt_movq_M0_wRn(rd0);
1641 if (insn & (1 << 22)) {
1642 if (insn & (1 << 20))
1643 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1644 else
1645 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1646 } else {
1647 if (insn & (1 << 20))
1648 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1649 else
1650 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1652 gen_op_iwmmxt_movq_wRn_M0(wrd);
1653 gen_op_iwmmxt_set_mup();
1654 gen_op_iwmmxt_set_cup();
1655 break;
1656 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1657 wrd = (insn >> 12) & 0xf;
1658 rd0 = (insn >> 16) & 0xf;
1659 rd1 = (insn >> 0) & 0xf;
1660 gen_op_iwmmxt_movq_M0_wRn(rd0);
1661 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1662 tcg_gen_andi_i32(tmp, tmp, 7);
1663 iwmmxt_load_reg(cpu_V1, rd1);
1664 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1665 dead_tmp(tmp);
1666 gen_op_iwmmxt_movq_wRn_M0(wrd);
1667 gen_op_iwmmxt_set_mup();
1668 break;
1669 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1670 if (((insn >> 6) & 3) == 3)
1671 return 1;
1672 rd = (insn >> 12) & 0xf;
1673 wrd = (insn >> 16) & 0xf;
1674 tmp = load_reg(s, rd);
1675 gen_op_iwmmxt_movq_M0_wRn(wrd);
1676 switch ((insn >> 6) & 3) {
1677 case 0:
1678 tmp2 = tcg_const_i32(0xff);
1679 tmp3 = tcg_const_i32((insn & 7) << 3);
1680 break;
1681 case 1:
1682 tmp2 = tcg_const_i32(0xffff);
1683 tmp3 = tcg_const_i32((insn & 3) << 4);
1684 break;
1685 case 2:
1686 tmp2 = tcg_const_i32(0xffffffff);
1687 tmp3 = tcg_const_i32((insn & 1) << 5);
1688 break;
1689 default:
1690 TCGV_UNUSED(tmp2);
1691 TCGV_UNUSED(tmp3);
1693 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1694 tcg_temp_free(tmp3);
1695 tcg_temp_free(tmp2);
1696 dead_tmp(tmp);
1697 gen_op_iwmmxt_movq_wRn_M0(wrd);
1698 gen_op_iwmmxt_set_mup();
1699 break;
1700 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1701 rd = (insn >> 12) & 0xf;
1702 wrd = (insn >> 16) & 0xf;
1703 if (rd == 15 || ((insn >> 22) & 3) == 3)
1704 return 1;
1705 gen_op_iwmmxt_movq_M0_wRn(wrd);
1706 tmp = new_tmp();
1707 switch ((insn >> 22) & 3) {
1708 case 0:
1709 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1710 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1711 if (insn & 8) {
1712 tcg_gen_ext8s_i32(tmp, tmp);
1713 } else {
1714 tcg_gen_andi_i32(tmp, tmp, 0xff);
1716 break;
1717 case 1:
1718 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1719 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1720 if (insn & 8) {
1721 tcg_gen_ext16s_i32(tmp, tmp);
1722 } else {
1723 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1725 break;
1726 case 2:
1727 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1728 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1729 break;
1731 store_reg(s, rd, tmp);
1732 break;
1733 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1734 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1735 return 1;
1736 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1737 switch ((insn >> 22) & 3) {
1738 case 0:
1739 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1740 break;
1741 case 1:
1742 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1743 break;
1744 case 2:
1745 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1746 break;
1748 tcg_gen_shli_i32(tmp, tmp, 28);
1749 gen_set_nzcv(tmp);
1750 dead_tmp(tmp);
1751 break;
1752 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1753 if (((insn >> 6) & 3) == 3)
1754 return 1;
1755 rd = (insn >> 12) & 0xf;
1756 wrd = (insn >> 16) & 0xf;
1757 tmp = load_reg(s, rd);
1758 switch ((insn >> 6) & 3) {
1759 case 0:
1760 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1761 break;
1762 case 1:
1763 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1764 break;
1765 case 2:
1766 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1767 break;
1769 dead_tmp(tmp);
1770 gen_op_iwmmxt_movq_wRn_M0(wrd);
1771 gen_op_iwmmxt_set_mup();
1772 break;
1773 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1774 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1775 return 1;
1776 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1777 tmp2 = new_tmp();
1778 tcg_gen_mov_i32(tmp2, tmp);
1779 switch ((insn >> 22) & 3) {
1780 case 0:
1781 for (i = 0; i < 7; i ++) {
1782 tcg_gen_shli_i32(tmp2, tmp2, 4);
1783 tcg_gen_and_i32(tmp, tmp, tmp2);
1785 break;
1786 case 1:
1787 for (i = 0; i < 3; i ++) {
1788 tcg_gen_shli_i32(tmp2, tmp2, 8);
1789 tcg_gen_and_i32(tmp, tmp, tmp2);
1791 break;
1792 case 2:
1793 tcg_gen_shli_i32(tmp2, tmp2, 16);
1794 tcg_gen_and_i32(tmp, tmp, tmp2);
1795 break;
1797 gen_set_nzcv(tmp);
1798 dead_tmp(tmp2);
1799 dead_tmp(tmp);
1800 break;
1801 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1802 wrd = (insn >> 12) & 0xf;
1803 rd0 = (insn >> 16) & 0xf;
1804 gen_op_iwmmxt_movq_M0_wRn(rd0);
1805 switch ((insn >> 22) & 3) {
1806 case 0:
1807 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1808 break;
1809 case 1:
1810 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1811 break;
1812 case 2:
1813 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1814 break;
1815 case 3:
1816 return 1;
1818 gen_op_iwmmxt_movq_wRn_M0(wrd);
1819 gen_op_iwmmxt_set_mup();
1820 break;
1821 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1822 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1823 return 1;
1824 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1825 tmp2 = new_tmp();
1826 tcg_gen_mov_i32(tmp2, tmp);
1827 switch ((insn >> 22) & 3) {
1828 case 0:
1829 for (i = 0; i < 7; i ++) {
1830 tcg_gen_shli_i32(tmp2, tmp2, 4);
1831 tcg_gen_or_i32(tmp, tmp, tmp2);
1833 break;
1834 case 1:
1835 for (i = 0; i < 3; i ++) {
1836 tcg_gen_shli_i32(tmp2, tmp2, 8);
1837 tcg_gen_or_i32(tmp, tmp, tmp2);
1839 break;
1840 case 2:
1841 tcg_gen_shli_i32(tmp2, tmp2, 16);
1842 tcg_gen_or_i32(tmp, tmp, tmp2);
1843 break;
1845 gen_set_nzcv(tmp);
1846 dead_tmp(tmp2);
1847 dead_tmp(tmp);
1848 break;
1849 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1850 rd = (insn >> 12) & 0xf;
1851 rd0 = (insn >> 16) & 0xf;
1852 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1853 return 1;
1854 gen_op_iwmmxt_movq_M0_wRn(rd0);
1855 tmp = new_tmp();
1856 switch ((insn >> 22) & 3) {
1857 case 0:
1858 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1859 break;
1860 case 1:
1861 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1862 break;
1863 case 2:
1864 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1865 break;
1867 store_reg(s, rd, tmp);
1868 break;
1869 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1870 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1871 wrd = (insn >> 12) & 0xf;
1872 rd0 = (insn >> 16) & 0xf;
1873 rd1 = (insn >> 0) & 0xf;
1874 gen_op_iwmmxt_movq_M0_wRn(rd0);
1875 switch ((insn >> 22) & 3) {
1876 case 0:
1877 if (insn & (1 << 21))
1878 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1879 else
1880 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1881 break;
1882 case 1:
1883 if (insn & (1 << 21))
1884 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1885 else
1886 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1887 break;
1888 case 2:
1889 if (insn & (1 << 21))
1890 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1891 else
1892 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1893 break;
1894 case 3:
1895 return 1;
1897 gen_op_iwmmxt_movq_wRn_M0(wrd);
1898 gen_op_iwmmxt_set_mup();
1899 gen_op_iwmmxt_set_cup();
1900 break;
1901 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1902 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1903 wrd = (insn >> 12) & 0xf;
1904 rd0 = (insn >> 16) & 0xf;
1905 gen_op_iwmmxt_movq_M0_wRn(rd0);
1906 switch ((insn >> 22) & 3) {
1907 case 0:
1908 if (insn & (1 << 21))
1909 gen_op_iwmmxt_unpacklsb_M0();
1910 else
1911 gen_op_iwmmxt_unpacklub_M0();
1912 break;
1913 case 1:
1914 if (insn & (1 << 21))
1915 gen_op_iwmmxt_unpacklsw_M0();
1916 else
1917 gen_op_iwmmxt_unpackluw_M0();
1918 break;
1919 case 2:
1920 if (insn & (1 << 21))
1921 gen_op_iwmmxt_unpacklsl_M0();
1922 else
1923 gen_op_iwmmxt_unpacklul_M0();
1924 break;
1925 case 3:
1926 return 1;
1928 gen_op_iwmmxt_movq_wRn_M0(wrd);
1929 gen_op_iwmmxt_set_mup();
1930 gen_op_iwmmxt_set_cup();
1931 break;
1932 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1933 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1934 wrd = (insn >> 12) & 0xf;
1935 rd0 = (insn >> 16) & 0xf;
1936 gen_op_iwmmxt_movq_M0_wRn(rd0);
1937 switch ((insn >> 22) & 3) {
1938 case 0:
1939 if (insn & (1 << 21))
1940 gen_op_iwmmxt_unpackhsb_M0();
1941 else
1942 gen_op_iwmmxt_unpackhub_M0();
1943 break;
1944 case 1:
1945 if (insn & (1 << 21))
1946 gen_op_iwmmxt_unpackhsw_M0();
1947 else
1948 gen_op_iwmmxt_unpackhuw_M0();
1949 break;
1950 case 2:
1951 if (insn & (1 << 21))
1952 gen_op_iwmmxt_unpackhsl_M0();
1953 else
1954 gen_op_iwmmxt_unpackhul_M0();
1955 break;
1956 case 3:
1957 return 1;
1959 gen_op_iwmmxt_movq_wRn_M0(wrd);
1960 gen_op_iwmmxt_set_mup();
1961 gen_op_iwmmxt_set_cup();
1962 break;
1963 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1964 case 0x214: case 0x614: case 0xa14: case 0xe14:
1965 if (((insn >> 22) & 3) == 0)
1966 return 1;
1967 wrd = (insn >> 12) & 0xf;
1968 rd0 = (insn >> 16) & 0xf;
1969 gen_op_iwmmxt_movq_M0_wRn(rd0);
1970 tmp = new_tmp();
1971 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1972 dead_tmp(tmp);
1973 return 1;
1975 switch ((insn >> 22) & 3) {
1976 case 1:
1977 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1978 break;
1979 case 2:
1980 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1981 break;
1982 case 3:
1983 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1984 break;
1986 dead_tmp(tmp);
1987 gen_op_iwmmxt_movq_wRn_M0(wrd);
1988 gen_op_iwmmxt_set_mup();
1989 gen_op_iwmmxt_set_cup();
1990 break;
1991 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1992 case 0x014: case 0x414: case 0x814: case 0xc14:
1993 if (((insn >> 22) & 3) == 0)
1994 return 1;
1995 wrd = (insn >> 12) & 0xf;
1996 rd0 = (insn >> 16) & 0xf;
1997 gen_op_iwmmxt_movq_M0_wRn(rd0);
1998 tmp = new_tmp();
1999 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2000 dead_tmp(tmp);
2001 return 1;
2003 switch ((insn >> 22) & 3) {
2004 case 1:
2005 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2006 break;
2007 case 2:
2008 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2009 break;
2010 case 3:
2011 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2012 break;
2014 dead_tmp(tmp);
2015 gen_op_iwmmxt_movq_wRn_M0(wrd);
2016 gen_op_iwmmxt_set_mup();
2017 gen_op_iwmmxt_set_cup();
2018 break;
2019 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2020 case 0x114: case 0x514: case 0x914: case 0xd14:
2021 if (((insn >> 22) & 3) == 0)
2022 return 1;
2023 wrd = (insn >> 12) & 0xf;
2024 rd0 = (insn >> 16) & 0xf;
2025 gen_op_iwmmxt_movq_M0_wRn(rd0);
2026 tmp = new_tmp();
2027 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2028 dead_tmp(tmp);
2029 return 1;
2031 switch ((insn >> 22) & 3) {
2032 case 1:
2033 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2034 break;
2035 case 2:
2036 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2037 break;
2038 case 3:
2039 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2040 break;
2042 dead_tmp(tmp);
2043 gen_op_iwmmxt_movq_wRn_M0(wrd);
2044 gen_op_iwmmxt_set_mup();
2045 gen_op_iwmmxt_set_cup();
2046 break;
2047 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2048 case 0x314: case 0x714: case 0xb14: case 0xf14:
2049 if (((insn >> 22) & 3) == 0)
2050 return 1;
2051 wrd = (insn >> 12) & 0xf;
2052 rd0 = (insn >> 16) & 0xf;
2053 gen_op_iwmmxt_movq_M0_wRn(rd0);
2054 tmp = new_tmp();
2055 switch ((insn >> 22) & 3) {
2056 case 1:
2057 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2058 dead_tmp(tmp);
2059 return 1;
2061 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2062 break;
2063 case 2:
2064 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2065 dead_tmp(tmp);
2066 return 1;
2068 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2069 break;
2070 case 3:
2071 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2072 dead_tmp(tmp);
2073 return 1;
2075 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2076 break;
2078 dead_tmp(tmp);
2079 gen_op_iwmmxt_movq_wRn_M0(wrd);
2080 gen_op_iwmmxt_set_mup();
2081 gen_op_iwmmxt_set_cup();
2082 break;
2083 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2084 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2085 wrd = (insn >> 12) & 0xf;
2086 rd0 = (insn >> 16) & 0xf;
2087 rd1 = (insn >> 0) & 0xf;
2088 gen_op_iwmmxt_movq_M0_wRn(rd0);
2089 switch ((insn >> 22) & 3) {
2090 case 0:
2091 if (insn & (1 << 21))
2092 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2093 else
2094 gen_op_iwmmxt_minub_M0_wRn(rd1);
2095 break;
2096 case 1:
2097 if (insn & (1 << 21))
2098 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2099 else
2100 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2101 break;
2102 case 2:
2103 if (insn & (1 << 21))
2104 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2105 else
2106 gen_op_iwmmxt_minul_M0_wRn(rd1);
2107 break;
2108 case 3:
2109 return 1;
2111 gen_op_iwmmxt_movq_wRn_M0(wrd);
2112 gen_op_iwmmxt_set_mup();
2113 break;
2114 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2115 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2116 wrd = (insn >> 12) & 0xf;
2117 rd0 = (insn >> 16) & 0xf;
2118 rd1 = (insn >> 0) & 0xf;
2119 gen_op_iwmmxt_movq_M0_wRn(rd0);
2120 switch ((insn >> 22) & 3) {
2121 case 0:
2122 if (insn & (1 << 21))
2123 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2124 else
2125 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2126 break;
2127 case 1:
2128 if (insn & (1 << 21))
2129 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2130 else
2131 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2132 break;
2133 case 2:
2134 if (insn & (1 << 21))
2135 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2136 else
2137 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2138 break;
2139 case 3:
2140 return 1;
2142 gen_op_iwmmxt_movq_wRn_M0(wrd);
2143 gen_op_iwmmxt_set_mup();
2144 break;
2145 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2146 case 0x402: case 0x502: case 0x602: case 0x702:
2147 wrd = (insn >> 12) & 0xf;
2148 rd0 = (insn >> 16) & 0xf;
2149 rd1 = (insn >> 0) & 0xf;
2150 gen_op_iwmmxt_movq_M0_wRn(rd0);
2151 tmp = tcg_const_i32((insn >> 20) & 3);
2152 iwmmxt_load_reg(cpu_V1, rd1);
2153 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2154 tcg_temp_free(tmp);
2155 gen_op_iwmmxt_movq_wRn_M0(wrd);
2156 gen_op_iwmmxt_set_mup();
2157 break;
2158 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2159 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2160 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2161 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2162 wrd = (insn >> 12) & 0xf;
2163 rd0 = (insn >> 16) & 0xf;
2164 rd1 = (insn >> 0) & 0xf;
2165 gen_op_iwmmxt_movq_M0_wRn(rd0);
2166 switch ((insn >> 20) & 0xf) {
2167 case 0x0:
2168 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2169 break;
2170 case 0x1:
2171 gen_op_iwmmxt_subub_M0_wRn(rd1);
2172 break;
2173 case 0x3:
2174 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2175 break;
2176 case 0x4:
2177 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2178 break;
2179 case 0x5:
2180 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2181 break;
2182 case 0x7:
2183 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2184 break;
2185 case 0x8:
2186 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2187 break;
2188 case 0x9:
2189 gen_op_iwmmxt_subul_M0_wRn(rd1);
2190 break;
2191 case 0xb:
2192 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2193 break;
2194 default:
2195 return 1;
2197 gen_op_iwmmxt_movq_wRn_M0(wrd);
2198 gen_op_iwmmxt_set_mup();
2199 gen_op_iwmmxt_set_cup();
2200 break;
2201 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2202 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2203 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2204 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2205 wrd = (insn >> 12) & 0xf;
2206 rd0 = (insn >> 16) & 0xf;
2207 gen_op_iwmmxt_movq_M0_wRn(rd0);
2208 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2209 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2210 tcg_temp_free(tmp);
2211 gen_op_iwmmxt_movq_wRn_M0(wrd);
2212 gen_op_iwmmxt_set_mup();
2213 gen_op_iwmmxt_set_cup();
2214 break;
2215 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2216 case 0x418: case 0x518: case 0x618: case 0x718:
2217 case 0x818: case 0x918: case 0xa18: case 0xb18:
2218 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2219 wrd = (insn >> 12) & 0xf;
2220 rd0 = (insn >> 16) & 0xf;
2221 rd1 = (insn >> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0);
2223 switch ((insn >> 20) & 0xf) {
2224 case 0x0:
2225 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2226 break;
2227 case 0x1:
2228 gen_op_iwmmxt_addub_M0_wRn(rd1);
2229 break;
2230 case 0x3:
2231 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2232 break;
2233 case 0x4:
2234 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2235 break;
2236 case 0x5:
2237 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2238 break;
2239 case 0x7:
2240 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2241 break;
2242 case 0x8:
2243 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2244 break;
2245 case 0x9:
2246 gen_op_iwmmxt_addul_M0_wRn(rd1);
2247 break;
2248 case 0xb:
2249 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2250 break;
2251 default:
2252 return 1;
2254 gen_op_iwmmxt_movq_wRn_M0(wrd);
2255 gen_op_iwmmxt_set_mup();
2256 gen_op_iwmmxt_set_cup();
2257 break;
2258 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2259 case 0x408: case 0x508: case 0x608: case 0x708:
2260 case 0x808: case 0x908: case 0xa08: case 0xb08:
2261 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2262 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2263 return 1;
2264 wrd = (insn >> 12) & 0xf;
2265 rd0 = (insn >> 16) & 0xf;
2266 rd1 = (insn >> 0) & 0xf;
2267 gen_op_iwmmxt_movq_M0_wRn(rd0);
2268 switch ((insn >> 22) & 3) {
2269 case 1:
2270 if (insn & (1 << 21))
2271 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2272 else
2273 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2274 break;
2275 case 2:
2276 if (insn & (1 << 21))
2277 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2278 else
2279 gen_op_iwmmxt_packul_M0_wRn(rd1);
2280 break;
2281 case 3:
2282 if (insn & (1 << 21))
2283 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2284 else
2285 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2286 break;
2288 gen_op_iwmmxt_movq_wRn_M0(wrd);
2289 gen_op_iwmmxt_set_mup();
2290 gen_op_iwmmxt_set_cup();
2291 break;
2292 case 0x201: case 0x203: case 0x205: case 0x207:
2293 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2294 case 0x211: case 0x213: case 0x215: case 0x217:
2295 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2296 wrd = (insn >> 5) & 0xf;
2297 rd0 = (insn >> 12) & 0xf;
2298 rd1 = (insn >> 0) & 0xf;
2299 if (rd0 == 0xf || rd1 == 0xf)
2300 return 1;
2301 gen_op_iwmmxt_movq_M0_wRn(wrd);
2302 tmp = load_reg(s, rd0);
2303 tmp2 = load_reg(s, rd1);
2304 switch ((insn >> 16) & 0xf) {
2305 case 0x0: /* TMIA */
2306 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2307 break;
2308 case 0x8: /* TMIAPH */
2309 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2310 break;
2311 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2312 if (insn & (1 << 16))
2313 tcg_gen_shri_i32(tmp, tmp, 16);
2314 if (insn & (1 << 17))
2315 tcg_gen_shri_i32(tmp2, tmp2, 16);
2316 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2317 break;
2318 default:
2319 dead_tmp(tmp2);
2320 dead_tmp(tmp);
2321 return 1;
2323 dead_tmp(tmp2);
2324 dead_tmp(tmp);
2325 gen_op_iwmmxt_movq_wRn_M0(wrd);
2326 gen_op_iwmmxt_set_mup();
2327 break;
2328 default:
2329 return 1;
2332 return 0;
2335 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2336 (ie. an undefined instruction). */
2337 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2339 int acc, rd0, rd1, rdhi, rdlo;
2340 TCGv tmp, tmp2;
2342 if ((insn & 0x0ff00f10) == 0x0e200010) {
2343 /* Multiply with Internal Accumulate Format */
2344 rd0 = (insn >> 12) & 0xf;
2345 rd1 = insn & 0xf;
2346 acc = (insn >> 5) & 7;
2348 if (acc != 0)
2349 return 1;
2351 tmp = load_reg(s, rd0);
2352 tmp2 = load_reg(s, rd1);
2353 switch ((insn >> 16) & 0xf) {
2354 case 0x0: /* MIA */
2355 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2356 break;
2357 case 0x8: /* MIAPH */
2358 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2359 break;
2360 case 0xc: /* MIABB */
2361 case 0xd: /* MIABT */
2362 case 0xe: /* MIATB */
2363 case 0xf: /* MIATT */
2364 if (insn & (1 << 16))
2365 tcg_gen_shri_i32(tmp, tmp, 16);
2366 if (insn & (1 << 17))
2367 tcg_gen_shri_i32(tmp2, tmp2, 16);
2368 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2369 break;
2370 default:
2371 return 1;
2373 dead_tmp(tmp2);
2374 dead_tmp(tmp);
2376 gen_op_iwmmxt_movq_wRn_M0(acc);
2377 return 0;
2380 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2381 /* Internal Accumulator Access Format */
2382 rdhi = (insn >> 16) & 0xf;
2383 rdlo = (insn >> 12) & 0xf;
2384 acc = insn & 7;
2386 if (acc != 0)
2387 return 1;
2389 if (insn & ARM_CP_RW_BIT) { /* MRA */
2390 iwmmxt_load_reg(cpu_V0, acc);
2391 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2392 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2393 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2394 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2395 } else { /* MAR */
2396 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2397 iwmmxt_store_reg(cpu_V0, acc);
2399 return 0;
2402 return 1;
2405 /* Disassemble system coprocessor instruction. Return nonzero if
2406 instruction is not defined. */
2407 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2409 TCGv tmp, tmp2;
2410 uint32_t rd = (insn >> 12) & 0xf;
2411 uint32_t cp = (insn >> 8) & 0xf;
2412 if (IS_USER(s)) {
2413 return 1;
2416 if (insn & ARM_CP_RW_BIT) {
2417 if (!env->cp[cp].cp_read)
2418 return 1;
2419 gen_set_pc_im(s->pc);
2420 tmp = new_tmp();
2421 tmp2 = tcg_const_i32(insn);
2422 gen_helper_get_cp(tmp, cpu_env, tmp2);
2423 tcg_temp_free(tmp2);
2424 store_reg(s, rd, tmp);
2425 } else {
2426 if (!env->cp[cp].cp_write)
2427 return 1;
2428 gen_set_pc_im(s->pc);
2429 tmp = load_reg(s, rd);
2430 tmp2 = tcg_const_i32(insn);
2431 gen_helper_set_cp(cpu_env, tmp2, tmp);
2432 tcg_temp_free(tmp2);
2433 dead_tmp(tmp);
2435 return 0;
2438 static int cp15_user_ok(uint32_t insn)
2440 int cpn = (insn >> 16) & 0xf;
2441 int cpm = insn & 0xf;
2442 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2444 if (cpn == 13 && cpm == 0) {
2445 /* TLS register. */
2446 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2447 return 1;
2449 if (cpn == 7) {
2450 /* ISB, DSB, DMB. */
2451 if ((cpm == 5 && op == 4)
2452 || (cpm == 10 && (op == 4 || op == 5)))
2453 return 1;
2455 return 0;
2458 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2460 TCGv tmp;
2461 int cpn = (insn >> 16) & 0xf;
2462 int cpm = insn & 0xf;
2463 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2465 if (!arm_feature(env, ARM_FEATURE_V6K))
2466 return 0;
2468 if (!(cpn == 13 && cpm == 0))
2469 return 0;
2471 if (insn & ARM_CP_RW_BIT) {
2472 tmp = new_tmp();
2473 switch (op) {
2474 case 2:
2475 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls1));
2476 break;
2477 case 3:
2478 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls2));
2479 break;
2480 case 4:
2481 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls3));
2482 break;
2483 default:
2484 dead_tmp(tmp);
2485 return 0;
2487 store_reg(s, rd, tmp);
2489 } else {
2490 tmp = load_reg(s, rd);
2491 switch (op) {
2492 case 2:
2493 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls1));
2494 break;
2495 case 3:
2496 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls2));
2497 break;
2498 case 4:
2499 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, cp15.c13_tls3));
2500 break;
2501 default:
2502 return 0;
2504 dead_tmp(tmp);
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, VSUBHL, VRSUBHL */
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 neon_store_reg64(cpu_V0, rd + pass);
5445 break;
5446 case 44: /* VCVT.F16.F32 */
5447 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5448 return 1;
5449 tmp = new_tmp();
5450 tmp2 = new_tmp();
5451 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5452 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5453 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5454 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5455 tcg_gen_shli_i32(tmp2, tmp2, 16);
5456 tcg_gen_or_i32(tmp2, tmp2, tmp);
5457 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5458 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5459 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5460 neon_store_reg(rd, 0, tmp2);
5461 tmp2 = new_tmp();
5462 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5463 tcg_gen_shli_i32(tmp2, tmp2, 16);
5464 tcg_gen_or_i32(tmp2, tmp2, tmp);
5465 neon_store_reg(rd, 1, tmp2);
5466 dead_tmp(tmp);
5467 break;
5468 case 46: /* VCVT.F32.F16 */
5469 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5470 return 1;
5471 tmp3 = new_tmp();
5472 tmp = neon_load_reg(rm, 0);
5473 tmp2 = neon_load_reg(rm, 1);
5474 tcg_gen_ext16u_i32(tmp3, tmp);
5475 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5476 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5477 tcg_gen_shri_i32(tmp3, tmp, 16);
5478 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5479 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5480 dead_tmp(tmp);
5481 tcg_gen_ext16u_i32(tmp3, tmp2);
5482 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5483 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5484 tcg_gen_shri_i32(tmp3, tmp2, 16);
5485 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5486 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5487 dead_tmp(tmp2);
5488 dead_tmp(tmp3);
5489 break;
5490 default:
5491 elementwise:
5492 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5493 if (op == 30 || op == 31 || op >= 58) {
5494 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5495 neon_reg_offset(rm, pass));
5496 TCGV_UNUSED(tmp);
5497 } else {
5498 tmp = neon_load_reg(rm, pass);
5500 switch (op) {
5501 case 1: /* VREV32 */
5502 switch (size) {
5503 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5504 case 1: gen_swap_half(tmp); break;
5505 default: return 1;
5507 break;
5508 case 2: /* VREV16 */
5509 if (size != 0)
5510 return 1;
5511 gen_rev16(tmp);
5512 break;
5513 case 8: /* CLS */
5514 switch (size) {
5515 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5516 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5517 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5518 default: return 1;
5520 break;
5521 case 9: /* CLZ */
5522 switch (size) {
5523 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5524 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5525 case 2: gen_helper_clz(tmp, tmp); break;
5526 default: return 1;
5528 break;
5529 case 10: /* CNT */
5530 if (size != 0)
5531 return 1;
5532 gen_helper_neon_cnt_u8(tmp, tmp);
5533 break;
5534 case 11: /* VNOT */
5535 if (size != 0)
5536 return 1;
5537 tcg_gen_not_i32(tmp, tmp);
5538 break;
5539 case 14: /* VQABS */
5540 switch (size) {
5541 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5542 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5543 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5544 default: return 1;
5546 break;
5547 case 15: /* VQNEG */
5548 switch (size) {
5549 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5550 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5551 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5552 default: return 1;
5554 break;
5555 case 16: case 19: /* VCGT #0, VCLE #0 */
5556 tmp2 = tcg_const_i32(0);
5557 switch(size) {
5558 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5559 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5560 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5561 default: return 1;
5563 tcg_temp_free(tmp2);
5564 if (op == 19)
5565 tcg_gen_not_i32(tmp, tmp);
5566 break;
5567 case 17: case 20: /* VCGE #0, VCLT #0 */
5568 tmp2 = tcg_const_i32(0);
5569 switch(size) {
5570 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5571 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5572 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5573 default: return 1;
5575 tcg_temp_free(tmp2);
5576 if (op == 20)
5577 tcg_gen_not_i32(tmp, tmp);
5578 break;
5579 case 18: /* VCEQ #0 */
5580 tmp2 = tcg_const_i32(0);
5581 switch(size) {
5582 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5583 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5584 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5585 default: return 1;
5587 tcg_temp_free(tmp2);
5588 break;
5589 case 22: /* VABS */
5590 switch(size) {
5591 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5592 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5593 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5594 default: return 1;
5596 break;
5597 case 23: /* VNEG */
5598 if (size == 3)
5599 return 1;
5600 tmp2 = tcg_const_i32(0);
5601 gen_neon_rsb(size, tmp, tmp2);
5602 tcg_temp_free(tmp2);
5603 break;
5604 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5605 tmp2 = tcg_const_i32(0);
5606 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5607 tcg_temp_free(tmp2);
5608 if (op == 27)
5609 tcg_gen_not_i32(tmp, tmp);
5610 break;
5611 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5612 tmp2 = tcg_const_i32(0);
5613 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5614 tcg_temp_free(tmp2);
5615 if (op == 28)
5616 tcg_gen_not_i32(tmp, tmp);
5617 break;
5618 case 26: /* Float VCEQ #0 */
5619 tmp2 = tcg_const_i32(0);
5620 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5621 tcg_temp_free(tmp2);
5622 break;
5623 case 30: /* Float VABS */
5624 gen_vfp_abs(0);
5625 break;
5626 case 31: /* Float VNEG */
5627 gen_vfp_neg(0);
5628 break;
5629 case 32: /* VSWP */
5630 tmp2 = neon_load_reg(rd, pass);
5631 neon_store_reg(rm, pass, tmp2);
5632 break;
5633 case 33: /* VTRN */
5634 tmp2 = neon_load_reg(rd, pass);
5635 switch (size) {
5636 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5637 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5638 case 2: abort();
5639 default: return 1;
5641 neon_store_reg(rm, pass, tmp2);
5642 break;
5643 case 56: /* Integer VRECPE */
5644 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5645 break;
5646 case 57: /* Integer VRSQRTE */
5647 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5648 break;
5649 case 58: /* Float VRECPE */
5650 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5651 break;
5652 case 59: /* Float VRSQRTE */
5653 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5654 break;
5655 case 60: /* VCVT.F32.S32 */
5656 gen_vfp_tosiz(0);
5657 break;
5658 case 61: /* VCVT.F32.U32 */
5659 gen_vfp_touiz(0);
5660 break;
5661 case 62: /* VCVT.S32.F32 */
5662 gen_vfp_sito(0);
5663 break;
5664 case 63: /* VCVT.U32.F32 */
5665 gen_vfp_uito(0);
5666 break;
5667 default:
5668 /* Reserved: 21, 29, 39-56 */
5669 return 1;
5671 if (op == 30 || op == 31 || op >= 58) {
5672 tcg_gen_st_f32(cpu_F0s, cpu_env,
5673 neon_reg_offset(rd, pass));
5674 } else {
5675 neon_store_reg(rd, pass, tmp);
5678 break;
5680 } else if ((insn & (1 << 10)) == 0) {
5681 /* VTBL, VTBX. */
5682 n = ((insn >> 5) & 0x18) + 8;
5683 if (insn & (1 << 6)) {
5684 tmp = neon_load_reg(rd, 0);
5685 } else {
5686 tmp = new_tmp();
5687 tcg_gen_movi_i32(tmp, 0);
5689 tmp2 = neon_load_reg(rm, 0);
5690 tmp4 = tcg_const_i32(rn);
5691 tmp5 = tcg_const_i32(n);
5692 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5693 dead_tmp(tmp);
5694 if (insn & (1 << 6)) {
5695 tmp = neon_load_reg(rd, 1);
5696 } else {
5697 tmp = new_tmp();
5698 tcg_gen_movi_i32(tmp, 0);
5700 tmp3 = neon_load_reg(rm, 1);
5701 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5702 tcg_temp_free_i32(tmp5);
5703 tcg_temp_free_i32(tmp4);
5704 neon_store_reg(rd, 0, tmp2);
5705 neon_store_reg(rd, 1, tmp3);
5706 dead_tmp(tmp);
5707 } else if ((insn & 0x380) == 0) {
5708 /* VDUP */
5709 if (insn & (1 << 19)) {
5710 tmp = neon_load_reg(rm, 1);
5711 } else {
5712 tmp = neon_load_reg(rm, 0);
5714 if (insn & (1 << 16)) {
5715 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5716 } else if (insn & (1 << 17)) {
5717 if ((insn >> 18) & 1)
5718 gen_neon_dup_high16(tmp);
5719 else
5720 gen_neon_dup_low16(tmp);
5722 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5723 tmp2 = new_tmp();
5724 tcg_gen_mov_i32(tmp2, tmp);
5725 neon_store_reg(rd, pass, tmp2);
5727 dead_tmp(tmp);
5728 } else {
5729 return 1;
5733 return 0;
5736 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5738 int crn = (insn >> 16) & 0xf;
5739 int crm = insn & 0xf;
5740 int op1 = (insn >> 21) & 7;
5741 int op2 = (insn >> 5) & 7;
5742 int rt = (insn >> 12) & 0xf;
5743 TCGv tmp;
5745 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5746 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5747 /* TEECR */
5748 if (IS_USER(s))
5749 return 1;
5750 tmp = load_cpu_field(teecr);
5751 store_reg(s, rt, tmp);
5752 return 0;
5754 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5755 /* TEEHBR */
5756 if (IS_USER(s) && (env->teecr & 1))
5757 return 1;
5758 tmp = load_cpu_field(teehbr);
5759 store_reg(s, rt, tmp);
5760 return 0;
5763 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5764 op1, crn, crm, op2);
5765 return 1;
5768 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5770 int crn = (insn >> 16) & 0xf;
5771 int crm = insn & 0xf;
5772 int op1 = (insn >> 21) & 7;
5773 int op2 = (insn >> 5) & 7;
5774 int rt = (insn >> 12) & 0xf;
5775 TCGv tmp;
5777 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5778 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5779 /* TEECR */
5780 if (IS_USER(s))
5781 return 1;
5782 tmp = load_reg(s, rt);
5783 gen_helper_set_teecr(cpu_env, tmp);
5784 dead_tmp(tmp);
5785 return 0;
5787 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5788 /* TEEHBR */
5789 if (IS_USER(s) && (env->teecr & 1))
5790 return 1;
5791 tmp = load_reg(s, rt);
5792 store_cpu_field(tmp, teehbr);
5793 return 0;
5796 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5797 op1, crn, crm, op2);
5798 return 1;
5801 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5803 int cpnum;
5805 cpnum = (insn >> 8) & 0xf;
5806 if (arm_feature(env, ARM_FEATURE_XSCALE)
5807 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5808 return 1;
5810 switch (cpnum) {
5811 case 0:
5812 case 1:
5813 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5814 return disas_iwmmxt_insn(env, s, insn);
5815 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5816 return disas_dsp_insn(env, s, insn);
5818 return 1;
5819 case 10:
5820 case 11:
5821 return disas_vfp_insn (env, s, insn);
5822 case 14:
5823 /* Coprocessors 7-15 are architecturally reserved by ARM.
5824 Unfortunately Intel decided to ignore this. */
5825 if (arm_feature(env, ARM_FEATURE_XSCALE))
5826 goto board;
5827 if (insn & (1 << 20))
5828 return disas_cp14_read(env, s, insn);
5829 else
5830 return disas_cp14_write(env, s, insn);
5831 case 15:
5832 return disas_cp15_insn (env, s, insn);
5833 default:
5834 board:
5835 /* Unknown coprocessor. See if the board has hooked it. */
5836 return disas_cp_insn (env, s, insn);
5841 /* Store a 64-bit value to a register pair. Clobbers val. */
5842 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5844 TCGv tmp;
5845 tmp = new_tmp();
5846 tcg_gen_trunc_i64_i32(tmp, val);
5847 store_reg(s, rlow, tmp);
5848 tmp = new_tmp();
5849 tcg_gen_shri_i64(val, val, 32);
5850 tcg_gen_trunc_i64_i32(tmp, val);
5851 store_reg(s, rhigh, tmp);
5854 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5855 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5857 TCGv_i64 tmp;
5858 TCGv tmp2;
5860 /* Load value and extend to 64 bits. */
5861 tmp = tcg_temp_new_i64();
5862 tmp2 = load_reg(s, rlow);
5863 tcg_gen_extu_i32_i64(tmp, tmp2);
5864 dead_tmp(tmp2);
5865 tcg_gen_add_i64(val, val, tmp);
5866 tcg_temp_free_i64(tmp);
5869 /* load and add a 64-bit value from a register pair. */
5870 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5872 TCGv_i64 tmp;
5873 TCGv tmpl;
5874 TCGv tmph;
5876 /* Load 64-bit value rd:rn. */
5877 tmpl = load_reg(s, rlow);
5878 tmph = load_reg(s, rhigh);
5879 tmp = tcg_temp_new_i64();
5880 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5881 dead_tmp(tmpl);
5882 dead_tmp(tmph);
5883 tcg_gen_add_i64(val, val, tmp);
5884 tcg_temp_free_i64(tmp);
5887 /* Set N and Z flags from a 64-bit value. */
5888 static void gen_logicq_cc(TCGv_i64 val)
5890 TCGv tmp = new_tmp();
5891 gen_helper_logicq_cc(tmp, val);
5892 gen_logic_CC(tmp);
5893 dead_tmp(tmp);
5896 /* Load/Store exclusive instructions are implemented by remembering
5897 the value/address loaded, and seeing if these are the same
5898 when the store is performed. This should be is sufficient to implement
5899 the architecturally mandated semantics, and avoids having to monitor
5900 regular stores.
5902 In system emulation mode only one CPU will be running at once, so
5903 this sequence is effectively atomic. In user emulation mode we
5904 throw an exception and handle the atomic operation elsewhere. */
5905 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
5906 TCGv addr, int size)
5908 TCGv tmp;
5910 switch (size) {
5911 case 0:
5912 tmp = gen_ld8u(addr, IS_USER(s));
5913 break;
5914 case 1:
5915 tmp = gen_ld16u(addr, IS_USER(s));
5916 break;
5917 case 2:
5918 case 3:
5919 tmp = gen_ld32(addr, IS_USER(s));
5920 break;
5921 default:
5922 abort();
5924 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
5925 store_reg(s, rt, tmp);
5926 if (size == 3) {
5927 tcg_gen_addi_i32(addr, addr, 4);
5928 tmp = gen_ld32(addr, IS_USER(s));
5929 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
5930 store_reg(s, rt2, tmp);
5932 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
5935 static void gen_clrex(DisasContext *s)
5937 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
5940 #ifdef CONFIG_USER_ONLY
5941 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5942 TCGv addr, int size)
5944 tcg_gen_mov_i32(cpu_exclusive_test, addr);
5945 tcg_gen_movi_i32(cpu_exclusive_info,
5946 size | (rd << 4) | (rt << 8) | (rt2 << 12));
5947 gen_set_condexec(s);
5948 gen_set_pc_im(s->pc - 4);
5949 gen_exception(EXCP_STREX);
5950 s->is_jmp = DISAS_JUMP;
5952 #else
5953 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5954 TCGv addr, int size)
5956 TCGv tmp;
5957 int done_label;
5958 int fail_label;
5960 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5961 [addr] = {Rt};
5962 {Rd} = 0;
5963 } else {
5964 {Rd} = 1;
5965 } */
5966 fail_label = gen_new_label();
5967 done_label = gen_new_label();
5968 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
5969 switch (size) {
5970 case 0:
5971 tmp = gen_ld8u(addr, IS_USER(s));
5972 break;
5973 case 1:
5974 tmp = gen_ld16u(addr, IS_USER(s));
5975 break;
5976 case 2:
5977 case 3:
5978 tmp = gen_ld32(addr, IS_USER(s));
5979 break;
5980 default:
5981 abort();
5983 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
5984 dead_tmp(tmp);
5985 if (size == 3) {
5986 TCGv tmp2 = new_tmp();
5987 tcg_gen_addi_i32(tmp2, addr, 4);
5988 tmp = gen_ld32(addr, IS_USER(s));
5989 dead_tmp(tmp2);
5990 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
5991 dead_tmp(tmp);
5993 tmp = load_reg(s, rt);
5994 switch (size) {
5995 case 0:
5996 gen_st8(tmp, addr, IS_USER(s));
5997 break;
5998 case 1:
5999 gen_st16(tmp, addr, IS_USER(s));
6000 break;
6001 case 2:
6002 case 3:
6003 gen_st32(tmp, addr, IS_USER(s));
6004 break;
6005 default:
6006 abort();
6008 if (size == 3) {
6009 tcg_gen_addi_i32(addr, addr, 4);
6010 tmp = load_reg(s, rt2);
6011 gen_st32(tmp, addr, IS_USER(s));
6013 tcg_gen_movi_i32(cpu_R[rd], 0);
6014 tcg_gen_br(done_label);
6015 gen_set_label(fail_label);
6016 tcg_gen_movi_i32(cpu_R[rd], 1);
6017 gen_set_label(done_label);
6018 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6020 #endif
6022 static void disas_arm_insn(CPUState * env, DisasContext *s)
6024 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6025 TCGv tmp;
6026 TCGv tmp2;
6027 TCGv tmp3;
6028 TCGv addr;
6029 TCGv_i64 tmp64;
6031 insn = ldl_code(s->pc);
6032 s->pc += 4;
6034 /* M variants do not implement ARM mode. */
6035 if (IS_M(env))
6036 goto illegal_op;
6037 cond = insn >> 28;
6038 if (cond == 0xf){
6039 /* Unconditional instructions. */
6040 if (((insn >> 25) & 7) == 1) {
6041 /* NEON Data processing. */
6042 if (!arm_feature(env, ARM_FEATURE_NEON))
6043 goto illegal_op;
6045 if (disas_neon_data_insn(env, s, insn))
6046 goto illegal_op;
6047 return;
6049 if ((insn & 0x0f100000) == 0x04000000) {
6050 /* NEON load/store. */
6051 if (!arm_feature(env, ARM_FEATURE_NEON))
6052 goto illegal_op;
6054 if (disas_neon_ls_insn(env, s, insn))
6055 goto illegal_op;
6056 return;
6058 if ((insn & 0x0d70f000) == 0x0550f000)
6059 return; /* PLD */
6060 else if ((insn & 0x0ffffdff) == 0x01010000) {
6061 ARCH(6);
6062 /* setend */
6063 if (insn & (1 << 9)) {
6064 /* BE8 mode not implemented. */
6065 goto illegal_op;
6067 return;
6068 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6069 switch ((insn >> 4) & 0xf) {
6070 case 1: /* clrex */
6071 ARCH(6K);
6072 gen_clrex(s);
6073 return;
6074 case 4: /* dsb */
6075 case 5: /* dmb */
6076 case 6: /* isb */
6077 ARCH(7);
6078 /* We don't emulate caches so these are a no-op. */
6079 return;
6080 default:
6081 goto illegal_op;
6083 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6084 /* srs */
6085 int32_t offset;
6086 if (IS_USER(s))
6087 goto illegal_op;
6088 ARCH(6);
6089 op1 = (insn & 0x1f);
6090 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6091 addr = load_reg(s, 13);
6092 } else {
6093 addr = new_tmp();
6094 tmp = tcg_const_i32(op1);
6095 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6096 tcg_temp_free_i32(tmp);
6098 i = (insn >> 23) & 3;
6099 switch (i) {
6100 case 0: offset = -4; break; /* DA */
6101 case 1: offset = 0; break; /* IA */
6102 case 2: offset = -8; break; /* DB */
6103 case 3: offset = 4; break; /* IB */
6104 default: abort();
6106 if (offset)
6107 tcg_gen_addi_i32(addr, addr, offset);
6108 tmp = load_reg(s, 14);
6109 gen_st32(tmp, addr, 0);
6110 tmp = load_cpu_field(spsr);
6111 tcg_gen_addi_i32(addr, addr, 4);
6112 gen_st32(tmp, addr, 0);
6113 if (insn & (1 << 21)) {
6114 /* Base writeback. */
6115 switch (i) {
6116 case 0: offset = -8; break;
6117 case 1: offset = 4; break;
6118 case 2: offset = -4; break;
6119 case 3: offset = 0; break;
6120 default: abort();
6122 if (offset)
6123 tcg_gen_addi_i32(addr, addr, offset);
6124 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6125 store_reg(s, 13, addr);
6126 } else {
6127 tmp = tcg_const_i32(op1);
6128 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6129 tcg_temp_free_i32(tmp);
6130 dead_tmp(addr);
6132 } else {
6133 dead_tmp(addr);
6135 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
6136 /* rfe */
6137 int32_t offset;
6138 if (IS_USER(s))
6139 goto illegal_op;
6140 ARCH(6);
6141 rn = (insn >> 16) & 0xf;
6142 addr = load_reg(s, rn);
6143 i = (insn >> 23) & 3;
6144 switch (i) {
6145 case 0: offset = -4; break; /* DA */
6146 case 1: offset = 0; break; /* IA */
6147 case 2: offset = -8; break; /* DB */
6148 case 3: offset = 4; break; /* IB */
6149 default: abort();
6151 if (offset)
6152 tcg_gen_addi_i32(addr, addr, offset);
6153 /* Load PC into tmp and CPSR into tmp2. */
6154 tmp = gen_ld32(addr, 0);
6155 tcg_gen_addi_i32(addr, addr, 4);
6156 tmp2 = gen_ld32(addr, 0);
6157 if (insn & (1 << 21)) {
6158 /* Base writeback. */
6159 switch (i) {
6160 case 0: offset = -8; break;
6161 case 1: offset = 4; break;
6162 case 2: offset = -4; break;
6163 case 3: offset = 0; break;
6164 default: abort();
6166 if (offset)
6167 tcg_gen_addi_i32(addr, addr, offset);
6168 store_reg(s, rn, addr);
6169 } else {
6170 dead_tmp(addr);
6172 gen_rfe(s, tmp, tmp2);
6173 return;
6174 } else if ((insn & 0x0e000000) == 0x0a000000) {
6175 /* branch link and change to thumb (blx <offset>) */
6176 int32_t offset;
6178 val = (uint32_t)s->pc;
6179 tmp = new_tmp();
6180 tcg_gen_movi_i32(tmp, val);
6181 store_reg(s, 14, tmp);
6182 /* Sign-extend the 24-bit offset */
6183 offset = (((int32_t)insn) << 8) >> 8;
6184 /* offset * 4 + bit24 * 2 + (thumb bit) */
6185 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6186 /* pipeline offset */
6187 val += 4;
6188 gen_bx_im(s, val);
6189 return;
6190 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6191 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6192 /* iWMMXt register transfer. */
6193 if (env->cp15.c15_cpar & (1 << 1))
6194 if (!disas_iwmmxt_insn(env, s, insn))
6195 return;
6197 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6198 /* Coprocessor double register transfer. */
6199 } else if ((insn & 0x0f000010) == 0x0e000010) {
6200 /* Additional coprocessor register transfer. */
6201 } else if ((insn & 0x0ff10020) == 0x01000000) {
6202 uint32_t mask;
6203 uint32_t val;
6204 /* cps (privileged) */
6205 if (IS_USER(s))
6206 return;
6207 mask = val = 0;
6208 if (insn & (1 << 19)) {
6209 if (insn & (1 << 8))
6210 mask |= CPSR_A;
6211 if (insn & (1 << 7))
6212 mask |= CPSR_I;
6213 if (insn & (1 << 6))
6214 mask |= CPSR_F;
6215 if (insn & (1 << 18))
6216 val |= mask;
6218 if (insn & (1 << 17)) {
6219 mask |= CPSR_M;
6220 val |= (insn & 0x1f);
6222 if (mask) {
6223 gen_set_psr_im(s, mask, 0, val);
6225 return;
6227 goto illegal_op;
6229 if (cond != 0xe) {
6230 /* if not always execute, we generate a conditional jump to
6231 next instruction */
6232 s->condlabel = gen_new_label();
6233 gen_test_cc(cond ^ 1, s->condlabel);
6234 s->condjmp = 1;
6236 if ((insn & 0x0f900000) == 0x03000000) {
6237 if ((insn & (1 << 21)) == 0) {
6238 ARCH(6T2);
6239 rd = (insn >> 12) & 0xf;
6240 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6241 if ((insn & (1 << 22)) == 0) {
6242 /* MOVW */
6243 tmp = new_tmp();
6244 tcg_gen_movi_i32(tmp, val);
6245 } else {
6246 /* MOVT */
6247 tmp = load_reg(s, rd);
6248 tcg_gen_ext16u_i32(tmp, tmp);
6249 tcg_gen_ori_i32(tmp, tmp, val << 16);
6251 store_reg(s, rd, tmp);
6252 } else {
6253 if (((insn >> 12) & 0xf) != 0xf)
6254 goto illegal_op;
6255 if (((insn >> 16) & 0xf) == 0) {
6256 gen_nop_hint(s, insn & 0xff);
6257 } else {
6258 /* CPSR = immediate */
6259 val = insn & 0xff;
6260 shift = ((insn >> 8) & 0xf) * 2;
6261 if (shift)
6262 val = (val >> shift) | (val << (32 - shift));
6263 i = ((insn & (1 << 22)) != 0);
6264 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6265 goto illegal_op;
6268 } else if ((insn & 0x0f900000) == 0x01000000
6269 && (insn & 0x00000090) != 0x00000090) {
6270 /* miscellaneous instructions */
6271 op1 = (insn >> 21) & 3;
6272 sh = (insn >> 4) & 0xf;
6273 rm = insn & 0xf;
6274 switch (sh) {
6275 case 0x0: /* move program status register */
6276 if (op1 & 1) {
6277 /* PSR = reg */
6278 tmp = load_reg(s, rm);
6279 i = ((op1 & 2) != 0);
6280 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6281 goto illegal_op;
6282 } else {
6283 /* reg = PSR */
6284 rd = (insn >> 12) & 0xf;
6285 if (op1 & 2) {
6286 if (IS_USER(s))
6287 goto illegal_op;
6288 tmp = load_cpu_field(spsr);
6289 } else {
6290 tmp = new_tmp();
6291 gen_helper_cpsr_read(tmp);
6293 store_reg(s, rd, tmp);
6295 break;
6296 case 0x1:
6297 if (op1 == 1) {
6298 /* branch/exchange thumb (bx). */
6299 tmp = load_reg(s, rm);
6300 gen_bx(s, tmp);
6301 } else if (op1 == 3) {
6302 /* clz */
6303 rd = (insn >> 12) & 0xf;
6304 tmp = load_reg(s, rm);
6305 gen_helper_clz(tmp, tmp);
6306 store_reg(s, rd, tmp);
6307 } else {
6308 goto illegal_op;
6310 break;
6311 case 0x2:
6312 if (op1 == 1) {
6313 ARCH(5J); /* bxj */
6314 /* Trivial implementation equivalent to bx. */
6315 tmp = load_reg(s, rm);
6316 gen_bx(s, tmp);
6317 } else {
6318 goto illegal_op;
6320 break;
6321 case 0x3:
6322 if (op1 != 1)
6323 goto illegal_op;
6325 /* branch link/exchange thumb (blx) */
6326 tmp = load_reg(s, rm);
6327 tmp2 = new_tmp();
6328 tcg_gen_movi_i32(tmp2, s->pc);
6329 store_reg(s, 14, tmp2);
6330 gen_bx(s, tmp);
6331 break;
6332 case 0x5: /* saturating add/subtract */
6333 rd = (insn >> 12) & 0xf;
6334 rn = (insn >> 16) & 0xf;
6335 tmp = load_reg(s, rm);
6336 tmp2 = load_reg(s, rn);
6337 if (op1 & 2)
6338 gen_helper_double_saturate(tmp2, tmp2);
6339 if (op1 & 1)
6340 gen_helper_sub_saturate(tmp, tmp, tmp2);
6341 else
6342 gen_helper_add_saturate(tmp, tmp, tmp2);
6343 dead_tmp(tmp2);
6344 store_reg(s, rd, tmp);
6345 break;
6346 case 7: /* bkpt */
6347 gen_set_condexec(s);
6348 gen_set_pc_im(s->pc - 4);
6349 gen_exception(EXCP_BKPT);
6350 s->is_jmp = DISAS_JUMP;
6351 break;
6352 case 0x8: /* signed multiply */
6353 case 0xa:
6354 case 0xc:
6355 case 0xe:
6356 rs = (insn >> 8) & 0xf;
6357 rn = (insn >> 12) & 0xf;
6358 rd = (insn >> 16) & 0xf;
6359 if (op1 == 1) {
6360 /* (32 * 16) >> 16 */
6361 tmp = load_reg(s, rm);
6362 tmp2 = load_reg(s, rs);
6363 if (sh & 4)
6364 tcg_gen_sari_i32(tmp2, tmp2, 16);
6365 else
6366 gen_sxth(tmp2);
6367 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6368 tcg_gen_shri_i64(tmp64, tmp64, 16);
6369 tmp = new_tmp();
6370 tcg_gen_trunc_i64_i32(tmp, tmp64);
6371 tcg_temp_free_i64(tmp64);
6372 if ((sh & 2) == 0) {
6373 tmp2 = load_reg(s, rn);
6374 gen_helper_add_setq(tmp, tmp, tmp2);
6375 dead_tmp(tmp2);
6377 store_reg(s, rd, tmp);
6378 } else {
6379 /* 16 * 16 */
6380 tmp = load_reg(s, rm);
6381 tmp2 = load_reg(s, rs);
6382 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6383 dead_tmp(tmp2);
6384 if (op1 == 2) {
6385 tmp64 = tcg_temp_new_i64();
6386 tcg_gen_ext_i32_i64(tmp64, tmp);
6387 dead_tmp(tmp);
6388 gen_addq(s, tmp64, rn, rd);
6389 gen_storeq_reg(s, rn, rd, tmp64);
6390 tcg_temp_free_i64(tmp64);
6391 } else {
6392 if (op1 == 0) {
6393 tmp2 = load_reg(s, rn);
6394 gen_helper_add_setq(tmp, tmp, tmp2);
6395 dead_tmp(tmp2);
6397 store_reg(s, rd, tmp);
6400 break;
6401 default:
6402 goto illegal_op;
6404 } else if (((insn & 0x0e000000) == 0 &&
6405 (insn & 0x00000090) != 0x90) ||
6406 ((insn & 0x0e000000) == (1 << 25))) {
6407 int set_cc, logic_cc, shiftop;
6409 op1 = (insn >> 21) & 0xf;
6410 set_cc = (insn >> 20) & 1;
6411 logic_cc = table_logic_cc[op1] & set_cc;
6413 /* data processing instruction */
6414 if (insn & (1 << 25)) {
6415 /* immediate operand */
6416 val = insn & 0xff;
6417 shift = ((insn >> 8) & 0xf) * 2;
6418 if (shift) {
6419 val = (val >> shift) | (val << (32 - shift));
6421 tmp2 = new_tmp();
6422 tcg_gen_movi_i32(tmp2, val);
6423 if (logic_cc && shift) {
6424 gen_set_CF_bit31(tmp2);
6426 } else {
6427 /* register */
6428 rm = (insn) & 0xf;
6429 tmp2 = load_reg(s, rm);
6430 shiftop = (insn >> 5) & 3;
6431 if (!(insn & (1 << 4))) {
6432 shift = (insn >> 7) & 0x1f;
6433 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6434 } else {
6435 rs = (insn >> 8) & 0xf;
6436 tmp = load_reg(s, rs);
6437 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6440 if (op1 != 0x0f && op1 != 0x0d) {
6441 rn = (insn >> 16) & 0xf;
6442 tmp = load_reg(s, rn);
6443 } else {
6444 TCGV_UNUSED(tmp);
6446 rd = (insn >> 12) & 0xf;
6447 switch(op1) {
6448 case 0x00:
6449 tcg_gen_and_i32(tmp, tmp, tmp2);
6450 if (logic_cc) {
6451 gen_logic_CC(tmp);
6453 store_reg_bx(env, s, rd, tmp);
6454 break;
6455 case 0x01:
6456 tcg_gen_xor_i32(tmp, tmp, tmp2);
6457 if (logic_cc) {
6458 gen_logic_CC(tmp);
6460 store_reg_bx(env, s, rd, tmp);
6461 break;
6462 case 0x02:
6463 if (set_cc && rd == 15) {
6464 /* SUBS r15, ... is used for exception return. */
6465 if (IS_USER(s)) {
6466 goto illegal_op;
6468 gen_helper_sub_cc(tmp, tmp, tmp2);
6469 gen_exception_return(s, tmp);
6470 } else {
6471 if (set_cc) {
6472 gen_helper_sub_cc(tmp, tmp, tmp2);
6473 } else {
6474 tcg_gen_sub_i32(tmp, tmp, tmp2);
6476 store_reg_bx(env, s, rd, tmp);
6478 break;
6479 case 0x03:
6480 if (set_cc) {
6481 gen_helper_sub_cc(tmp, tmp2, tmp);
6482 } else {
6483 tcg_gen_sub_i32(tmp, tmp2, tmp);
6485 store_reg_bx(env, s, rd, tmp);
6486 break;
6487 case 0x04:
6488 if (set_cc) {
6489 gen_helper_add_cc(tmp, tmp, tmp2);
6490 } else {
6491 tcg_gen_add_i32(tmp, tmp, tmp2);
6493 store_reg_bx(env, s, rd, tmp);
6494 break;
6495 case 0x05:
6496 if (set_cc) {
6497 gen_helper_adc_cc(tmp, tmp, tmp2);
6498 } else {
6499 gen_add_carry(tmp, tmp, tmp2);
6501 store_reg_bx(env, s, rd, tmp);
6502 break;
6503 case 0x06:
6504 if (set_cc) {
6505 gen_helper_sbc_cc(tmp, tmp, tmp2);
6506 } else {
6507 gen_sub_carry(tmp, tmp, tmp2);
6509 store_reg_bx(env, s, rd, tmp);
6510 break;
6511 case 0x07:
6512 if (set_cc) {
6513 gen_helper_sbc_cc(tmp, tmp2, tmp);
6514 } else {
6515 gen_sub_carry(tmp, tmp2, tmp);
6517 store_reg_bx(env, s, rd, tmp);
6518 break;
6519 case 0x08:
6520 if (set_cc) {
6521 tcg_gen_and_i32(tmp, tmp, tmp2);
6522 gen_logic_CC(tmp);
6524 dead_tmp(tmp);
6525 break;
6526 case 0x09:
6527 if (set_cc) {
6528 tcg_gen_xor_i32(tmp, tmp, tmp2);
6529 gen_logic_CC(tmp);
6531 dead_tmp(tmp);
6532 break;
6533 case 0x0a:
6534 if (set_cc) {
6535 gen_helper_sub_cc(tmp, tmp, tmp2);
6537 dead_tmp(tmp);
6538 break;
6539 case 0x0b:
6540 if (set_cc) {
6541 gen_helper_add_cc(tmp, tmp, tmp2);
6543 dead_tmp(tmp);
6544 break;
6545 case 0x0c:
6546 tcg_gen_or_i32(tmp, tmp, tmp2);
6547 if (logic_cc) {
6548 gen_logic_CC(tmp);
6550 store_reg_bx(env, s, rd, tmp);
6551 break;
6552 case 0x0d:
6553 if (logic_cc && rd == 15) {
6554 /* MOVS r15, ... is used for exception return. */
6555 if (IS_USER(s)) {
6556 goto illegal_op;
6558 gen_exception_return(s, tmp2);
6559 } else {
6560 if (logic_cc) {
6561 gen_logic_CC(tmp2);
6563 store_reg_bx(env, s, rd, tmp2);
6565 break;
6566 case 0x0e:
6567 tcg_gen_andc_i32(tmp, tmp, tmp2);
6568 if (logic_cc) {
6569 gen_logic_CC(tmp);
6571 store_reg_bx(env, s, rd, tmp);
6572 break;
6573 default:
6574 case 0x0f:
6575 tcg_gen_not_i32(tmp2, tmp2);
6576 if (logic_cc) {
6577 gen_logic_CC(tmp2);
6579 store_reg_bx(env, s, rd, tmp2);
6580 break;
6582 if (op1 != 0x0f && op1 != 0x0d) {
6583 dead_tmp(tmp2);
6585 } else {
6586 /* other instructions */
6587 op1 = (insn >> 24) & 0xf;
6588 switch(op1) {
6589 case 0x0:
6590 case 0x1:
6591 /* multiplies, extra load/stores */
6592 sh = (insn >> 5) & 3;
6593 if (sh == 0) {
6594 if (op1 == 0x0) {
6595 rd = (insn >> 16) & 0xf;
6596 rn = (insn >> 12) & 0xf;
6597 rs = (insn >> 8) & 0xf;
6598 rm = (insn) & 0xf;
6599 op1 = (insn >> 20) & 0xf;
6600 switch (op1) {
6601 case 0: case 1: case 2: case 3: case 6:
6602 /* 32 bit mul */
6603 tmp = load_reg(s, rs);
6604 tmp2 = load_reg(s, rm);
6605 tcg_gen_mul_i32(tmp, tmp, tmp2);
6606 dead_tmp(tmp2);
6607 if (insn & (1 << 22)) {
6608 /* Subtract (mls) */
6609 ARCH(6T2);
6610 tmp2 = load_reg(s, rn);
6611 tcg_gen_sub_i32(tmp, tmp2, tmp);
6612 dead_tmp(tmp2);
6613 } else if (insn & (1 << 21)) {
6614 /* Add */
6615 tmp2 = load_reg(s, rn);
6616 tcg_gen_add_i32(tmp, tmp, tmp2);
6617 dead_tmp(tmp2);
6619 if (insn & (1 << 20))
6620 gen_logic_CC(tmp);
6621 store_reg(s, rd, tmp);
6622 break;
6623 default:
6624 /* 64 bit mul */
6625 tmp = load_reg(s, rs);
6626 tmp2 = load_reg(s, rm);
6627 if (insn & (1 << 22))
6628 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6629 else
6630 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6631 if (insn & (1 << 21)) /* mult accumulate */
6632 gen_addq(s, tmp64, rn, rd);
6633 if (!(insn & (1 << 23))) { /* double accumulate */
6634 ARCH(6);
6635 gen_addq_lo(s, tmp64, rn);
6636 gen_addq_lo(s, tmp64, rd);
6638 if (insn & (1 << 20))
6639 gen_logicq_cc(tmp64);
6640 gen_storeq_reg(s, rn, rd, tmp64);
6641 tcg_temp_free_i64(tmp64);
6642 break;
6644 } else {
6645 rn = (insn >> 16) & 0xf;
6646 rd = (insn >> 12) & 0xf;
6647 if (insn & (1 << 23)) {
6648 /* load/store exclusive */
6649 op1 = (insn >> 21) & 0x3;
6650 if (op1)
6651 ARCH(6K);
6652 else
6653 ARCH(6);
6654 addr = tcg_temp_local_new_i32();
6655 load_reg_var(s, addr, rn);
6656 if (insn & (1 << 20)) {
6657 switch (op1) {
6658 case 0: /* ldrex */
6659 gen_load_exclusive(s, rd, 15, addr, 2);
6660 break;
6661 case 1: /* ldrexd */
6662 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6663 break;
6664 case 2: /* ldrexb */
6665 gen_load_exclusive(s, rd, 15, addr, 0);
6666 break;
6667 case 3: /* ldrexh */
6668 gen_load_exclusive(s, rd, 15, addr, 1);
6669 break;
6670 default:
6671 abort();
6673 } else {
6674 rm = insn & 0xf;
6675 switch (op1) {
6676 case 0: /* strex */
6677 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6678 break;
6679 case 1: /* strexd */
6680 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6681 break;
6682 case 2: /* strexb */
6683 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6684 break;
6685 case 3: /* strexh */
6686 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6687 break;
6688 default:
6689 abort();
6692 tcg_temp_free(addr);
6693 } else {
6694 /* SWP instruction */
6695 rm = (insn) & 0xf;
6697 /* ??? This is not really atomic. However we know
6698 we never have multiple CPUs running in parallel,
6699 so it is good enough. */
6700 addr = load_reg(s, rn);
6701 tmp = load_reg(s, rm);
6702 if (insn & (1 << 22)) {
6703 tmp2 = gen_ld8u(addr, IS_USER(s));
6704 gen_st8(tmp, addr, IS_USER(s));
6705 } else {
6706 tmp2 = gen_ld32(addr, IS_USER(s));
6707 gen_st32(tmp, addr, IS_USER(s));
6709 dead_tmp(addr);
6710 store_reg(s, rd, tmp2);
6713 } else {
6714 int address_offset;
6715 int load;
6716 /* Misc load/store */
6717 rn = (insn >> 16) & 0xf;
6718 rd = (insn >> 12) & 0xf;
6719 addr = load_reg(s, rn);
6720 if (insn & (1 << 24))
6721 gen_add_datah_offset(s, insn, 0, addr);
6722 address_offset = 0;
6723 if (insn & (1 << 20)) {
6724 /* load */
6725 switch(sh) {
6726 case 1:
6727 tmp = gen_ld16u(addr, IS_USER(s));
6728 break;
6729 case 2:
6730 tmp = gen_ld8s(addr, IS_USER(s));
6731 break;
6732 default:
6733 case 3:
6734 tmp = gen_ld16s(addr, IS_USER(s));
6735 break;
6737 load = 1;
6738 } else if (sh & 2) {
6739 /* doubleword */
6740 if (sh & 1) {
6741 /* store */
6742 tmp = load_reg(s, rd);
6743 gen_st32(tmp, addr, IS_USER(s));
6744 tcg_gen_addi_i32(addr, addr, 4);
6745 tmp = load_reg(s, rd + 1);
6746 gen_st32(tmp, addr, IS_USER(s));
6747 load = 0;
6748 } else {
6749 /* load */
6750 tmp = gen_ld32(addr, IS_USER(s));
6751 store_reg(s, rd, tmp);
6752 tcg_gen_addi_i32(addr, addr, 4);
6753 tmp = gen_ld32(addr, IS_USER(s));
6754 rd++;
6755 load = 1;
6757 address_offset = -4;
6758 } else {
6759 /* store */
6760 tmp = load_reg(s, rd);
6761 gen_st16(tmp, addr, IS_USER(s));
6762 load = 0;
6764 /* Perform base writeback before the loaded value to
6765 ensure correct behavior with overlapping index registers.
6766 ldrd with base writeback is is undefined if the
6767 destination and index registers overlap. */
6768 if (!(insn & (1 << 24))) {
6769 gen_add_datah_offset(s, insn, address_offset, addr);
6770 store_reg(s, rn, addr);
6771 } else if (insn & (1 << 21)) {
6772 if (address_offset)
6773 tcg_gen_addi_i32(addr, addr, address_offset);
6774 store_reg(s, rn, addr);
6775 } else {
6776 dead_tmp(addr);
6778 if (load) {
6779 /* Complete the load. */
6780 store_reg(s, rd, tmp);
6783 break;
6784 case 0x4:
6785 case 0x5:
6786 goto do_ldst;
6787 case 0x6:
6788 case 0x7:
6789 if (insn & (1 << 4)) {
6790 ARCH(6);
6791 /* Armv6 Media instructions. */
6792 rm = insn & 0xf;
6793 rn = (insn >> 16) & 0xf;
6794 rd = (insn >> 12) & 0xf;
6795 rs = (insn >> 8) & 0xf;
6796 switch ((insn >> 23) & 3) {
6797 case 0: /* Parallel add/subtract. */
6798 op1 = (insn >> 20) & 7;
6799 tmp = load_reg(s, rn);
6800 tmp2 = load_reg(s, rm);
6801 sh = (insn >> 5) & 7;
6802 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6803 goto illegal_op;
6804 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6805 dead_tmp(tmp2);
6806 store_reg(s, rd, tmp);
6807 break;
6808 case 1:
6809 if ((insn & 0x00700020) == 0) {
6810 /* Halfword pack. */
6811 tmp = load_reg(s, rn);
6812 tmp2 = load_reg(s, rm);
6813 shift = (insn >> 7) & 0x1f;
6814 if (insn & (1 << 6)) {
6815 /* pkhtb */
6816 if (shift == 0)
6817 shift = 31;
6818 tcg_gen_sari_i32(tmp2, tmp2, shift);
6819 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6820 tcg_gen_ext16u_i32(tmp2, tmp2);
6821 } else {
6822 /* pkhbt */
6823 if (shift)
6824 tcg_gen_shli_i32(tmp2, tmp2, shift);
6825 tcg_gen_ext16u_i32(tmp, tmp);
6826 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6828 tcg_gen_or_i32(tmp, tmp, tmp2);
6829 dead_tmp(tmp2);
6830 store_reg(s, rd, tmp);
6831 } else if ((insn & 0x00200020) == 0x00200000) {
6832 /* [us]sat */
6833 tmp = load_reg(s, rm);
6834 shift = (insn >> 7) & 0x1f;
6835 if (insn & (1 << 6)) {
6836 if (shift == 0)
6837 shift = 31;
6838 tcg_gen_sari_i32(tmp, tmp, shift);
6839 } else {
6840 tcg_gen_shli_i32(tmp, tmp, shift);
6842 sh = (insn >> 16) & 0x1f;
6843 if (sh != 0) {
6844 tmp2 = tcg_const_i32(sh);
6845 if (insn & (1 << 22))
6846 gen_helper_usat(tmp, tmp, tmp2);
6847 else
6848 gen_helper_ssat(tmp, tmp, tmp2);
6849 tcg_temp_free_i32(tmp2);
6851 store_reg(s, rd, tmp);
6852 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6853 /* [us]sat16 */
6854 tmp = load_reg(s, rm);
6855 sh = (insn >> 16) & 0x1f;
6856 if (sh != 0) {
6857 tmp2 = tcg_const_i32(sh);
6858 if (insn & (1 << 22))
6859 gen_helper_usat16(tmp, tmp, tmp2);
6860 else
6861 gen_helper_ssat16(tmp, tmp, tmp2);
6862 tcg_temp_free_i32(tmp2);
6864 store_reg(s, rd, tmp);
6865 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6866 /* Select bytes. */
6867 tmp = load_reg(s, rn);
6868 tmp2 = load_reg(s, rm);
6869 tmp3 = new_tmp();
6870 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6871 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6872 dead_tmp(tmp3);
6873 dead_tmp(tmp2);
6874 store_reg(s, rd, tmp);
6875 } else if ((insn & 0x000003e0) == 0x00000060) {
6876 tmp = load_reg(s, rm);
6877 shift = (insn >> 10) & 3;
6878 /* ??? In many cases it's not neccessary to do a
6879 rotate, a shift is sufficient. */
6880 if (shift != 0)
6881 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6882 op1 = (insn >> 20) & 7;
6883 switch (op1) {
6884 case 0: gen_sxtb16(tmp); break;
6885 case 2: gen_sxtb(tmp); break;
6886 case 3: gen_sxth(tmp); break;
6887 case 4: gen_uxtb16(tmp); break;
6888 case 6: gen_uxtb(tmp); break;
6889 case 7: gen_uxth(tmp); break;
6890 default: goto illegal_op;
6892 if (rn != 15) {
6893 tmp2 = load_reg(s, rn);
6894 if ((op1 & 3) == 0) {
6895 gen_add16(tmp, tmp2);
6896 } else {
6897 tcg_gen_add_i32(tmp, tmp, tmp2);
6898 dead_tmp(tmp2);
6901 store_reg(s, rd, tmp);
6902 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6903 /* rev */
6904 tmp = load_reg(s, rm);
6905 if (insn & (1 << 22)) {
6906 if (insn & (1 << 7)) {
6907 gen_revsh(tmp);
6908 } else {
6909 ARCH(6T2);
6910 gen_helper_rbit(tmp, tmp);
6912 } else {
6913 if (insn & (1 << 7))
6914 gen_rev16(tmp);
6915 else
6916 tcg_gen_bswap32_i32(tmp, tmp);
6918 store_reg(s, rd, tmp);
6919 } else {
6920 goto illegal_op;
6922 break;
6923 case 2: /* Multiplies (Type 3). */
6924 tmp = load_reg(s, rm);
6925 tmp2 = load_reg(s, rs);
6926 if (insn & (1 << 20)) {
6927 /* Signed multiply most significant [accumulate]. */
6928 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6929 if (insn & (1 << 5))
6930 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6931 tcg_gen_shri_i64(tmp64, tmp64, 32);
6932 tmp = new_tmp();
6933 tcg_gen_trunc_i64_i32(tmp, tmp64);
6934 tcg_temp_free_i64(tmp64);
6935 if (rd != 15) {
6936 tmp2 = load_reg(s, rd);
6937 if (insn & (1 << 6)) {
6938 tcg_gen_sub_i32(tmp, tmp, tmp2);
6939 } else {
6940 tcg_gen_add_i32(tmp, tmp, tmp2);
6942 dead_tmp(tmp2);
6944 store_reg(s, rn, tmp);
6945 } else {
6946 if (insn & (1 << 5))
6947 gen_swap_half(tmp2);
6948 gen_smul_dual(tmp, tmp2);
6949 /* This addition cannot overflow. */
6950 if (insn & (1 << 6)) {
6951 tcg_gen_sub_i32(tmp, tmp, tmp2);
6952 } else {
6953 tcg_gen_add_i32(tmp, tmp, tmp2);
6955 dead_tmp(tmp2);
6956 if (insn & (1 << 22)) {
6957 /* smlald, smlsld */
6958 tmp64 = tcg_temp_new_i64();
6959 tcg_gen_ext_i32_i64(tmp64, tmp);
6960 dead_tmp(tmp);
6961 gen_addq(s, tmp64, rd, rn);
6962 gen_storeq_reg(s, rd, rn, tmp64);
6963 tcg_temp_free_i64(tmp64);
6964 } else {
6965 /* smuad, smusd, smlad, smlsd */
6966 if (rd != 15)
6968 tmp2 = load_reg(s, rd);
6969 gen_helper_add_setq(tmp, tmp, tmp2);
6970 dead_tmp(tmp2);
6972 store_reg(s, rn, tmp);
6975 break;
6976 case 3:
6977 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6978 switch (op1) {
6979 case 0: /* Unsigned sum of absolute differences. */
6980 ARCH(6);
6981 tmp = load_reg(s, rm);
6982 tmp2 = load_reg(s, rs);
6983 gen_helper_usad8(tmp, tmp, tmp2);
6984 dead_tmp(tmp2);
6985 if (rd != 15) {
6986 tmp2 = load_reg(s, rd);
6987 tcg_gen_add_i32(tmp, tmp, tmp2);
6988 dead_tmp(tmp2);
6990 store_reg(s, rn, tmp);
6991 break;
6992 case 0x20: case 0x24: case 0x28: case 0x2c:
6993 /* Bitfield insert/clear. */
6994 ARCH(6T2);
6995 shift = (insn >> 7) & 0x1f;
6996 i = (insn >> 16) & 0x1f;
6997 i = i + 1 - shift;
6998 if (rm == 15) {
6999 tmp = new_tmp();
7000 tcg_gen_movi_i32(tmp, 0);
7001 } else {
7002 tmp = load_reg(s, rm);
7004 if (i != 32) {
7005 tmp2 = load_reg(s, rd);
7006 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7007 dead_tmp(tmp2);
7009 store_reg(s, rd, tmp);
7010 break;
7011 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7012 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7013 ARCH(6T2);
7014 tmp = load_reg(s, rm);
7015 shift = (insn >> 7) & 0x1f;
7016 i = ((insn >> 16) & 0x1f) + 1;
7017 if (shift + i > 32)
7018 goto illegal_op;
7019 if (i < 32) {
7020 if (op1 & 0x20) {
7021 gen_ubfx(tmp, shift, (1u << i) - 1);
7022 } else {
7023 gen_sbfx(tmp, shift, i);
7026 store_reg(s, rd, tmp);
7027 break;
7028 default:
7029 goto illegal_op;
7031 break;
7033 break;
7035 do_ldst:
7036 /* Check for undefined extension instructions
7037 * per the ARM Bible IE:
7038 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7040 sh = (0xf << 20) | (0xf << 4);
7041 if (op1 == 0x7 && ((insn & sh) == sh))
7043 goto illegal_op;
7045 /* load/store byte/word */
7046 rn = (insn >> 16) & 0xf;
7047 rd = (insn >> 12) & 0xf;
7048 tmp2 = load_reg(s, rn);
7049 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7050 if (insn & (1 << 24))
7051 gen_add_data_offset(s, insn, tmp2);
7052 if (insn & (1 << 20)) {
7053 /* load */
7054 if (insn & (1 << 22)) {
7055 tmp = gen_ld8u(tmp2, i);
7056 } else {
7057 tmp = gen_ld32(tmp2, i);
7059 } else {
7060 /* store */
7061 tmp = load_reg(s, rd);
7062 if (insn & (1 << 22))
7063 gen_st8(tmp, tmp2, i);
7064 else
7065 gen_st32(tmp, tmp2, i);
7067 if (!(insn & (1 << 24))) {
7068 gen_add_data_offset(s, insn, tmp2);
7069 store_reg(s, rn, tmp2);
7070 } else if (insn & (1 << 21)) {
7071 store_reg(s, rn, tmp2);
7072 } else {
7073 dead_tmp(tmp2);
7075 if (insn & (1 << 20)) {
7076 /* Complete the load. */
7077 if (rd == 15)
7078 gen_bx(s, tmp);
7079 else
7080 store_reg(s, rd, tmp);
7082 break;
7083 case 0x08:
7084 case 0x09:
7086 int j, n, user, loaded_base;
7087 TCGv loaded_var;
7088 /* load/store multiple words */
7089 /* XXX: store correct base if write back */
7090 user = 0;
7091 if (insn & (1 << 22)) {
7092 if (IS_USER(s))
7093 goto illegal_op; /* only usable in supervisor mode */
7095 if ((insn & (1 << 15)) == 0)
7096 user = 1;
7098 rn = (insn >> 16) & 0xf;
7099 addr = load_reg(s, rn);
7101 /* compute total size */
7102 loaded_base = 0;
7103 TCGV_UNUSED(loaded_var);
7104 n = 0;
7105 for(i=0;i<16;i++) {
7106 if (insn & (1 << i))
7107 n++;
7109 /* XXX: test invalid n == 0 case ? */
7110 if (insn & (1 << 23)) {
7111 if (insn & (1 << 24)) {
7112 /* pre increment */
7113 tcg_gen_addi_i32(addr, addr, 4);
7114 } else {
7115 /* post increment */
7117 } else {
7118 if (insn & (1 << 24)) {
7119 /* pre decrement */
7120 tcg_gen_addi_i32(addr, addr, -(n * 4));
7121 } else {
7122 /* post decrement */
7123 if (n != 1)
7124 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7127 j = 0;
7128 for(i=0;i<16;i++) {
7129 if (insn & (1 << i)) {
7130 if (insn & (1 << 20)) {
7131 /* load */
7132 tmp = gen_ld32(addr, IS_USER(s));
7133 if (i == 15) {
7134 gen_bx(s, tmp);
7135 } else if (user) {
7136 tmp2 = tcg_const_i32(i);
7137 gen_helper_set_user_reg(tmp2, tmp);
7138 tcg_temp_free_i32(tmp2);
7139 dead_tmp(tmp);
7140 } else if (i == rn) {
7141 loaded_var = tmp;
7142 loaded_base = 1;
7143 } else {
7144 store_reg(s, i, tmp);
7146 } else {
7147 /* store */
7148 if (i == 15) {
7149 /* special case: r15 = PC + 8 */
7150 val = (long)s->pc + 4;
7151 tmp = new_tmp();
7152 tcg_gen_movi_i32(tmp, val);
7153 } else if (user) {
7154 tmp = new_tmp();
7155 tmp2 = tcg_const_i32(i);
7156 gen_helper_get_user_reg(tmp, tmp2);
7157 tcg_temp_free_i32(tmp2);
7158 } else {
7159 tmp = load_reg(s, i);
7161 gen_st32(tmp, addr, IS_USER(s));
7163 j++;
7164 /* no need to add after the last transfer */
7165 if (j != n)
7166 tcg_gen_addi_i32(addr, addr, 4);
7169 if (insn & (1 << 21)) {
7170 /* write back */
7171 if (insn & (1 << 23)) {
7172 if (insn & (1 << 24)) {
7173 /* pre increment */
7174 } else {
7175 /* post increment */
7176 tcg_gen_addi_i32(addr, addr, 4);
7178 } else {
7179 if (insn & (1 << 24)) {
7180 /* pre decrement */
7181 if (n != 1)
7182 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7183 } else {
7184 /* post decrement */
7185 tcg_gen_addi_i32(addr, addr, -(n * 4));
7188 store_reg(s, rn, addr);
7189 } else {
7190 dead_tmp(addr);
7192 if (loaded_base) {
7193 store_reg(s, rn, loaded_var);
7195 if ((insn & (1 << 22)) && !user) {
7196 /* Restore CPSR from SPSR. */
7197 tmp = load_cpu_field(spsr);
7198 gen_set_cpsr(tmp, 0xffffffff);
7199 dead_tmp(tmp);
7200 s->is_jmp = DISAS_UPDATE;
7203 break;
7204 case 0xa:
7205 case 0xb:
7207 int32_t offset;
7209 /* branch (and link) */
7210 val = (int32_t)s->pc;
7211 if (insn & (1 << 24)) {
7212 tmp = new_tmp();
7213 tcg_gen_movi_i32(tmp, val);
7214 store_reg(s, 14, tmp);
7216 offset = (((int32_t)insn << 8) >> 8);
7217 val += (offset << 2) + 4;
7218 gen_jmp(s, val);
7220 break;
7221 case 0xc:
7222 case 0xd:
7223 case 0xe:
7224 /* Coprocessor. */
7225 if (disas_coproc_insn(env, s, insn))
7226 goto illegal_op;
7227 break;
7228 case 0xf:
7229 /* swi */
7230 gen_set_pc_im(s->pc);
7231 s->is_jmp = DISAS_SWI;
7232 break;
7233 default:
7234 illegal_op:
7235 gen_set_condexec(s);
7236 gen_set_pc_im(s->pc - 4);
7237 gen_exception(EXCP_UDEF);
7238 s->is_jmp = DISAS_JUMP;
7239 break;
7244 /* Return true if this is a Thumb-2 logical op. */
7245 static int
7246 thumb2_logic_op(int op)
7248 return (op < 8);
7251 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7252 then set condition code flags based on the result of the operation.
7253 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7254 to the high bit of T1.
7255 Returns zero if the opcode is valid. */
7257 static int
7258 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7260 int logic_cc;
7262 logic_cc = 0;
7263 switch (op) {
7264 case 0: /* and */
7265 tcg_gen_and_i32(t0, t0, t1);
7266 logic_cc = conds;
7267 break;
7268 case 1: /* bic */
7269 tcg_gen_andc_i32(t0, t0, t1);
7270 logic_cc = conds;
7271 break;
7272 case 2: /* orr */
7273 tcg_gen_or_i32(t0, t0, t1);
7274 logic_cc = conds;
7275 break;
7276 case 3: /* orn */
7277 tcg_gen_not_i32(t1, t1);
7278 tcg_gen_or_i32(t0, t0, t1);
7279 logic_cc = conds;
7280 break;
7281 case 4: /* eor */
7282 tcg_gen_xor_i32(t0, t0, t1);
7283 logic_cc = conds;
7284 break;
7285 case 8: /* add */
7286 if (conds)
7287 gen_helper_add_cc(t0, t0, t1);
7288 else
7289 tcg_gen_add_i32(t0, t0, t1);
7290 break;
7291 case 10: /* adc */
7292 if (conds)
7293 gen_helper_adc_cc(t0, t0, t1);
7294 else
7295 gen_adc(t0, t1);
7296 break;
7297 case 11: /* sbc */
7298 if (conds)
7299 gen_helper_sbc_cc(t0, t0, t1);
7300 else
7301 gen_sub_carry(t0, t0, t1);
7302 break;
7303 case 13: /* sub */
7304 if (conds)
7305 gen_helper_sub_cc(t0, t0, t1);
7306 else
7307 tcg_gen_sub_i32(t0, t0, t1);
7308 break;
7309 case 14: /* rsb */
7310 if (conds)
7311 gen_helper_sub_cc(t0, t1, t0);
7312 else
7313 tcg_gen_sub_i32(t0, t1, t0);
7314 break;
7315 default: /* 5, 6, 7, 9, 12, 15. */
7316 return 1;
7318 if (logic_cc) {
7319 gen_logic_CC(t0);
7320 if (shifter_out)
7321 gen_set_CF_bit31(t1);
7323 return 0;
7326 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7327 is not legal. */
7328 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7330 uint32_t insn, imm, shift, offset;
7331 uint32_t rd, rn, rm, rs;
7332 TCGv tmp;
7333 TCGv tmp2;
7334 TCGv tmp3;
7335 TCGv addr;
7336 TCGv_i64 tmp64;
7337 int op;
7338 int shiftop;
7339 int conds;
7340 int logic_cc;
7342 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7343 || arm_feature (env, ARM_FEATURE_M))) {
7344 /* Thumb-1 cores may need to treat bl and blx as a pair of
7345 16-bit instructions to get correct prefetch abort behavior. */
7346 insn = insn_hw1;
7347 if ((insn & (1 << 12)) == 0) {
7348 /* Second half of blx. */
7349 offset = ((insn & 0x7ff) << 1);
7350 tmp = load_reg(s, 14);
7351 tcg_gen_addi_i32(tmp, tmp, offset);
7352 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7354 tmp2 = new_tmp();
7355 tcg_gen_movi_i32(tmp2, s->pc | 1);
7356 store_reg(s, 14, tmp2);
7357 gen_bx(s, tmp);
7358 return 0;
7360 if (insn & (1 << 11)) {
7361 /* Second half of bl. */
7362 offset = ((insn & 0x7ff) << 1) | 1;
7363 tmp = load_reg(s, 14);
7364 tcg_gen_addi_i32(tmp, tmp, offset);
7366 tmp2 = new_tmp();
7367 tcg_gen_movi_i32(tmp2, s->pc | 1);
7368 store_reg(s, 14, tmp2);
7369 gen_bx(s, tmp);
7370 return 0;
7372 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7373 /* Instruction spans a page boundary. Implement it as two
7374 16-bit instructions in case the second half causes an
7375 prefetch abort. */
7376 offset = ((int32_t)insn << 21) >> 9;
7377 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7378 return 0;
7380 /* Fall through to 32-bit decode. */
7383 insn = lduw_code(s->pc);
7384 s->pc += 2;
7385 insn |= (uint32_t)insn_hw1 << 16;
7387 if ((insn & 0xf800e800) != 0xf000e800) {
7388 ARCH(6T2);
7391 rn = (insn >> 16) & 0xf;
7392 rs = (insn >> 12) & 0xf;
7393 rd = (insn >> 8) & 0xf;
7394 rm = insn & 0xf;
7395 switch ((insn >> 25) & 0xf) {
7396 case 0: case 1: case 2: case 3:
7397 /* 16-bit instructions. Should never happen. */
7398 abort();
7399 case 4:
7400 if (insn & (1 << 22)) {
7401 /* Other load/store, table branch. */
7402 if (insn & 0x01200000) {
7403 /* Load/store doubleword. */
7404 if (rn == 15) {
7405 addr = new_tmp();
7406 tcg_gen_movi_i32(addr, s->pc & ~3);
7407 } else {
7408 addr = load_reg(s, rn);
7410 offset = (insn & 0xff) * 4;
7411 if ((insn & (1 << 23)) == 0)
7412 offset = -offset;
7413 if (insn & (1 << 24)) {
7414 tcg_gen_addi_i32(addr, addr, offset);
7415 offset = 0;
7417 if (insn & (1 << 20)) {
7418 /* ldrd */
7419 tmp = gen_ld32(addr, IS_USER(s));
7420 store_reg(s, rs, tmp);
7421 tcg_gen_addi_i32(addr, addr, 4);
7422 tmp = gen_ld32(addr, IS_USER(s));
7423 store_reg(s, rd, tmp);
7424 } else {
7425 /* strd */
7426 tmp = load_reg(s, rs);
7427 gen_st32(tmp, addr, IS_USER(s));
7428 tcg_gen_addi_i32(addr, addr, 4);
7429 tmp = load_reg(s, rd);
7430 gen_st32(tmp, addr, IS_USER(s));
7432 if (insn & (1 << 21)) {
7433 /* Base writeback. */
7434 if (rn == 15)
7435 goto illegal_op;
7436 tcg_gen_addi_i32(addr, addr, offset - 4);
7437 store_reg(s, rn, addr);
7438 } else {
7439 dead_tmp(addr);
7441 } else if ((insn & (1 << 23)) == 0) {
7442 /* Load/store exclusive word. */
7443 addr = tcg_temp_local_new();
7444 load_reg_var(s, addr, rn);
7445 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7446 if (insn & (1 << 20)) {
7447 gen_load_exclusive(s, rs, 15, addr, 2);
7448 } else {
7449 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7451 tcg_temp_free(addr);
7452 } else if ((insn & (1 << 6)) == 0) {
7453 /* Table Branch. */
7454 if (rn == 15) {
7455 addr = new_tmp();
7456 tcg_gen_movi_i32(addr, s->pc);
7457 } else {
7458 addr = load_reg(s, rn);
7460 tmp = load_reg(s, rm);
7461 tcg_gen_add_i32(addr, addr, tmp);
7462 if (insn & (1 << 4)) {
7463 /* tbh */
7464 tcg_gen_add_i32(addr, addr, tmp);
7465 dead_tmp(tmp);
7466 tmp = gen_ld16u(addr, IS_USER(s));
7467 } else { /* tbb */
7468 dead_tmp(tmp);
7469 tmp = gen_ld8u(addr, IS_USER(s));
7471 dead_tmp(addr);
7472 tcg_gen_shli_i32(tmp, tmp, 1);
7473 tcg_gen_addi_i32(tmp, tmp, s->pc);
7474 store_reg(s, 15, tmp);
7475 } else {
7476 /* Load/store exclusive byte/halfword/doubleword. */
7477 ARCH(7);
7478 op = (insn >> 4) & 0x3;
7479 if (op == 2) {
7480 goto illegal_op;
7482 addr = tcg_temp_local_new();
7483 load_reg_var(s, addr, rn);
7484 if (insn & (1 << 20)) {
7485 gen_load_exclusive(s, rs, rd, addr, op);
7486 } else {
7487 gen_store_exclusive(s, rm, rs, rd, addr, op);
7489 tcg_temp_free(addr);
7491 } else {
7492 /* Load/store multiple, RFE, SRS. */
7493 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7494 /* Not available in user mode. */
7495 if (IS_USER(s))
7496 goto illegal_op;
7497 if (insn & (1 << 20)) {
7498 /* rfe */
7499 addr = load_reg(s, rn);
7500 if ((insn & (1 << 24)) == 0)
7501 tcg_gen_addi_i32(addr, addr, -8);
7502 /* Load PC into tmp and CPSR into tmp2. */
7503 tmp = gen_ld32(addr, 0);
7504 tcg_gen_addi_i32(addr, addr, 4);
7505 tmp2 = gen_ld32(addr, 0);
7506 if (insn & (1 << 21)) {
7507 /* Base writeback. */
7508 if (insn & (1 << 24)) {
7509 tcg_gen_addi_i32(addr, addr, 4);
7510 } else {
7511 tcg_gen_addi_i32(addr, addr, -4);
7513 store_reg(s, rn, addr);
7514 } else {
7515 dead_tmp(addr);
7517 gen_rfe(s, tmp, tmp2);
7518 } else {
7519 /* srs */
7520 op = (insn & 0x1f);
7521 if (op == (env->uncached_cpsr & CPSR_M)) {
7522 addr = load_reg(s, 13);
7523 } else {
7524 addr = new_tmp();
7525 tmp = tcg_const_i32(op);
7526 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7527 tcg_temp_free_i32(tmp);
7529 if ((insn & (1 << 24)) == 0) {
7530 tcg_gen_addi_i32(addr, addr, -8);
7532 tmp = load_reg(s, 14);
7533 gen_st32(tmp, addr, 0);
7534 tcg_gen_addi_i32(addr, addr, 4);
7535 tmp = new_tmp();
7536 gen_helper_cpsr_read(tmp);
7537 gen_st32(tmp, addr, 0);
7538 if (insn & (1 << 21)) {
7539 if ((insn & (1 << 24)) == 0) {
7540 tcg_gen_addi_i32(addr, addr, -4);
7541 } else {
7542 tcg_gen_addi_i32(addr, addr, 4);
7544 if (op == (env->uncached_cpsr & CPSR_M)) {
7545 store_reg(s, 13, addr);
7546 } else {
7547 tmp = tcg_const_i32(op);
7548 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7549 tcg_temp_free_i32(tmp);
7551 } else {
7552 dead_tmp(addr);
7555 } else {
7556 int i;
7557 /* Load/store multiple. */
7558 addr = load_reg(s, rn);
7559 offset = 0;
7560 for (i = 0; i < 16; i++) {
7561 if (insn & (1 << i))
7562 offset += 4;
7564 if (insn & (1 << 24)) {
7565 tcg_gen_addi_i32(addr, addr, -offset);
7568 for (i = 0; i < 16; i++) {
7569 if ((insn & (1 << i)) == 0)
7570 continue;
7571 if (insn & (1 << 20)) {
7572 /* Load. */
7573 tmp = gen_ld32(addr, IS_USER(s));
7574 if (i == 15) {
7575 gen_bx(s, tmp);
7576 } else {
7577 store_reg(s, i, tmp);
7579 } else {
7580 /* Store. */
7581 tmp = load_reg(s, i);
7582 gen_st32(tmp, addr, IS_USER(s));
7584 tcg_gen_addi_i32(addr, addr, 4);
7586 if (insn & (1 << 21)) {
7587 /* Base register writeback. */
7588 if (insn & (1 << 24)) {
7589 tcg_gen_addi_i32(addr, addr, -offset);
7591 /* Fault if writeback register is in register list. */
7592 if (insn & (1 << rn))
7593 goto illegal_op;
7594 store_reg(s, rn, addr);
7595 } else {
7596 dead_tmp(addr);
7600 break;
7601 case 5: /* Data processing register constant shift. */
7602 if (rn == 15) {
7603 tmp = new_tmp();
7604 tcg_gen_movi_i32(tmp, 0);
7605 } else {
7606 tmp = load_reg(s, rn);
7608 tmp2 = load_reg(s, rm);
7609 op = (insn >> 21) & 0xf;
7610 shiftop = (insn >> 4) & 3;
7611 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7612 conds = (insn & (1 << 20)) != 0;
7613 logic_cc = (conds && thumb2_logic_op(op));
7614 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7615 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7616 goto illegal_op;
7617 dead_tmp(tmp2);
7618 if (rd != 15) {
7619 store_reg(s, rd, tmp);
7620 } else {
7621 dead_tmp(tmp);
7623 break;
7624 case 13: /* Misc data processing. */
7625 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7626 if (op < 4 && (insn & 0xf000) != 0xf000)
7627 goto illegal_op;
7628 switch (op) {
7629 case 0: /* Register controlled shift. */
7630 tmp = load_reg(s, rn);
7631 tmp2 = load_reg(s, rm);
7632 if ((insn & 0x70) != 0)
7633 goto illegal_op;
7634 op = (insn >> 21) & 3;
7635 logic_cc = (insn & (1 << 20)) != 0;
7636 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7637 if (logic_cc)
7638 gen_logic_CC(tmp);
7639 store_reg_bx(env, s, rd, tmp);
7640 break;
7641 case 1: /* Sign/zero extend. */
7642 tmp = load_reg(s, rm);
7643 shift = (insn >> 4) & 3;
7644 /* ??? In many cases it's not neccessary to do a
7645 rotate, a shift is sufficient. */
7646 if (shift != 0)
7647 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7648 op = (insn >> 20) & 7;
7649 switch (op) {
7650 case 0: gen_sxth(tmp); break;
7651 case 1: gen_uxth(tmp); break;
7652 case 2: gen_sxtb16(tmp); break;
7653 case 3: gen_uxtb16(tmp); break;
7654 case 4: gen_sxtb(tmp); break;
7655 case 5: gen_uxtb(tmp); break;
7656 default: goto illegal_op;
7658 if (rn != 15) {
7659 tmp2 = load_reg(s, rn);
7660 if ((op >> 1) == 1) {
7661 gen_add16(tmp, tmp2);
7662 } else {
7663 tcg_gen_add_i32(tmp, tmp, tmp2);
7664 dead_tmp(tmp2);
7667 store_reg(s, rd, tmp);
7668 break;
7669 case 2: /* SIMD add/subtract. */
7670 op = (insn >> 20) & 7;
7671 shift = (insn >> 4) & 7;
7672 if ((op & 3) == 3 || (shift & 3) == 3)
7673 goto illegal_op;
7674 tmp = load_reg(s, rn);
7675 tmp2 = load_reg(s, rm);
7676 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7677 dead_tmp(tmp2);
7678 store_reg(s, rd, tmp);
7679 break;
7680 case 3: /* Other data processing. */
7681 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7682 if (op < 4) {
7683 /* Saturating add/subtract. */
7684 tmp = load_reg(s, rn);
7685 tmp2 = load_reg(s, rm);
7686 if (op & 2)
7687 gen_helper_double_saturate(tmp, tmp);
7688 if (op & 1)
7689 gen_helper_sub_saturate(tmp, tmp2, tmp);
7690 else
7691 gen_helper_add_saturate(tmp, tmp, tmp2);
7692 dead_tmp(tmp2);
7693 } else {
7694 tmp = load_reg(s, rn);
7695 switch (op) {
7696 case 0x0a: /* rbit */
7697 gen_helper_rbit(tmp, tmp);
7698 break;
7699 case 0x08: /* rev */
7700 tcg_gen_bswap32_i32(tmp, tmp);
7701 break;
7702 case 0x09: /* rev16 */
7703 gen_rev16(tmp);
7704 break;
7705 case 0x0b: /* revsh */
7706 gen_revsh(tmp);
7707 break;
7708 case 0x10: /* sel */
7709 tmp2 = load_reg(s, rm);
7710 tmp3 = new_tmp();
7711 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7712 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7713 dead_tmp(tmp3);
7714 dead_tmp(tmp2);
7715 break;
7716 case 0x18: /* clz */
7717 gen_helper_clz(tmp, tmp);
7718 break;
7719 default:
7720 goto illegal_op;
7723 store_reg(s, rd, tmp);
7724 break;
7725 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7726 op = (insn >> 4) & 0xf;
7727 tmp = load_reg(s, rn);
7728 tmp2 = load_reg(s, rm);
7729 switch ((insn >> 20) & 7) {
7730 case 0: /* 32 x 32 -> 32 */
7731 tcg_gen_mul_i32(tmp, tmp, tmp2);
7732 dead_tmp(tmp2);
7733 if (rs != 15) {
7734 tmp2 = load_reg(s, rs);
7735 if (op)
7736 tcg_gen_sub_i32(tmp, tmp2, tmp);
7737 else
7738 tcg_gen_add_i32(tmp, tmp, tmp2);
7739 dead_tmp(tmp2);
7741 break;
7742 case 1: /* 16 x 16 -> 32 */
7743 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7744 dead_tmp(tmp2);
7745 if (rs != 15) {
7746 tmp2 = load_reg(s, rs);
7747 gen_helper_add_setq(tmp, tmp, tmp2);
7748 dead_tmp(tmp2);
7750 break;
7751 case 2: /* Dual multiply add. */
7752 case 4: /* Dual multiply subtract. */
7753 if (op)
7754 gen_swap_half(tmp2);
7755 gen_smul_dual(tmp, tmp2);
7756 /* This addition cannot overflow. */
7757 if (insn & (1 << 22)) {
7758 tcg_gen_sub_i32(tmp, tmp, tmp2);
7759 } else {
7760 tcg_gen_add_i32(tmp, tmp, tmp2);
7762 dead_tmp(tmp2);
7763 if (rs != 15)
7765 tmp2 = load_reg(s, rs);
7766 gen_helper_add_setq(tmp, tmp, tmp2);
7767 dead_tmp(tmp2);
7769 break;
7770 case 3: /* 32 * 16 -> 32msb */
7771 if (op)
7772 tcg_gen_sari_i32(tmp2, tmp2, 16);
7773 else
7774 gen_sxth(tmp2);
7775 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7776 tcg_gen_shri_i64(tmp64, tmp64, 16);
7777 tmp = new_tmp();
7778 tcg_gen_trunc_i64_i32(tmp, tmp64);
7779 tcg_temp_free_i64(tmp64);
7780 if (rs != 15)
7782 tmp2 = load_reg(s, rs);
7783 gen_helper_add_setq(tmp, tmp, tmp2);
7784 dead_tmp(tmp2);
7786 break;
7787 case 5: case 6: /* 32 * 32 -> 32msb */
7788 gen_imull(tmp, tmp2);
7789 if (insn & (1 << 5)) {
7790 gen_roundqd(tmp, tmp2);
7791 dead_tmp(tmp2);
7792 } else {
7793 dead_tmp(tmp);
7794 tmp = tmp2;
7796 if (rs != 15) {
7797 tmp2 = load_reg(s, rs);
7798 if (insn & (1 << 21)) {
7799 tcg_gen_add_i32(tmp, tmp, tmp2);
7800 } else {
7801 tcg_gen_sub_i32(tmp, tmp2, tmp);
7803 dead_tmp(tmp2);
7805 break;
7806 case 7: /* Unsigned sum of absolute differences. */
7807 gen_helper_usad8(tmp, tmp, tmp2);
7808 dead_tmp(tmp2);
7809 if (rs != 15) {
7810 tmp2 = load_reg(s, rs);
7811 tcg_gen_add_i32(tmp, tmp, tmp2);
7812 dead_tmp(tmp2);
7814 break;
7816 store_reg(s, rd, tmp);
7817 break;
7818 case 6: case 7: /* 64-bit multiply, Divide. */
7819 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7820 tmp = load_reg(s, rn);
7821 tmp2 = load_reg(s, rm);
7822 if ((op & 0x50) == 0x10) {
7823 /* sdiv, udiv */
7824 if (!arm_feature(env, ARM_FEATURE_DIV))
7825 goto illegal_op;
7826 if (op & 0x20)
7827 gen_helper_udiv(tmp, tmp, tmp2);
7828 else
7829 gen_helper_sdiv(tmp, tmp, tmp2);
7830 dead_tmp(tmp2);
7831 store_reg(s, rd, tmp);
7832 } else if ((op & 0xe) == 0xc) {
7833 /* Dual multiply accumulate long. */
7834 if (op & 1)
7835 gen_swap_half(tmp2);
7836 gen_smul_dual(tmp, tmp2);
7837 if (op & 0x10) {
7838 tcg_gen_sub_i32(tmp, tmp, tmp2);
7839 } else {
7840 tcg_gen_add_i32(tmp, tmp, tmp2);
7842 dead_tmp(tmp2);
7843 /* BUGFIX */
7844 tmp64 = tcg_temp_new_i64();
7845 tcg_gen_ext_i32_i64(tmp64, tmp);
7846 dead_tmp(tmp);
7847 gen_addq(s, tmp64, rs, rd);
7848 gen_storeq_reg(s, rs, rd, tmp64);
7849 tcg_temp_free_i64(tmp64);
7850 } else {
7851 if (op & 0x20) {
7852 /* Unsigned 64-bit multiply */
7853 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7854 } else {
7855 if (op & 8) {
7856 /* smlalxy */
7857 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7858 dead_tmp(tmp2);
7859 tmp64 = tcg_temp_new_i64();
7860 tcg_gen_ext_i32_i64(tmp64, tmp);
7861 dead_tmp(tmp);
7862 } else {
7863 /* Signed 64-bit multiply */
7864 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7867 if (op & 4) {
7868 /* umaal */
7869 gen_addq_lo(s, tmp64, rs);
7870 gen_addq_lo(s, tmp64, rd);
7871 } else if (op & 0x40) {
7872 /* 64-bit accumulate. */
7873 gen_addq(s, tmp64, rs, rd);
7875 gen_storeq_reg(s, rs, rd, tmp64);
7876 tcg_temp_free_i64(tmp64);
7878 break;
7880 break;
7881 case 6: case 7: case 14: case 15:
7882 /* Coprocessor. */
7883 if (((insn >> 24) & 3) == 3) {
7884 /* Translate into the equivalent ARM encoding. */
7885 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7886 if (disas_neon_data_insn(env, s, insn))
7887 goto illegal_op;
7888 } else {
7889 if (insn & (1 << 28))
7890 goto illegal_op;
7891 if (disas_coproc_insn (env, s, insn))
7892 goto illegal_op;
7894 break;
7895 case 8: case 9: case 10: case 11:
7896 if (insn & (1 << 15)) {
7897 /* Branches, misc control. */
7898 if (insn & 0x5000) {
7899 /* Unconditional branch. */
7900 /* signextend(hw1[10:0]) -> offset[:12]. */
7901 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7902 /* hw1[10:0] -> offset[11:1]. */
7903 offset |= (insn & 0x7ff) << 1;
7904 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7905 offset[24:22] already have the same value because of the
7906 sign extension above. */
7907 offset ^= ((~insn) & (1 << 13)) << 10;
7908 offset ^= ((~insn) & (1 << 11)) << 11;
7910 if (insn & (1 << 14)) {
7911 /* Branch and link. */
7912 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7915 offset += s->pc;
7916 if (insn & (1 << 12)) {
7917 /* b/bl */
7918 gen_jmp(s, offset);
7919 } else {
7920 /* blx */
7921 offset &= ~(uint32_t)2;
7922 gen_bx_im(s, offset);
7924 } else if (((insn >> 23) & 7) == 7) {
7925 /* Misc control */
7926 if (insn & (1 << 13))
7927 goto illegal_op;
7929 if (insn & (1 << 26)) {
7930 /* Secure monitor call (v6Z) */
7931 goto illegal_op; /* not implemented. */
7932 } else {
7933 op = (insn >> 20) & 7;
7934 switch (op) {
7935 case 0: /* msr cpsr. */
7936 if (IS_M(env)) {
7937 tmp = load_reg(s, rn);
7938 addr = tcg_const_i32(insn & 0xff);
7939 gen_helper_v7m_msr(cpu_env, addr, tmp);
7940 tcg_temp_free_i32(addr);
7941 dead_tmp(tmp);
7942 gen_lookup_tb(s);
7943 break;
7945 /* fall through */
7946 case 1: /* msr spsr. */
7947 if (IS_M(env))
7948 goto illegal_op;
7949 tmp = load_reg(s, rn);
7950 if (gen_set_psr(s,
7951 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7952 op == 1, tmp))
7953 goto illegal_op;
7954 break;
7955 case 2: /* cps, nop-hint. */
7956 if (((insn >> 8) & 7) == 0) {
7957 gen_nop_hint(s, insn & 0xff);
7959 /* Implemented as NOP in user mode. */
7960 if (IS_USER(s))
7961 break;
7962 offset = 0;
7963 imm = 0;
7964 if (insn & (1 << 10)) {
7965 if (insn & (1 << 7))
7966 offset |= CPSR_A;
7967 if (insn & (1 << 6))
7968 offset |= CPSR_I;
7969 if (insn & (1 << 5))
7970 offset |= CPSR_F;
7971 if (insn & (1 << 9))
7972 imm = CPSR_A | CPSR_I | CPSR_F;
7974 if (insn & (1 << 8)) {
7975 offset |= 0x1f;
7976 imm |= (insn & 0x1f);
7978 if (offset) {
7979 gen_set_psr_im(s, offset, 0, imm);
7981 break;
7982 case 3: /* Special control operations. */
7983 ARCH(7);
7984 op = (insn >> 4) & 0xf;
7985 switch (op) {
7986 case 2: /* clrex */
7987 gen_clrex(s);
7988 break;
7989 case 4: /* dsb */
7990 case 5: /* dmb */
7991 case 6: /* isb */
7992 /* These execute as NOPs. */
7993 break;
7994 default:
7995 goto illegal_op;
7997 break;
7998 case 4: /* bxj */
7999 /* Trivial implementation equivalent to bx. */
8000 tmp = load_reg(s, rn);
8001 gen_bx(s, tmp);
8002 break;
8003 case 5: /* Exception return. */
8004 if (IS_USER(s)) {
8005 goto illegal_op;
8007 if (rn != 14 || rd != 15) {
8008 goto illegal_op;
8010 tmp = load_reg(s, rn);
8011 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8012 gen_exception_return(s, tmp);
8013 break;
8014 case 6: /* mrs cpsr. */
8015 tmp = new_tmp();
8016 if (IS_M(env)) {
8017 addr = tcg_const_i32(insn & 0xff);
8018 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8019 tcg_temp_free_i32(addr);
8020 } else {
8021 gen_helper_cpsr_read(tmp);
8023 store_reg(s, rd, tmp);
8024 break;
8025 case 7: /* mrs spsr. */
8026 /* Not accessible in user mode. */
8027 if (IS_USER(s) || IS_M(env))
8028 goto illegal_op;
8029 tmp = load_cpu_field(spsr);
8030 store_reg(s, rd, tmp);
8031 break;
8034 } else {
8035 /* Conditional branch. */
8036 op = (insn >> 22) & 0xf;
8037 /* Generate a conditional jump to next instruction. */
8038 s->condlabel = gen_new_label();
8039 gen_test_cc(op ^ 1, s->condlabel);
8040 s->condjmp = 1;
8042 /* offset[11:1] = insn[10:0] */
8043 offset = (insn & 0x7ff) << 1;
8044 /* offset[17:12] = insn[21:16]. */
8045 offset |= (insn & 0x003f0000) >> 4;
8046 /* offset[31:20] = insn[26]. */
8047 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8048 /* offset[18] = insn[13]. */
8049 offset |= (insn & (1 << 13)) << 5;
8050 /* offset[19] = insn[11]. */
8051 offset |= (insn & (1 << 11)) << 8;
8053 /* jump to the offset */
8054 gen_jmp(s, s->pc + offset);
8056 } else {
8057 /* Data processing immediate. */
8058 if (insn & (1 << 25)) {
8059 if (insn & (1 << 24)) {
8060 if (insn & (1 << 20))
8061 goto illegal_op;
8062 /* Bitfield/Saturate. */
8063 op = (insn >> 21) & 7;
8064 imm = insn & 0x1f;
8065 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8066 if (rn == 15) {
8067 tmp = new_tmp();
8068 tcg_gen_movi_i32(tmp, 0);
8069 } else {
8070 tmp = load_reg(s, rn);
8072 switch (op) {
8073 case 2: /* Signed bitfield extract. */
8074 imm++;
8075 if (shift + imm > 32)
8076 goto illegal_op;
8077 if (imm < 32)
8078 gen_sbfx(tmp, shift, imm);
8079 break;
8080 case 6: /* Unsigned bitfield extract. */
8081 imm++;
8082 if (shift + imm > 32)
8083 goto illegal_op;
8084 if (imm < 32)
8085 gen_ubfx(tmp, shift, (1u << imm) - 1);
8086 break;
8087 case 3: /* Bitfield insert/clear. */
8088 if (imm < shift)
8089 goto illegal_op;
8090 imm = imm + 1 - shift;
8091 if (imm != 32) {
8092 tmp2 = load_reg(s, rd);
8093 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8094 dead_tmp(tmp2);
8096 break;
8097 case 7:
8098 goto illegal_op;
8099 default: /* Saturate. */
8100 if (shift) {
8101 if (op & 1)
8102 tcg_gen_sari_i32(tmp, tmp, shift);
8103 else
8104 tcg_gen_shli_i32(tmp, tmp, shift);
8106 tmp2 = tcg_const_i32(imm);
8107 if (op & 4) {
8108 /* Unsigned. */
8109 if ((op & 1) && shift == 0)
8110 gen_helper_usat16(tmp, tmp, tmp2);
8111 else
8112 gen_helper_usat(tmp, tmp, tmp2);
8113 } else {
8114 /* Signed. */
8115 if ((op & 1) && shift == 0)
8116 gen_helper_ssat16(tmp, tmp, tmp2);
8117 else
8118 gen_helper_ssat(tmp, tmp, tmp2);
8120 tcg_temp_free_i32(tmp2);
8121 break;
8123 store_reg(s, rd, tmp);
8124 } else {
8125 imm = ((insn & 0x04000000) >> 15)
8126 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8127 if (insn & (1 << 22)) {
8128 /* 16-bit immediate. */
8129 imm |= (insn >> 4) & 0xf000;
8130 if (insn & (1 << 23)) {
8131 /* movt */
8132 tmp = load_reg(s, rd);
8133 tcg_gen_ext16u_i32(tmp, tmp);
8134 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8135 } else {
8136 /* movw */
8137 tmp = new_tmp();
8138 tcg_gen_movi_i32(tmp, imm);
8140 } else {
8141 /* Add/sub 12-bit immediate. */
8142 if (rn == 15) {
8143 offset = s->pc & ~(uint32_t)3;
8144 if (insn & (1 << 23))
8145 offset -= imm;
8146 else
8147 offset += imm;
8148 tmp = new_tmp();
8149 tcg_gen_movi_i32(tmp, offset);
8150 } else {
8151 tmp = load_reg(s, rn);
8152 if (insn & (1 << 23))
8153 tcg_gen_subi_i32(tmp, tmp, imm);
8154 else
8155 tcg_gen_addi_i32(tmp, tmp, imm);
8158 store_reg(s, rd, tmp);
8160 } else {
8161 int shifter_out = 0;
8162 /* modified 12-bit immediate. */
8163 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8164 imm = (insn & 0xff);
8165 switch (shift) {
8166 case 0: /* XY */
8167 /* Nothing to do. */
8168 break;
8169 case 1: /* 00XY00XY */
8170 imm |= imm << 16;
8171 break;
8172 case 2: /* XY00XY00 */
8173 imm |= imm << 16;
8174 imm <<= 8;
8175 break;
8176 case 3: /* XYXYXYXY */
8177 imm |= imm << 16;
8178 imm |= imm << 8;
8179 break;
8180 default: /* Rotated constant. */
8181 shift = (shift << 1) | (imm >> 7);
8182 imm |= 0x80;
8183 imm = imm << (32 - shift);
8184 shifter_out = 1;
8185 break;
8187 tmp2 = new_tmp();
8188 tcg_gen_movi_i32(tmp2, imm);
8189 rn = (insn >> 16) & 0xf;
8190 if (rn == 15) {
8191 tmp = new_tmp();
8192 tcg_gen_movi_i32(tmp, 0);
8193 } else {
8194 tmp = load_reg(s, rn);
8196 op = (insn >> 21) & 0xf;
8197 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8198 shifter_out, tmp, tmp2))
8199 goto illegal_op;
8200 dead_tmp(tmp2);
8201 rd = (insn >> 8) & 0xf;
8202 if (rd != 15) {
8203 store_reg(s, rd, tmp);
8204 } else {
8205 dead_tmp(tmp);
8209 break;
8210 case 12: /* Load/store single data item. */
8212 int postinc = 0;
8213 int writeback = 0;
8214 int user;
8215 if ((insn & 0x01100000) == 0x01000000) {
8216 if (disas_neon_ls_insn(env, s, insn))
8217 goto illegal_op;
8218 break;
8220 user = IS_USER(s);
8221 if (rn == 15) {
8222 addr = new_tmp();
8223 /* PC relative. */
8224 /* s->pc has already been incremented by 4. */
8225 imm = s->pc & 0xfffffffc;
8226 if (insn & (1 << 23))
8227 imm += insn & 0xfff;
8228 else
8229 imm -= insn & 0xfff;
8230 tcg_gen_movi_i32(addr, imm);
8231 } else {
8232 addr = load_reg(s, rn);
8233 if (insn & (1 << 23)) {
8234 /* Positive offset. */
8235 imm = insn & 0xfff;
8236 tcg_gen_addi_i32(addr, addr, imm);
8237 } else {
8238 op = (insn >> 8) & 7;
8239 imm = insn & 0xff;
8240 switch (op) {
8241 case 0: case 8: /* Shifted Register. */
8242 shift = (insn >> 4) & 0xf;
8243 if (shift > 3)
8244 goto illegal_op;
8245 tmp = load_reg(s, rm);
8246 if (shift)
8247 tcg_gen_shli_i32(tmp, tmp, shift);
8248 tcg_gen_add_i32(addr, addr, tmp);
8249 dead_tmp(tmp);
8250 break;
8251 case 4: /* Negative offset. */
8252 tcg_gen_addi_i32(addr, addr, -imm);
8253 break;
8254 case 6: /* User privilege. */
8255 tcg_gen_addi_i32(addr, addr, imm);
8256 user = 1;
8257 break;
8258 case 1: /* Post-decrement. */
8259 imm = -imm;
8260 /* Fall through. */
8261 case 3: /* Post-increment. */
8262 postinc = 1;
8263 writeback = 1;
8264 break;
8265 case 5: /* Pre-decrement. */
8266 imm = -imm;
8267 /* Fall through. */
8268 case 7: /* Pre-increment. */
8269 tcg_gen_addi_i32(addr, addr, imm);
8270 writeback = 1;
8271 break;
8272 default:
8273 goto illegal_op;
8277 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8278 if (insn & (1 << 20)) {
8279 /* Load. */
8280 if (rs == 15 && op != 2) {
8281 if (op & 2)
8282 goto illegal_op;
8283 /* Memory hint. Implemented as NOP. */
8284 } else {
8285 switch (op) {
8286 case 0: tmp = gen_ld8u(addr, user); break;
8287 case 4: tmp = gen_ld8s(addr, user); break;
8288 case 1: tmp = gen_ld16u(addr, user); break;
8289 case 5: tmp = gen_ld16s(addr, user); break;
8290 case 2: tmp = gen_ld32(addr, user); break;
8291 default: goto illegal_op;
8293 if (rs == 15) {
8294 gen_bx(s, tmp);
8295 } else {
8296 store_reg(s, rs, tmp);
8299 } else {
8300 /* Store. */
8301 if (rs == 15)
8302 goto illegal_op;
8303 tmp = load_reg(s, rs);
8304 switch (op) {
8305 case 0: gen_st8(tmp, addr, user); break;
8306 case 1: gen_st16(tmp, addr, user); break;
8307 case 2: gen_st32(tmp, addr, user); break;
8308 default: goto illegal_op;
8311 if (postinc)
8312 tcg_gen_addi_i32(addr, addr, imm);
8313 if (writeback) {
8314 store_reg(s, rn, addr);
8315 } else {
8316 dead_tmp(addr);
8319 break;
8320 default:
8321 goto illegal_op;
8323 return 0;
8324 illegal_op:
8325 return 1;
8328 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8330 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8331 int32_t offset;
8332 int i;
8333 TCGv tmp;
8334 TCGv tmp2;
8335 TCGv addr;
8337 if (s->condexec_mask) {
8338 cond = s->condexec_cond;
8339 s->condlabel = gen_new_label();
8340 gen_test_cc(cond ^ 1, s->condlabel);
8341 s->condjmp = 1;
8344 insn = lduw_code(s->pc);
8345 s->pc += 2;
8347 switch (insn >> 12) {
8348 case 0: case 1:
8350 rd = insn & 7;
8351 op = (insn >> 11) & 3;
8352 if (op == 3) {
8353 /* add/subtract */
8354 rn = (insn >> 3) & 7;
8355 tmp = load_reg(s, rn);
8356 if (insn & (1 << 10)) {
8357 /* immediate */
8358 tmp2 = new_tmp();
8359 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8360 } else {
8361 /* reg */
8362 rm = (insn >> 6) & 7;
8363 tmp2 = load_reg(s, rm);
8365 if (insn & (1 << 9)) {
8366 if (s->condexec_mask)
8367 tcg_gen_sub_i32(tmp, tmp, tmp2);
8368 else
8369 gen_helper_sub_cc(tmp, tmp, tmp2);
8370 } else {
8371 if (s->condexec_mask)
8372 tcg_gen_add_i32(tmp, tmp, tmp2);
8373 else
8374 gen_helper_add_cc(tmp, tmp, tmp2);
8376 dead_tmp(tmp2);
8377 store_reg(s, rd, tmp);
8378 } else {
8379 /* shift immediate */
8380 rm = (insn >> 3) & 7;
8381 shift = (insn >> 6) & 0x1f;
8382 tmp = load_reg(s, rm);
8383 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8384 if (!s->condexec_mask)
8385 gen_logic_CC(tmp);
8386 store_reg(s, rd, tmp);
8388 break;
8389 case 2: case 3:
8390 /* arithmetic large immediate */
8391 op = (insn >> 11) & 3;
8392 rd = (insn >> 8) & 0x7;
8393 if (op == 0) { /* mov */
8394 tmp = new_tmp();
8395 tcg_gen_movi_i32(tmp, insn & 0xff);
8396 if (!s->condexec_mask)
8397 gen_logic_CC(tmp);
8398 store_reg(s, rd, tmp);
8399 } else {
8400 tmp = load_reg(s, rd);
8401 tmp2 = new_tmp();
8402 tcg_gen_movi_i32(tmp2, insn & 0xff);
8403 switch (op) {
8404 case 1: /* cmp */
8405 gen_helper_sub_cc(tmp, tmp, tmp2);
8406 dead_tmp(tmp);
8407 dead_tmp(tmp2);
8408 break;
8409 case 2: /* add */
8410 if (s->condexec_mask)
8411 tcg_gen_add_i32(tmp, tmp, tmp2);
8412 else
8413 gen_helper_add_cc(tmp, tmp, tmp2);
8414 dead_tmp(tmp2);
8415 store_reg(s, rd, tmp);
8416 break;
8417 case 3: /* sub */
8418 if (s->condexec_mask)
8419 tcg_gen_sub_i32(tmp, tmp, tmp2);
8420 else
8421 gen_helper_sub_cc(tmp, tmp, tmp2);
8422 dead_tmp(tmp2);
8423 store_reg(s, rd, tmp);
8424 break;
8427 break;
8428 case 4:
8429 if (insn & (1 << 11)) {
8430 rd = (insn >> 8) & 7;
8431 /* load pc-relative. Bit 1 of PC is ignored. */
8432 val = s->pc + 2 + ((insn & 0xff) * 4);
8433 val &= ~(uint32_t)2;
8434 addr = new_tmp();
8435 tcg_gen_movi_i32(addr, val);
8436 tmp = gen_ld32(addr, IS_USER(s));
8437 dead_tmp(addr);
8438 store_reg(s, rd, tmp);
8439 break;
8441 if (insn & (1 << 10)) {
8442 /* data processing extended or blx */
8443 rd = (insn & 7) | ((insn >> 4) & 8);
8444 rm = (insn >> 3) & 0xf;
8445 op = (insn >> 8) & 3;
8446 switch (op) {
8447 case 0: /* add */
8448 tmp = load_reg(s, rd);
8449 tmp2 = load_reg(s, rm);
8450 tcg_gen_add_i32(tmp, tmp, tmp2);
8451 dead_tmp(tmp2);
8452 store_reg(s, rd, tmp);
8453 break;
8454 case 1: /* cmp */
8455 tmp = load_reg(s, rd);
8456 tmp2 = load_reg(s, rm);
8457 gen_helper_sub_cc(tmp, tmp, tmp2);
8458 dead_tmp(tmp2);
8459 dead_tmp(tmp);
8460 break;
8461 case 2: /* mov/cpy */
8462 tmp = load_reg(s, rm);
8463 store_reg(s, rd, tmp);
8464 break;
8465 case 3:/* branch [and link] exchange thumb register */
8466 tmp = load_reg(s, rm);
8467 if (insn & (1 << 7)) {
8468 val = (uint32_t)s->pc | 1;
8469 tmp2 = new_tmp();
8470 tcg_gen_movi_i32(tmp2, val);
8471 store_reg(s, 14, tmp2);
8473 gen_bx(s, tmp);
8474 break;
8476 break;
8479 /* data processing register */
8480 rd = insn & 7;
8481 rm = (insn >> 3) & 7;
8482 op = (insn >> 6) & 0xf;
8483 if (op == 2 || op == 3 || op == 4 || op == 7) {
8484 /* the shift/rotate ops want the operands backwards */
8485 val = rm;
8486 rm = rd;
8487 rd = val;
8488 val = 1;
8489 } else {
8490 val = 0;
8493 if (op == 9) { /* neg */
8494 tmp = new_tmp();
8495 tcg_gen_movi_i32(tmp, 0);
8496 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8497 tmp = load_reg(s, rd);
8498 } else {
8499 TCGV_UNUSED(tmp);
8502 tmp2 = load_reg(s, rm);
8503 switch (op) {
8504 case 0x0: /* and */
8505 tcg_gen_and_i32(tmp, tmp, tmp2);
8506 if (!s->condexec_mask)
8507 gen_logic_CC(tmp);
8508 break;
8509 case 0x1: /* eor */
8510 tcg_gen_xor_i32(tmp, tmp, tmp2);
8511 if (!s->condexec_mask)
8512 gen_logic_CC(tmp);
8513 break;
8514 case 0x2: /* lsl */
8515 if (s->condexec_mask) {
8516 gen_helper_shl(tmp2, tmp2, tmp);
8517 } else {
8518 gen_helper_shl_cc(tmp2, tmp2, tmp);
8519 gen_logic_CC(tmp2);
8521 break;
8522 case 0x3: /* lsr */
8523 if (s->condexec_mask) {
8524 gen_helper_shr(tmp2, tmp2, tmp);
8525 } else {
8526 gen_helper_shr_cc(tmp2, tmp2, tmp);
8527 gen_logic_CC(tmp2);
8529 break;
8530 case 0x4: /* asr */
8531 if (s->condexec_mask) {
8532 gen_helper_sar(tmp2, tmp2, tmp);
8533 } else {
8534 gen_helper_sar_cc(tmp2, tmp2, tmp);
8535 gen_logic_CC(tmp2);
8537 break;
8538 case 0x5: /* adc */
8539 if (s->condexec_mask)
8540 gen_adc(tmp, tmp2);
8541 else
8542 gen_helper_adc_cc(tmp, tmp, tmp2);
8543 break;
8544 case 0x6: /* sbc */
8545 if (s->condexec_mask)
8546 gen_sub_carry(tmp, tmp, tmp2);
8547 else
8548 gen_helper_sbc_cc(tmp, tmp, tmp2);
8549 break;
8550 case 0x7: /* ror */
8551 if (s->condexec_mask) {
8552 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8553 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8554 } else {
8555 gen_helper_ror_cc(tmp2, tmp2, tmp);
8556 gen_logic_CC(tmp2);
8558 break;
8559 case 0x8: /* tst */
8560 tcg_gen_and_i32(tmp, tmp, tmp2);
8561 gen_logic_CC(tmp);
8562 rd = 16;
8563 break;
8564 case 0x9: /* neg */
8565 if (s->condexec_mask)
8566 tcg_gen_neg_i32(tmp, tmp2);
8567 else
8568 gen_helper_sub_cc(tmp, tmp, tmp2);
8569 break;
8570 case 0xa: /* cmp */
8571 gen_helper_sub_cc(tmp, tmp, tmp2);
8572 rd = 16;
8573 break;
8574 case 0xb: /* cmn */
8575 gen_helper_add_cc(tmp, tmp, tmp2);
8576 rd = 16;
8577 break;
8578 case 0xc: /* orr */
8579 tcg_gen_or_i32(tmp, tmp, tmp2);
8580 if (!s->condexec_mask)
8581 gen_logic_CC(tmp);
8582 break;
8583 case 0xd: /* mul */
8584 tcg_gen_mul_i32(tmp, tmp, tmp2);
8585 if (!s->condexec_mask)
8586 gen_logic_CC(tmp);
8587 break;
8588 case 0xe: /* bic */
8589 tcg_gen_andc_i32(tmp, tmp, tmp2);
8590 if (!s->condexec_mask)
8591 gen_logic_CC(tmp);
8592 break;
8593 case 0xf: /* mvn */
8594 tcg_gen_not_i32(tmp2, tmp2);
8595 if (!s->condexec_mask)
8596 gen_logic_CC(tmp2);
8597 val = 1;
8598 rm = rd;
8599 break;
8601 if (rd != 16) {
8602 if (val) {
8603 store_reg(s, rm, tmp2);
8604 if (op != 0xf)
8605 dead_tmp(tmp);
8606 } else {
8607 store_reg(s, rd, tmp);
8608 dead_tmp(tmp2);
8610 } else {
8611 dead_tmp(tmp);
8612 dead_tmp(tmp2);
8614 break;
8616 case 5:
8617 /* load/store register offset. */
8618 rd = insn & 7;
8619 rn = (insn >> 3) & 7;
8620 rm = (insn >> 6) & 7;
8621 op = (insn >> 9) & 7;
8622 addr = load_reg(s, rn);
8623 tmp = load_reg(s, rm);
8624 tcg_gen_add_i32(addr, addr, tmp);
8625 dead_tmp(tmp);
8627 if (op < 3) /* store */
8628 tmp = load_reg(s, rd);
8630 switch (op) {
8631 case 0: /* str */
8632 gen_st32(tmp, addr, IS_USER(s));
8633 break;
8634 case 1: /* strh */
8635 gen_st16(tmp, addr, IS_USER(s));
8636 break;
8637 case 2: /* strb */
8638 gen_st8(tmp, addr, IS_USER(s));
8639 break;
8640 case 3: /* ldrsb */
8641 tmp = gen_ld8s(addr, IS_USER(s));
8642 break;
8643 case 4: /* ldr */
8644 tmp = gen_ld32(addr, IS_USER(s));
8645 break;
8646 case 5: /* ldrh */
8647 tmp = gen_ld16u(addr, IS_USER(s));
8648 break;
8649 case 6: /* ldrb */
8650 tmp = gen_ld8u(addr, IS_USER(s));
8651 break;
8652 case 7: /* ldrsh */
8653 tmp = gen_ld16s(addr, IS_USER(s));
8654 break;
8656 if (op >= 3) /* load */
8657 store_reg(s, rd, tmp);
8658 dead_tmp(addr);
8659 break;
8661 case 6:
8662 /* load/store word immediate offset */
8663 rd = insn & 7;
8664 rn = (insn >> 3) & 7;
8665 addr = load_reg(s, rn);
8666 val = (insn >> 4) & 0x7c;
8667 tcg_gen_addi_i32(addr, addr, val);
8669 if (insn & (1 << 11)) {
8670 /* load */
8671 tmp = gen_ld32(addr, IS_USER(s));
8672 store_reg(s, rd, tmp);
8673 } else {
8674 /* store */
8675 tmp = load_reg(s, rd);
8676 gen_st32(tmp, addr, IS_USER(s));
8678 dead_tmp(addr);
8679 break;
8681 case 7:
8682 /* load/store byte immediate offset */
8683 rd = insn & 7;
8684 rn = (insn >> 3) & 7;
8685 addr = load_reg(s, rn);
8686 val = (insn >> 6) & 0x1f;
8687 tcg_gen_addi_i32(addr, addr, val);
8689 if (insn & (1 << 11)) {
8690 /* load */
8691 tmp = gen_ld8u(addr, IS_USER(s));
8692 store_reg(s, rd, tmp);
8693 } else {
8694 /* store */
8695 tmp = load_reg(s, rd);
8696 gen_st8(tmp, addr, IS_USER(s));
8698 dead_tmp(addr);
8699 break;
8701 case 8:
8702 /* load/store halfword immediate offset */
8703 rd = insn & 7;
8704 rn = (insn >> 3) & 7;
8705 addr = load_reg(s, rn);
8706 val = (insn >> 5) & 0x3e;
8707 tcg_gen_addi_i32(addr, addr, val);
8709 if (insn & (1 << 11)) {
8710 /* load */
8711 tmp = gen_ld16u(addr, IS_USER(s));
8712 store_reg(s, rd, tmp);
8713 } else {
8714 /* store */
8715 tmp = load_reg(s, rd);
8716 gen_st16(tmp, addr, IS_USER(s));
8718 dead_tmp(addr);
8719 break;
8721 case 9:
8722 /* load/store from stack */
8723 rd = (insn >> 8) & 7;
8724 addr = load_reg(s, 13);
8725 val = (insn & 0xff) * 4;
8726 tcg_gen_addi_i32(addr, addr, val);
8728 if (insn & (1 << 11)) {
8729 /* load */
8730 tmp = gen_ld32(addr, IS_USER(s));
8731 store_reg(s, rd, tmp);
8732 } else {
8733 /* store */
8734 tmp = load_reg(s, rd);
8735 gen_st32(tmp, addr, IS_USER(s));
8737 dead_tmp(addr);
8738 break;
8740 case 10:
8741 /* add to high reg */
8742 rd = (insn >> 8) & 7;
8743 if (insn & (1 << 11)) {
8744 /* SP */
8745 tmp = load_reg(s, 13);
8746 } else {
8747 /* PC. bit 1 is ignored. */
8748 tmp = new_tmp();
8749 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8751 val = (insn & 0xff) * 4;
8752 tcg_gen_addi_i32(tmp, tmp, val);
8753 store_reg(s, rd, tmp);
8754 break;
8756 case 11:
8757 /* misc */
8758 op = (insn >> 8) & 0xf;
8759 switch (op) {
8760 case 0:
8761 /* adjust stack pointer */
8762 tmp = load_reg(s, 13);
8763 val = (insn & 0x7f) * 4;
8764 if (insn & (1 << 7))
8765 val = -(int32_t)val;
8766 tcg_gen_addi_i32(tmp, tmp, val);
8767 store_reg(s, 13, tmp);
8768 break;
8770 case 2: /* sign/zero extend. */
8771 ARCH(6);
8772 rd = insn & 7;
8773 rm = (insn >> 3) & 7;
8774 tmp = load_reg(s, rm);
8775 switch ((insn >> 6) & 3) {
8776 case 0: gen_sxth(tmp); break;
8777 case 1: gen_sxtb(tmp); break;
8778 case 2: gen_uxth(tmp); break;
8779 case 3: gen_uxtb(tmp); break;
8781 store_reg(s, rd, tmp);
8782 break;
8783 case 4: case 5: case 0xc: case 0xd:
8784 /* push/pop */
8785 addr = load_reg(s, 13);
8786 if (insn & (1 << 8))
8787 offset = 4;
8788 else
8789 offset = 0;
8790 for (i = 0; i < 8; i++) {
8791 if (insn & (1 << i))
8792 offset += 4;
8794 if ((insn & (1 << 11)) == 0) {
8795 tcg_gen_addi_i32(addr, addr, -offset);
8797 for (i = 0; i < 8; i++) {
8798 if (insn & (1 << i)) {
8799 if (insn & (1 << 11)) {
8800 /* pop */
8801 tmp = gen_ld32(addr, IS_USER(s));
8802 store_reg(s, i, tmp);
8803 } else {
8804 /* push */
8805 tmp = load_reg(s, i);
8806 gen_st32(tmp, addr, IS_USER(s));
8808 /* advance to the next address. */
8809 tcg_gen_addi_i32(addr, addr, 4);
8812 TCGV_UNUSED(tmp);
8813 if (insn & (1 << 8)) {
8814 if (insn & (1 << 11)) {
8815 /* pop pc */
8816 tmp = gen_ld32(addr, IS_USER(s));
8817 /* don't set the pc until the rest of the instruction
8818 has completed */
8819 } else {
8820 /* push lr */
8821 tmp = load_reg(s, 14);
8822 gen_st32(tmp, addr, IS_USER(s));
8824 tcg_gen_addi_i32(addr, addr, 4);
8826 if ((insn & (1 << 11)) == 0) {
8827 tcg_gen_addi_i32(addr, addr, -offset);
8829 /* write back the new stack pointer */
8830 store_reg(s, 13, addr);
8831 /* set the new PC value */
8832 if ((insn & 0x0900) == 0x0900)
8833 gen_bx(s, tmp);
8834 break;
8836 case 1: case 3: case 9: case 11: /* czb */
8837 rm = insn & 7;
8838 tmp = load_reg(s, rm);
8839 s->condlabel = gen_new_label();
8840 s->condjmp = 1;
8841 if (insn & (1 << 11))
8842 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8843 else
8844 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8845 dead_tmp(tmp);
8846 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8847 val = (uint32_t)s->pc + 2;
8848 val += offset;
8849 gen_jmp(s, val);
8850 break;
8852 case 15: /* IT, nop-hint. */
8853 if ((insn & 0xf) == 0) {
8854 gen_nop_hint(s, (insn >> 4) & 0xf);
8855 break;
8857 /* If Then. */
8858 s->condexec_cond = (insn >> 4) & 0xe;
8859 s->condexec_mask = insn & 0x1f;
8860 /* No actual code generated for this insn, just setup state. */
8861 break;
8863 case 0xe: /* bkpt */
8864 gen_set_condexec(s);
8865 gen_set_pc_im(s->pc - 2);
8866 gen_exception(EXCP_BKPT);
8867 s->is_jmp = DISAS_JUMP;
8868 break;
8870 case 0xa: /* rev */
8871 ARCH(6);
8872 rn = (insn >> 3) & 0x7;
8873 rd = insn & 0x7;
8874 tmp = load_reg(s, rn);
8875 switch ((insn >> 6) & 3) {
8876 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8877 case 1: gen_rev16(tmp); break;
8878 case 3: gen_revsh(tmp); break;
8879 default: goto illegal_op;
8881 store_reg(s, rd, tmp);
8882 break;
8884 case 6: /* cps */
8885 ARCH(6);
8886 if (IS_USER(s))
8887 break;
8888 if (IS_M(env)) {
8889 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8890 /* PRIMASK */
8891 if (insn & 1) {
8892 addr = tcg_const_i32(16);
8893 gen_helper_v7m_msr(cpu_env, addr, tmp);
8894 tcg_temp_free_i32(addr);
8896 /* FAULTMASK */
8897 if (insn & 2) {
8898 addr = tcg_const_i32(17);
8899 gen_helper_v7m_msr(cpu_env, addr, tmp);
8900 tcg_temp_free_i32(addr);
8902 tcg_temp_free_i32(tmp);
8903 gen_lookup_tb(s);
8904 } else {
8905 if (insn & (1 << 4))
8906 shift = CPSR_A | CPSR_I | CPSR_F;
8907 else
8908 shift = 0;
8909 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8911 break;
8913 default:
8914 goto undef;
8916 break;
8918 case 12:
8919 /* load/store multiple */
8920 rn = (insn >> 8) & 0x7;
8921 addr = load_reg(s, rn);
8922 for (i = 0; i < 8; i++) {
8923 if (insn & (1 << i)) {
8924 if (insn & (1 << 11)) {
8925 /* load */
8926 tmp = gen_ld32(addr, IS_USER(s));
8927 store_reg(s, i, tmp);
8928 } else {
8929 /* store */
8930 tmp = load_reg(s, i);
8931 gen_st32(tmp, addr, IS_USER(s));
8933 /* advance to the next address */
8934 tcg_gen_addi_i32(addr, addr, 4);
8937 /* Base register writeback. */
8938 if ((insn & (1 << rn)) == 0) {
8939 store_reg(s, rn, addr);
8940 } else {
8941 dead_tmp(addr);
8943 break;
8945 case 13:
8946 /* conditional branch or swi */
8947 cond = (insn >> 8) & 0xf;
8948 if (cond == 0xe)
8949 goto undef;
8951 if (cond == 0xf) {
8952 /* swi */
8953 gen_set_condexec(s);
8954 gen_set_pc_im(s->pc);
8955 s->is_jmp = DISAS_SWI;
8956 break;
8958 /* generate a conditional jump to next instruction */
8959 s->condlabel = gen_new_label();
8960 gen_test_cc(cond ^ 1, s->condlabel);
8961 s->condjmp = 1;
8963 /* jump to the offset */
8964 val = (uint32_t)s->pc + 2;
8965 offset = ((int32_t)insn << 24) >> 24;
8966 val += offset << 1;
8967 gen_jmp(s, val);
8968 break;
8970 case 14:
8971 if (insn & (1 << 11)) {
8972 if (disas_thumb2_insn(env, s, insn))
8973 goto undef32;
8974 break;
8976 /* unconditional branch */
8977 val = (uint32_t)s->pc;
8978 offset = ((int32_t)insn << 21) >> 21;
8979 val += (offset << 1) + 2;
8980 gen_jmp(s, val);
8981 break;
8983 case 15:
8984 if (disas_thumb2_insn(env, s, insn))
8985 goto undef32;
8986 break;
8988 return;
8989 undef32:
8990 gen_set_condexec(s);
8991 gen_set_pc_im(s->pc - 4);
8992 gen_exception(EXCP_UDEF);
8993 s->is_jmp = DISAS_JUMP;
8994 return;
8995 illegal_op:
8996 undef:
8997 gen_set_condexec(s);
8998 gen_set_pc_im(s->pc - 2);
8999 gen_exception(EXCP_UDEF);
9000 s->is_jmp = DISAS_JUMP;
9003 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9004 basic block 'tb'. If search_pc is TRUE, also generate PC
9005 information for each intermediate instruction. */
9006 static inline void gen_intermediate_code_internal(CPUState *env,
9007 TranslationBlock *tb,
9008 int search_pc)
9010 DisasContext dc1, *dc = &dc1;
9011 CPUBreakpoint *bp;
9012 uint16_t *gen_opc_end;
9013 int j, lj;
9014 target_ulong pc_start;
9015 uint32_t next_page_start;
9016 int num_insns;
9017 int max_insns;
9019 /* generate intermediate code */
9020 num_temps = 0;
9022 pc_start = tb->pc;
9024 dc->tb = tb;
9026 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9028 dc->is_jmp = DISAS_NEXT;
9029 dc->pc = pc_start;
9030 dc->singlestep_enabled = env->singlestep_enabled;
9031 dc->condjmp = 0;
9032 dc->thumb = env->thumb;
9033 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
9034 dc->condexec_cond = env->condexec_bits >> 4;
9035 #if !defined(CONFIG_USER_ONLY)
9036 if (IS_M(env)) {
9037 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
9038 } else {
9039 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
9041 #endif
9042 cpu_F0s = tcg_temp_new_i32();
9043 cpu_F1s = tcg_temp_new_i32();
9044 cpu_F0d = tcg_temp_new_i64();
9045 cpu_F1d = tcg_temp_new_i64();
9046 cpu_V0 = cpu_F0d;
9047 cpu_V1 = cpu_F1d;
9048 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9049 cpu_M0 = tcg_temp_new_i64();
9050 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9051 lj = -1;
9052 num_insns = 0;
9053 max_insns = tb->cflags & CF_COUNT_MASK;
9054 if (max_insns == 0)
9055 max_insns = CF_COUNT_MASK;
9057 gen_icount_start();
9058 /* Reset the conditional execution bits immediately. This avoids
9059 complications trying to do it at the end of the block. */
9060 if (env->condexec_bits)
9062 TCGv tmp = new_tmp();
9063 tcg_gen_movi_i32(tmp, 0);
9064 store_cpu_field(tmp, condexec_bits);
9066 do {
9067 #ifdef CONFIG_USER_ONLY
9068 /* Intercept jump to the magic kernel page. */
9069 if (dc->pc >= 0xffff0000) {
9070 /* We always get here via a jump, so know we are not in a
9071 conditional execution block. */
9072 gen_exception(EXCP_KERNEL_TRAP);
9073 dc->is_jmp = DISAS_UPDATE;
9074 break;
9076 #else
9077 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9078 /* We always get here via a jump, so know we are not in a
9079 conditional execution block. */
9080 gen_exception(EXCP_EXCEPTION_EXIT);
9081 dc->is_jmp = DISAS_UPDATE;
9082 break;
9084 #endif
9086 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9087 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9088 if (bp->pc == dc->pc) {
9089 gen_set_condexec(dc);
9090 gen_set_pc_im(dc->pc);
9091 gen_exception(EXCP_DEBUG);
9092 dc->is_jmp = DISAS_JUMP;
9093 /* Advance PC so that clearing the breakpoint will
9094 invalidate this TB. */
9095 dc->pc += 2;
9096 goto done_generating;
9097 break;
9101 if (search_pc) {
9102 j = gen_opc_ptr - gen_opc_buf;
9103 if (lj < j) {
9104 lj++;
9105 while (lj < j)
9106 gen_opc_instr_start[lj++] = 0;
9108 gen_opc_pc[lj] = dc->pc;
9109 gen_opc_instr_start[lj] = 1;
9110 gen_opc_icount[lj] = num_insns;
9113 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9114 gen_io_start();
9116 if (env->thumb) {
9117 disas_thumb_insn(env, dc);
9118 if (dc->condexec_mask) {
9119 dc->condexec_cond = (dc->condexec_cond & 0xe)
9120 | ((dc->condexec_mask >> 4) & 1);
9121 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9122 if (dc->condexec_mask == 0) {
9123 dc->condexec_cond = 0;
9126 } else {
9127 disas_arm_insn(env, dc);
9129 if (num_temps) {
9130 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
9131 num_temps = 0;
9134 if (dc->condjmp && !dc->is_jmp) {
9135 gen_set_label(dc->condlabel);
9136 dc->condjmp = 0;
9138 /* Translation stops when a conditional branch is encountered.
9139 * Otherwise the subsequent code could get translated several times.
9140 * Also stop translation when a page boundary is reached. This
9141 * ensures prefetch aborts occur at the right place. */
9142 num_insns ++;
9143 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9144 !env->singlestep_enabled &&
9145 !singlestep &&
9146 dc->pc < next_page_start &&
9147 num_insns < max_insns);
9149 if (tb->cflags & CF_LAST_IO) {
9150 if (dc->condjmp) {
9151 /* FIXME: This can theoretically happen with self-modifying
9152 code. */
9153 cpu_abort(env, "IO on conditional branch instruction");
9155 gen_io_end();
9158 /* At this stage dc->condjmp will only be set when the skipped
9159 instruction was a conditional branch or trap, and the PC has
9160 already been written. */
9161 if (unlikely(env->singlestep_enabled)) {
9162 /* Make sure the pc is updated, and raise a debug exception. */
9163 if (dc->condjmp) {
9164 gen_set_condexec(dc);
9165 if (dc->is_jmp == DISAS_SWI) {
9166 gen_exception(EXCP_SWI);
9167 } else {
9168 gen_exception(EXCP_DEBUG);
9170 gen_set_label(dc->condlabel);
9172 if (dc->condjmp || !dc->is_jmp) {
9173 gen_set_pc_im(dc->pc);
9174 dc->condjmp = 0;
9176 gen_set_condexec(dc);
9177 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9178 gen_exception(EXCP_SWI);
9179 } else {
9180 /* FIXME: Single stepping a WFI insn will not halt
9181 the CPU. */
9182 gen_exception(EXCP_DEBUG);
9184 } else {
9185 /* While branches must always occur at the end of an IT block,
9186 there are a few other things that can cause us to terminate
9187 the TB in the middel of an IT block:
9188 - Exception generating instructions (bkpt, swi, undefined).
9189 - Page boundaries.
9190 - Hardware watchpoints.
9191 Hardware breakpoints have already been handled and skip this code.
9193 gen_set_condexec(dc);
9194 switch(dc->is_jmp) {
9195 case DISAS_NEXT:
9196 gen_goto_tb(dc, 1, dc->pc);
9197 break;
9198 default:
9199 case DISAS_JUMP:
9200 case DISAS_UPDATE:
9201 /* indicate that the hash table must be used to find the next TB */
9202 tcg_gen_exit_tb(0);
9203 break;
9204 case DISAS_TB_JUMP:
9205 /* nothing more to generate */
9206 break;
9207 case DISAS_WFI:
9208 gen_helper_wfi();
9209 break;
9210 case DISAS_SWI:
9211 gen_exception(EXCP_SWI);
9212 break;
9214 if (dc->condjmp) {
9215 gen_set_label(dc->condlabel);
9216 gen_set_condexec(dc);
9217 gen_goto_tb(dc, 1, dc->pc);
9218 dc->condjmp = 0;
9222 done_generating:
9223 gen_icount_end(tb, num_insns);
9224 *gen_opc_ptr = INDEX_op_end;
9226 #ifdef DEBUG_DISAS
9227 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9228 qemu_log("----------------\n");
9229 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9230 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9231 qemu_log("\n");
9233 #endif
9234 if (search_pc) {
9235 j = gen_opc_ptr - gen_opc_buf;
9236 lj++;
9237 while (lj <= j)
9238 gen_opc_instr_start[lj++] = 0;
9239 } else {
9240 tb->size = dc->pc - pc_start;
9241 tb->icount = num_insns;
9245 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9247 gen_intermediate_code_internal(env, tb, 0);
9250 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9252 gen_intermediate_code_internal(env, tb, 1);
9255 static const char *cpu_mode_names[16] = {
9256 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9257 "???", "???", "???", "und", "???", "???", "???", "sys"
9260 void cpu_dump_state(CPUState *env, FILE *f,
9261 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9262 int flags)
9264 int i;
9265 #if 0
9266 union {
9267 uint32_t i;
9268 float s;
9269 } s0, s1;
9270 CPU_DoubleU d;
9271 /* ??? This assumes float64 and double have the same layout.
9272 Oh well, it's only debug dumps. */
9273 union {
9274 float64 f64;
9275 double d;
9276 } d0;
9277 #endif
9278 uint32_t psr;
9280 for(i=0;i<16;i++) {
9281 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9282 if ((i % 4) == 3)
9283 cpu_fprintf(f, "\n");
9284 else
9285 cpu_fprintf(f, " ");
9287 psr = cpsr_read(env);
9288 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9289 psr,
9290 psr & (1 << 31) ? 'N' : '-',
9291 psr & (1 << 30) ? 'Z' : '-',
9292 psr & (1 << 29) ? 'C' : '-',
9293 psr & (1 << 28) ? 'V' : '-',
9294 psr & CPSR_T ? 'T' : 'A',
9295 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9297 #if 0
9298 for (i = 0; i < 16; i++) {
9299 d.d = env->vfp.regs[i];
9300 s0.i = d.l.lower;
9301 s1.i = d.l.upper;
9302 d0.f64 = d.d;
9303 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9304 i * 2, (int)s0.i, s0.s,
9305 i * 2 + 1, (int)s1.i, s1.s,
9306 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9307 d0.d);
9309 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9310 #endif
9313 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9314 unsigned long searched_pc, int pc_pos, void *puc)
9316 env->regs[15] = gen_opc_pc[pc_pos];