eepro100: Use symbolic names and BIT macros in binary operations
[qemu.git] / target-arm / translate.c
blob9607aaeaa342483b5cbd7cfbf83d10349f1bac49
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 switch (op) {
2473 case 2:
2474 tmp = load_cpu_field(cp15.c13_tls1);
2475 break;
2476 case 3:
2477 tmp = load_cpu_field(cp15.c13_tls2);
2478 break;
2479 case 4:
2480 tmp = load_cpu_field(cp15.c13_tls3);
2481 break;
2482 default:
2483 return 0;
2485 store_reg(s, rd, tmp);
2487 } else {
2488 tmp = load_reg(s, rd);
2489 switch (op) {
2490 case 2:
2491 store_cpu_field(tmp, cp15.c13_tls1);
2492 break;
2493 case 3:
2494 store_cpu_field(tmp, cp15.c13_tls2);
2495 break;
2496 case 4:
2497 store_cpu_field(tmp, cp15.c13_tls3);
2498 break;
2499 default:
2500 dead_tmp(tmp);
2501 return 0;
2504 return 1;
2507 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2508 instruction is not defined. */
2509 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2511 uint32_t rd;
2512 TCGv tmp, tmp2;
2514 /* M profile cores use memory mapped registers instead of cp15. */
2515 if (arm_feature(env, ARM_FEATURE_M))
2516 return 1;
2518 if ((insn & (1 << 25)) == 0) {
2519 if (insn & (1 << 20)) {
2520 /* mrrc */
2521 return 1;
2523 /* mcrr. Used for block cache operations, so implement as no-op. */
2524 return 0;
2526 if ((insn & (1 << 4)) == 0) {
2527 /* cdp */
2528 return 1;
2530 if (IS_USER(s) && !cp15_user_ok(insn)) {
2531 return 1;
2533 if ((insn & 0x0fff0fff) == 0x0e070f90
2534 || (insn & 0x0fff0fff) == 0x0e070f58) {
2535 /* Wait for interrupt. */
2536 gen_set_pc_im(s->pc);
2537 s->is_jmp = DISAS_WFI;
2538 return 0;
2540 rd = (insn >> 12) & 0xf;
2542 if (cp15_tls_load_store(env, s, insn, rd))
2543 return 0;
2545 tmp2 = tcg_const_i32(insn);
2546 if (insn & ARM_CP_RW_BIT) {
2547 tmp = new_tmp();
2548 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2549 /* If the destination register is r15 then sets condition codes. */
2550 if (rd != 15)
2551 store_reg(s, rd, tmp);
2552 else
2553 dead_tmp(tmp);
2554 } else {
2555 tmp = load_reg(s, rd);
2556 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2557 dead_tmp(tmp);
2558 /* Normally we would always end the TB here, but Linux
2559 * arch/arm/mach-pxa/sleep.S expects two instructions following
2560 * an MMU enable to execute from cache. Imitate this behaviour. */
2561 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2562 (insn & 0x0fff0fff) != 0x0e010f10)
2563 gen_lookup_tb(s);
2565 tcg_temp_free_i32(tmp2);
2566 return 0;
2569 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2570 #define VFP_SREG(insn, bigbit, smallbit) \
2571 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2572 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2573 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2574 reg = (((insn) >> (bigbit)) & 0x0f) \
2575 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2576 } else { \
2577 if (insn & (1 << (smallbit))) \
2578 return 1; \
2579 reg = ((insn) >> (bigbit)) & 0x0f; \
2580 }} while (0)
2582 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2583 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2584 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2585 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2586 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2587 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2589 /* Move between integer and VFP cores. */
2590 static TCGv gen_vfp_mrs(void)
2592 TCGv tmp = new_tmp();
2593 tcg_gen_mov_i32(tmp, cpu_F0s);
2594 return tmp;
2597 static void gen_vfp_msr(TCGv tmp)
2599 tcg_gen_mov_i32(cpu_F0s, tmp);
2600 dead_tmp(tmp);
2603 static inline int
2604 vfp_enabled(CPUState * env)
2606 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2609 static void gen_neon_dup_u8(TCGv var, int shift)
2611 TCGv tmp = new_tmp();
2612 if (shift)
2613 tcg_gen_shri_i32(var, var, shift);
2614 tcg_gen_ext8u_i32(var, var);
2615 tcg_gen_shli_i32(tmp, var, 8);
2616 tcg_gen_or_i32(var, var, tmp);
2617 tcg_gen_shli_i32(tmp, var, 16);
2618 tcg_gen_or_i32(var, var, tmp);
2619 dead_tmp(tmp);
2622 static void gen_neon_dup_low16(TCGv var)
2624 TCGv tmp = new_tmp();
2625 tcg_gen_ext16u_i32(var, var);
2626 tcg_gen_shli_i32(tmp, var, 16);
2627 tcg_gen_or_i32(var, var, tmp);
2628 dead_tmp(tmp);
2631 static void gen_neon_dup_high16(TCGv var)
2633 TCGv tmp = new_tmp();
2634 tcg_gen_andi_i32(var, var, 0xffff0000);
2635 tcg_gen_shri_i32(tmp, var, 16);
2636 tcg_gen_or_i32(var, var, tmp);
2637 dead_tmp(tmp);
2640 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2641 (ie. an undefined instruction). */
2642 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2644 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2645 int dp, veclen;
2646 TCGv addr;
2647 TCGv tmp;
2648 TCGv tmp2;
2650 if (!arm_feature(env, ARM_FEATURE_VFP))
2651 return 1;
2653 if (!vfp_enabled(env)) {
2654 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2655 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2656 return 1;
2657 rn = (insn >> 16) & 0xf;
2658 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2659 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2660 return 1;
2662 dp = ((insn & 0xf00) == 0xb00);
2663 switch ((insn >> 24) & 0xf) {
2664 case 0xe:
2665 if (insn & (1 << 4)) {
2666 /* single register transfer */
2667 rd = (insn >> 12) & 0xf;
2668 if (dp) {
2669 int size;
2670 int pass;
2672 VFP_DREG_N(rn, insn);
2673 if (insn & 0xf)
2674 return 1;
2675 if (insn & 0x00c00060
2676 && !arm_feature(env, ARM_FEATURE_NEON))
2677 return 1;
2679 pass = (insn >> 21) & 1;
2680 if (insn & (1 << 22)) {
2681 size = 0;
2682 offset = ((insn >> 5) & 3) * 8;
2683 } else if (insn & (1 << 5)) {
2684 size = 1;
2685 offset = (insn & (1 << 6)) ? 16 : 0;
2686 } else {
2687 size = 2;
2688 offset = 0;
2690 if (insn & ARM_CP_RW_BIT) {
2691 /* vfp->arm */
2692 tmp = neon_load_reg(rn, pass);
2693 switch (size) {
2694 case 0:
2695 if (offset)
2696 tcg_gen_shri_i32(tmp, tmp, offset);
2697 if (insn & (1 << 23))
2698 gen_uxtb(tmp);
2699 else
2700 gen_sxtb(tmp);
2701 break;
2702 case 1:
2703 if (insn & (1 << 23)) {
2704 if (offset) {
2705 tcg_gen_shri_i32(tmp, tmp, 16);
2706 } else {
2707 gen_uxth(tmp);
2709 } else {
2710 if (offset) {
2711 tcg_gen_sari_i32(tmp, tmp, 16);
2712 } else {
2713 gen_sxth(tmp);
2716 break;
2717 case 2:
2718 break;
2720 store_reg(s, rd, tmp);
2721 } else {
2722 /* arm->vfp */
2723 tmp = load_reg(s, rd);
2724 if (insn & (1 << 23)) {
2725 /* VDUP */
2726 if (size == 0) {
2727 gen_neon_dup_u8(tmp, 0);
2728 } else if (size == 1) {
2729 gen_neon_dup_low16(tmp);
2731 for (n = 0; n <= pass * 2; n++) {
2732 tmp2 = new_tmp();
2733 tcg_gen_mov_i32(tmp2, tmp);
2734 neon_store_reg(rn, n, tmp2);
2736 neon_store_reg(rn, n, tmp);
2737 } else {
2738 /* VMOV */
2739 switch (size) {
2740 case 0:
2741 tmp2 = neon_load_reg(rn, pass);
2742 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2743 dead_tmp(tmp2);
2744 break;
2745 case 1:
2746 tmp2 = neon_load_reg(rn, pass);
2747 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2748 dead_tmp(tmp2);
2749 break;
2750 case 2:
2751 break;
2753 neon_store_reg(rn, pass, tmp);
2756 } else { /* !dp */
2757 if ((insn & 0x6f) != 0x00)
2758 return 1;
2759 rn = VFP_SREG_N(insn);
2760 if (insn & ARM_CP_RW_BIT) {
2761 /* vfp->arm */
2762 if (insn & (1 << 21)) {
2763 /* system register */
2764 rn >>= 1;
2766 switch (rn) {
2767 case ARM_VFP_FPSID:
2768 /* VFP2 allows access to FSID from userspace.
2769 VFP3 restricts all id registers to privileged
2770 accesses. */
2771 if (IS_USER(s)
2772 && arm_feature(env, ARM_FEATURE_VFP3))
2773 return 1;
2774 tmp = load_cpu_field(vfp.xregs[rn]);
2775 break;
2776 case ARM_VFP_FPEXC:
2777 if (IS_USER(s))
2778 return 1;
2779 tmp = load_cpu_field(vfp.xregs[rn]);
2780 break;
2781 case ARM_VFP_FPINST:
2782 case ARM_VFP_FPINST2:
2783 /* Not present in VFP3. */
2784 if (IS_USER(s)
2785 || arm_feature(env, ARM_FEATURE_VFP3))
2786 return 1;
2787 tmp = load_cpu_field(vfp.xregs[rn]);
2788 break;
2789 case ARM_VFP_FPSCR:
2790 if (rd == 15) {
2791 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2792 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2793 } else {
2794 tmp = new_tmp();
2795 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2797 break;
2798 case ARM_VFP_MVFR0:
2799 case ARM_VFP_MVFR1:
2800 if (IS_USER(s)
2801 || !arm_feature(env, ARM_FEATURE_VFP3))
2802 return 1;
2803 tmp = load_cpu_field(vfp.xregs[rn]);
2804 break;
2805 default:
2806 return 1;
2808 } else {
2809 gen_mov_F0_vreg(0, rn);
2810 tmp = gen_vfp_mrs();
2812 if (rd == 15) {
2813 /* Set the 4 flag bits in the CPSR. */
2814 gen_set_nzcv(tmp);
2815 dead_tmp(tmp);
2816 } else {
2817 store_reg(s, rd, tmp);
2819 } else {
2820 /* arm->vfp */
2821 tmp = load_reg(s, rd);
2822 if (insn & (1 << 21)) {
2823 rn >>= 1;
2824 /* system register */
2825 switch (rn) {
2826 case ARM_VFP_FPSID:
2827 case ARM_VFP_MVFR0:
2828 case ARM_VFP_MVFR1:
2829 /* Writes are ignored. */
2830 break;
2831 case ARM_VFP_FPSCR:
2832 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2833 dead_tmp(tmp);
2834 gen_lookup_tb(s);
2835 break;
2836 case ARM_VFP_FPEXC:
2837 if (IS_USER(s))
2838 return 1;
2839 /* TODO: VFP subarchitecture support.
2840 * For now, keep the EN bit only */
2841 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2842 store_cpu_field(tmp, vfp.xregs[rn]);
2843 gen_lookup_tb(s);
2844 break;
2845 case ARM_VFP_FPINST:
2846 case ARM_VFP_FPINST2:
2847 store_cpu_field(tmp, vfp.xregs[rn]);
2848 break;
2849 default:
2850 return 1;
2852 } else {
2853 gen_vfp_msr(tmp);
2854 gen_mov_vreg_F0(0, rn);
2858 } else {
2859 /* data processing */
2860 /* The opcode is in bits 23, 21, 20 and 6. */
2861 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2862 if (dp) {
2863 if (op == 15) {
2864 /* rn is opcode */
2865 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2866 } else {
2867 /* rn is register number */
2868 VFP_DREG_N(rn, insn);
2871 if (op == 15 && (rn == 15 || rn > 17)) {
2872 /* Integer or single precision destination. */
2873 rd = VFP_SREG_D(insn);
2874 } else {
2875 VFP_DREG_D(rd, insn);
2878 if (op == 15 && (rn == 16 || rn == 17)) {
2879 /* Integer source. */
2880 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2881 } else {
2882 VFP_DREG_M(rm, insn);
2884 } else {
2885 rn = VFP_SREG_N(insn);
2886 if (op == 15 && rn == 15) {
2887 /* Double precision destination. */
2888 VFP_DREG_D(rd, insn);
2889 } else {
2890 rd = VFP_SREG_D(insn);
2892 rm = VFP_SREG_M(insn);
2895 veclen = env->vfp.vec_len;
2896 if (op == 15 && rn > 3)
2897 veclen = 0;
2899 /* Shut up compiler warnings. */
2900 delta_m = 0;
2901 delta_d = 0;
2902 bank_mask = 0;
2904 if (veclen > 0) {
2905 if (dp)
2906 bank_mask = 0xc;
2907 else
2908 bank_mask = 0x18;
2910 /* Figure out what type of vector operation this is. */
2911 if ((rd & bank_mask) == 0) {
2912 /* scalar */
2913 veclen = 0;
2914 } else {
2915 if (dp)
2916 delta_d = (env->vfp.vec_stride >> 1) + 1;
2917 else
2918 delta_d = env->vfp.vec_stride + 1;
2920 if ((rm & bank_mask) == 0) {
2921 /* mixed scalar/vector */
2922 delta_m = 0;
2923 } else {
2924 /* vector */
2925 delta_m = delta_d;
2930 /* Load the initial operands. */
2931 if (op == 15) {
2932 switch (rn) {
2933 case 16:
2934 case 17:
2935 /* Integer source */
2936 gen_mov_F0_vreg(0, rm);
2937 break;
2938 case 8:
2939 case 9:
2940 /* Compare */
2941 gen_mov_F0_vreg(dp, rd);
2942 gen_mov_F1_vreg(dp, rm);
2943 break;
2944 case 10:
2945 case 11:
2946 /* Compare with zero */
2947 gen_mov_F0_vreg(dp, rd);
2948 gen_vfp_F1_ld0(dp);
2949 break;
2950 case 20:
2951 case 21:
2952 case 22:
2953 case 23:
2954 case 28:
2955 case 29:
2956 case 30:
2957 case 31:
2958 /* Source and destination the same. */
2959 gen_mov_F0_vreg(dp, rd);
2960 break;
2961 default:
2962 /* One source operand. */
2963 gen_mov_F0_vreg(dp, rm);
2964 break;
2966 } else {
2967 /* Two source operands. */
2968 gen_mov_F0_vreg(dp, rn);
2969 gen_mov_F1_vreg(dp, rm);
2972 for (;;) {
2973 /* Perform the calculation. */
2974 switch (op) {
2975 case 0: /* mac: fd + (fn * fm) */
2976 gen_vfp_mul(dp);
2977 gen_mov_F1_vreg(dp, rd);
2978 gen_vfp_add(dp);
2979 break;
2980 case 1: /* nmac: fd - (fn * fm) */
2981 gen_vfp_mul(dp);
2982 gen_vfp_neg(dp);
2983 gen_mov_F1_vreg(dp, rd);
2984 gen_vfp_add(dp);
2985 break;
2986 case 2: /* msc: -fd + (fn * fm) */
2987 gen_vfp_mul(dp);
2988 gen_mov_F1_vreg(dp, rd);
2989 gen_vfp_sub(dp);
2990 break;
2991 case 3: /* nmsc: -fd - (fn * fm) */
2992 gen_vfp_mul(dp);
2993 gen_vfp_neg(dp);
2994 gen_mov_F1_vreg(dp, rd);
2995 gen_vfp_sub(dp);
2996 break;
2997 case 4: /* mul: fn * fm */
2998 gen_vfp_mul(dp);
2999 break;
3000 case 5: /* nmul: -(fn * fm) */
3001 gen_vfp_mul(dp);
3002 gen_vfp_neg(dp);
3003 break;
3004 case 6: /* add: fn + fm */
3005 gen_vfp_add(dp);
3006 break;
3007 case 7: /* sub: fn - fm */
3008 gen_vfp_sub(dp);
3009 break;
3010 case 8: /* div: fn / fm */
3011 gen_vfp_div(dp);
3012 break;
3013 case 14: /* fconst */
3014 if (!arm_feature(env, ARM_FEATURE_VFP3))
3015 return 1;
3017 n = (insn << 12) & 0x80000000;
3018 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3019 if (dp) {
3020 if (i & 0x40)
3021 i |= 0x3f80;
3022 else
3023 i |= 0x4000;
3024 n |= i << 16;
3025 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3026 } else {
3027 if (i & 0x40)
3028 i |= 0x780;
3029 else
3030 i |= 0x800;
3031 n |= i << 19;
3032 tcg_gen_movi_i32(cpu_F0s, n);
3034 break;
3035 case 15: /* extension space */
3036 switch (rn) {
3037 case 0: /* cpy */
3038 /* no-op */
3039 break;
3040 case 1: /* abs */
3041 gen_vfp_abs(dp);
3042 break;
3043 case 2: /* neg */
3044 gen_vfp_neg(dp);
3045 break;
3046 case 3: /* sqrt */
3047 gen_vfp_sqrt(dp);
3048 break;
3049 case 4: /* vcvtb.f32.f16 */
3050 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3051 return 1;
3052 tmp = gen_vfp_mrs();
3053 tcg_gen_ext16u_i32(tmp, tmp);
3054 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3055 dead_tmp(tmp);
3056 break;
3057 case 5: /* vcvtt.f32.f16 */
3058 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3059 return 1;
3060 tmp = gen_vfp_mrs();
3061 tcg_gen_shri_i32(tmp, tmp, 16);
3062 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3063 dead_tmp(tmp);
3064 break;
3065 case 6: /* vcvtb.f16.f32 */
3066 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3067 return 1;
3068 tmp = new_tmp();
3069 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3070 gen_mov_F0_vreg(0, rd);
3071 tmp2 = gen_vfp_mrs();
3072 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3073 tcg_gen_or_i32(tmp, tmp, tmp2);
3074 dead_tmp(tmp2);
3075 gen_vfp_msr(tmp);
3076 break;
3077 case 7: /* vcvtt.f16.f32 */
3078 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3079 return 1;
3080 tmp = new_tmp();
3081 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3082 tcg_gen_shli_i32(tmp, tmp, 16);
3083 gen_mov_F0_vreg(0, rd);
3084 tmp2 = gen_vfp_mrs();
3085 tcg_gen_ext16u_i32(tmp2, tmp2);
3086 tcg_gen_or_i32(tmp, tmp, tmp2);
3087 dead_tmp(tmp2);
3088 gen_vfp_msr(tmp);
3089 break;
3090 case 8: /* cmp */
3091 gen_vfp_cmp(dp);
3092 break;
3093 case 9: /* cmpe */
3094 gen_vfp_cmpe(dp);
3095 break;
3096 case 10: /* cmpz */
3097 gen_vfp_cmp(dp);
3098 break;
3099 case 11: /* cmpez */
3100 gen_vfp_F1_ld0(dp);
3101 gen_vfp_cmpe(dp);
3102 break;
3103 case 15: /* single<->double conversion */
3104 if (dp)
3105 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3106 else
3107 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3108 break;
3109 case 16: /* fuito */
3110 gen_vfp_uito(dp);
3111 break;
3112 case 17: /* fsito */
3113 gen_vfp_sito(dp);
3114 break;
3115 case 20: /* fshto */
3116 if (!arm_feature(env, ARM_FEATURE_VFP3))
3117 return 1;
3118 gen_vfp_shto(dp, 16 - rm);
3119 break;
3120 case 21: /* fslto */
3121 if (!arm_feature(env, ARM_FEATURE_VFP3))
3122 return 1;
3123 gen_vfp_slto(dp, 32 - rm);
3124 break;
3125 case 22: /* fuhto */
3126 if (!arm_feature(env, ARM_FEATURE_VFP3))
3127 return 1;
3128 gen_vfp_uhto(dp, 16 - rm);
3129 break;
3130 case 23: /* fulto */
3131 if (!arm_feature(env, ARM_FEATURE_VFP3))
3132 return 1;
3133 gen_vfp_ulto(dp, 32 - rm);
3134 break;
3135 case 24: /* ftoui */
3136 gen_vfp_toui(dp);
3137 break;
3138 case 25: /* ftouiz */
3139 gen_vfp_touiz(dp);
3140 break;
3141 case 26: /* ftosi */
3142 gen_vfp_tosi(dp);
3143 break;
3144 case 27: /* ftosiz */
3145 gen_vfp_tosiz(dp);
3146 break;
3147 case 28: /* ftosh */
3148 if (!arm_feature(env, ARM_FEATURE_VFP3))
3149 return 1;
3150 gen_vfp_tosh(dp, 16 - rm);
3151 break;
3152 case 29: /* ftosl */
3153 if (!arm_feature(env, ARM_FEATURE_VFP3))
3154 return 1;
3155 gen_vfp_tosl(dp, 32 - rm);
3156 break;
3157 case 30: /* ftouh */
3158 if (!arm_feature(env, ARM_FEATURE_VFP3))
3159 return 1;
3160 gen_vfp_touh(dp, 16 - rm);
3161 break;
3162 case 31: /* ftoul */
3163 if (!arm_feature(env, ARM_FEATURE_VFP3))
3164 return 1;
3165 gen_vfp_toul(dp, 32 - rm);
3166 break;
3167 default: /* undefined */
3168 printf ("rn:%d\n", rn);
3169 return 1;
3171 break;
3172 default: /* undefined */
3173 printf ("op:%d\n", op);
3174 return 1;
3177 /* Write back the result. */
3178 if (op == 15 && (rn >= 8 && rn <= 11))
3179 ; /* Comparison, do nothing. */
3180 else if (op == 15 && rn > 17)
3181 /* Integer result. */
3182 gen_mov_vreg_F0(0, rd);
3183 else if (op == 15 && rn == 15)
3184 /* conversion */
3185 gen_mov_vreg_F0(!dp, rd);
3186 else
3187 gen_mov_vreg_F0(dp, rd);
3189 /* break out of the loop if we have finished */
3190 if (veclen == 0)
3191 break;
3193 if (op == 15 && delta_m == 0) {
3194 /* single source one-many */
3195 while (veclen--) {
3196 rd = ((rd + delta_d) & (bank_mask - 1))
3197 | (rd & bank_mask);
3198 gen_mov_vreg_F0(dp, rd);
3200 break;
3202 /* Setup the next operands. */
3203 veclen--;
3204 rd = ((rd + delta_d) & (bank_mask - 1))
3205 | (rd & bank_mask);
3207 if (op == 15) {
3208 /* One source operand. */
3209 rm = ((rm + delta_m) & (bank_mask - 1))
3210 | (rm & bank_mask);
3211 gen_mov_F0_vreg(dp, rm);
3212 } else {
3213 /* Two source operands. */
3214 rn = ((rn + delta_d) & (bank_mask - 1))
3215 | (rn & bank_mask);
3216 gen_mov_F0_vreg(dp, rn);
3217 if (delta_m) {
3218 rm = ((rm + delta_m) & (bank_mask - 1))
3219 | (rm & bank_mask);
3220 gen_mov_F1_vreg(dp, rm);
3225 break;
3226 case 0xc:
3227 case 0xd:
3228 if (dp && (insn & 0x03e00000) == 0x00400000) {
3229 /* two-register transfer */
3230 rn = (insn >> 16) & 0xf;
3231 rd = (insn >> 12) & 0xf;
3232 if (dp) {
3233 VFP_DREG_M(rm, insn);
3234 } else {
3235 rm = VFP_SREG_M(insn);
3238 if (insn & ARM_CP_RW_BIT) {
3239 /* vfp->arm */
3240 if (dp) {
3241 gen_mov_F0_vreg(0, rm * 2);
3242 tmp = gen_vfp_mrs();
3243 store_reg(s, rd, tmp);
3244 gen_mov_F0_vreg(0, rm * 2 + 1);
3245 tmp = gen_vfp_mrs();
3246 store_reg(s, rn, tmp);
3247 } else {
3248 gen_mov_F0_vreg(0, rm);
3249 tmp = gen_vfp_mrs();
3250 store_reg(s, rn, tmp);
3251 gen_mov_F0_vreg(0, rm + 1);
3252 tmp = gen_vfp_mrs();
3253 store_reg(s, rd, tmp);
3255 } else {
3256 /* arm->vfp */
3257 if (dp) {
3258 tmp = load_reg(s, rd);
3259 gen_vfp_msr(tmp);
3260 gen_mov_vreg_F0(0, rm * 2);
3261 tmp = load_reg(s, rn);
3262 gen_vfp_msr(tmp);
3263 gen_mov_vreg_F0(0, rm * 2 + 1);
3264 } else {
3265 tmp = load_reg(s, rn);
3266 gen_vfp_msr(tmp);
3267 gen_mov_vreg_F0(0, rm);
3268 tmp = load_reg(s, rd);
3269 gen_vfp_msr(tmp);
3270 gen_mov_vreg_F0(0, rm + 1);
3273 } else {
3274 /* Load/store */
3275 rn = (insn >> 16) & 0xf;
3276 if (dp)
3277 VFP_DREG_D(rd, insn);
3278 else
3279 rd = VFP_SREG_D(insn);
3280 if (s->thumb && rn == 15) {
3281 addr = new_tmp();
3282 tcg_gen_movi_i32(addr, s->pc & ~2);
3283 } else {
3284 addr = load_reg(s, rn);
3286 if ((insn & 0x01200000) == 0x01000000) {
3287 /* Single load/store */
3288 offset = (insn & 0xff) << 2;
3289 if ((insn & (1 << 23)) == 0)
3290 offset = -offset;
3291 tcg_gen_addi_i32(addr, addr, offset);
3292 if (insn & (1 << 20)) {
3293 gen_vfp_ld(s, dp, addr);
3294 gen_mov_vreg_F0(dp, rd);
3295 } else {
3296 gen_mov_F0_vreg(dp, rd);
3297 gen_vfp_st(s, dp, addr);
3299 dead_tmp(addr);
3300 } else {
3301 /* load/store multiple */
3302 if (dp)
3303 n = (insn >> 1) & 0x7f;
3304 else
3305 n = insn & 0xff;
3307 if (insn & (1 << 24)) /* pre-decrement */
3308 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3310 if (dp)
3311 offset = 8;
3312 else
3313 offset = 4;
3314 for (i = 0; i < n; i++) {
3315 if (insn & ARM_CP_RW_BIT) {
3316 /* load */
3317 gen_vfp_ld(s, dp, addr);
3318 gen_mov_vreg_F0(dp, rd + i);
3319 } else {
3320 /* store */
3321 gen_mov_F0_vreg(dp, rd + i);
3322 gen_vfp_st(s, dp, addr);
3324 tcg_gen_addi_i32(addr, addr, offset);
3326 if (insn & (1 << 21)) {
3327 /* writeback */
3328 if (insn & (1 << 24))
3329 offset = -offset * n;
3330 else if (dp && (insn & 1))
3331 offset = 4;
3332 else
3333 offset = 0;
3335 if (offset != 0)
3336 tcg_gen_addi_i32(addr, addr, offset);
3337 store_reg(s, rn, addr);
3338 } else {
3339 dead_tmp(addr);
3343 break;
3344 default:
3345 /* Should never happen. */
3346 return 1;
3348 return 0;
3351 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3353 TranslationBlock *tb;
3355 tb = s->tb;
3356 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3357 tcg_gen_goto_tb(n);
3358 gen_set_pc_im(dest);
3359 tcg_gen_exit_tb((long)tb + n);
3360 } else {
3361 gen_set_pc_im(dest);
3362 tcg_gen_exit_tb(0);
3366 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3368 if (unlikely(s->singlestep_enabled)) {
3369 /* An indirect jump so that we still trigger the debug exception. */
3370 if (s->thumb)
3371 dest |= 1;
3372 gen_bx_im(s, dest);
3373 } else {
3374 gen_goto_tb(s, 0, dest);
3375 s->is_jmp = DISAS_TB_JUMP;
3379 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3381 if (x)
3382 tcg_gen_sari_i32(t0, t0, 16);
3383 else
3384 gen_sxth(t0);
3385 if (y)
3386 tcg_gen_sari_i32(t1, t1, 16);
3387 else
3388 gen_sxth(t1);
3389 tcg_gen_mul_i32(t0, t0, t1);
3392 /* Return the mask of PSR bits set by a MSR instruction. */
3393 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3394 uint32_t mask;
3396 mask = 0;
3397 if (flags & (1 << 0))
3398 mask |= 0xff;
3399 if (flags & (1 << 1))
3400 mask |= 0xff00;
3401 if (flags & (1 << 2))
3402 mask |= 0xff0000;
3403 if (flags & (1 << 3))
3404 mask |= 0xff000000;
3406 /* Mask out undefined bits. */
3407 mask &= ~CPSR_RESERVED;
3408 if (!arm_feature(env, ARM_FEATURE_V6))
3409 mask &= ~(CPSR_E | CPSR_GE);
3410 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3411 mask &= ~CPSR_IT;
3412 /* Mask out execution state bits. */
3413 if (!spsr)
3414 mask &= ~CPSR_EXEC;
3415 /* Mask out privileged bits. */
3416 if (IS_USER(s))
3417 mask &= CPSR_USER;
3418 return mask;
3421 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3422 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3424 TCGv tmp;
3425 if (spsr) {
3426 /* ??? This is also undefined in system mode. */
3427 if (IS_USER(s))
3428 return 1;
3430 tmp = load_cpu_field(spsr);
3431 tcg_gen_andi_i32(tmp, tmp, ~mask);
3432 tcg_gen_andi_i32(t0, t0, mask);
3433 tcg_gen_or_i32(tmp, tmp, t0);
3434 store_cpu_field(tmp, spsr);
3435 } else {
3436 gen_set_cpsr(t0, mask);
3438 dead_tmp(t0);
3439 gen_lookup_tb(s);
3440 return 0;
3443 /* Returns nonzero if access to the PSR is not permitted. */
3444 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3446 TCGv tmp;
3447 tmp = new_tmp();
3448 tcg_gen_movi_i32(tmp, val);
3449 return gen_set_psr(s, mask, spsr, tmp);
3452 /* Generate an old-style exception return. Marks pc as dead. */
3453 static void gen_exception_return(DisasContext *s, TCGv pc)
3455 TCGv tmp;
3456 store_reg(s, 15, pc);
3457 tmp = load_cpu_field(spsr);
3458 gen_set_cpsr(tmp, 0xffffffff);
3459 dead_tmp(tmp);
3460 s->is_jmp = DISAS_UPDATE;
3463 /* Generate a v6 exception return. Marks both values as dead. */
3464 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3466 gen_set_cpsr(cpsr, 0xffffffff);
3467 dead_tmp(cpsr);
3468 store_reg(s, 15, pc);
3469 s->is_jmp = DISAS_UPDATE;
3472 static inline void
3473 gen_set_condexec (DisasContext *s)
3475 if (s->condexec_mask) {
3476 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3477 TCGv tmp = new_tmp();
3478 tcg_gen_movi_i32(tmp, val);
3479 store_cpu_field(tmp, condexec_bits);
3483 static void gen_nop_hint(DisasContext *s, int val)
3485 switch (val) {
3486 case 3: /* wfi */
3487 gen_set_pc_im(s->pc);
3488 s->is_jmp = DISAS_WFI;
3489 break;
3490 case 2: /* wfe */
3491 case 4: /* sev */
3492 /* TODO: Implement SEV and WFE. May help SMP performance. */
3493 default: /* nop */
3494 break;
3498 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3500 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3502 switch (size) {
3503 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3504 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3505 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3506 default: return 1;
3508 return 0;
3511 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3513 switch (size) {
3514 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3515 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3516 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3517 default: return;
3521 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3522 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3523 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3524 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3525 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3527 /* FIXME: This is wrong. They set the wrong overflow bit. */
3528 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3529 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3530 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3531 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3533 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3534 switch ((size << 1) | u) { \
3535 case 0: \
3536 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3537 break; \
3538 case 1: \
3539 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3540 break; \
3541 case 2: \
3542 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3543 break; \
3544 case 3: \
3545 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3546 break; \
3547 case 4: \
3548 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3549 break; \
3550 case 5: \
3551 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3552 break; \
3553 default: return 1; \
3554 }} while (0)
3556 #define GEN_NEON_INTEGER_OP(name) do { \
3557 switch ((size << 1) | u) { \
3558 case 0: \
3559 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3560 break; \
3561 case 1: \
3562 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3563 break; \
3564 case 2: \
3565 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3566 break; \
3567 case 3: \
3568 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3569 break; \
3570 case 4: \
3571 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3572 break; \
3573 case 5: \
3574 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3575 break; \
3576 default: return 1; \
3577 }} while (0)
3579 static TCGv neon_load_scratch(int scratch)
3581 TCGv tmp = new_tmp();
3582 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3583 return tmp;
3586 static void neon_store_scratch(int scratch, TCGv var)
3588 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3589 dead_tmp(var);
3592 static inline TCGv neon_get_scalar(int size, int reg)
3594 TCGv tmp;
3595 if (size == 1) {
3596 tmp = neon_load_reg(reg >> 1, reg & 1);
3597 } else {
3598 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3599 if (reg & 1) {
3600 gen_neon_dup_low16(tmp);
3601 } else {
3602 gen_neon_dup_high16(tmp);
3605 return tmp;
3608 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3610 TCGv rd, rm, tmp;
3612 rd = new_tmp();
3613 rm = new_tmp();
3614 tmp = new_tmp();
3616 tcg_gen_andi_i32(rd, t0, 0xff);
3617 tcg_gen_shri_i32(tmp, t0, 8);
3618 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3619 tcg_gen_or_i32(rd, rd, tmp);
3620 tcg_gen_shli_i32(tmp, t1, 16);
3621 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3622 tcg_gen_or_i32(rd, rd, tmp);
3623 tcg_gen_shli_i32(tmp, t1, 8);
3624 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3625 tcg_gen_or_i32(rd, rd, tmp);
3627 tcg_gen_shri_i32(rm, t0, 8);
3628 tcg_gen_andi_i32(rm, rm, 0xff);
3629 tcg_gen_shri_i32(tmp, t0, 16);
3630 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3631 tcg_gen_or_i32(rm, rm, tmp);
3632 tcg_gen_shli_i32(tmp, t1, 8);
3633 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3634 tcg_gen_or_i32(rm, rm, tmp);
3635 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3636 tcg_gen_or_i32(t1, rm, tmp);
3637 tcg_gen_mov_i32(t0, rd);
3639 dead_tmp(tmp);
3640 dead_tmp(rm);
3641 dead_tmp(rd);
3644 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3646 TCGv rd, rm, tmp;
3648 rd = new_tmp();
3649 rm = new_tmp();
3650 tmp = new_tmp();
3652 tcg_gen_andi_i32(rd, t0, 0xff);
3653 tcg_gen_shli_i32(tmp, t1, 8);
3654 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3655 tcg_gen_or_i32(rd, rd, tmp);
3656 tcg_gen_shli_i32(tmp, t0, 16);
3657 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3658 tcg_gen_or_i32(rd, rd, tmp);
3659 tcg_gen_shli_i32(tmp, t1, 24);
3660 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3661 tcg_gen_or_i32(rd, rd, tmp);
3663 tcg_gen_andi_i32(rm, t1, 0xff000000);
3664 tcg_gen_shri_i32(tmp, t0, 8);
3665 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3666 tcg_gen_or_i32(rm, rm, tmp);
3667 tcg_gen_shri_i32(tmp, t1, 8);
3668 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3669 tcg_gen_or_i32(rm, rm, tmp);
3670 tcg_gen_shri_i32(tmp, t0, 16);
3671 tcg_gen_andi_i32(tmp, tmp, 0xff);
3672 tcg_gen_or_i32(t1, rm, tmp);
3673 tcg_gen_mov_i32(t0, rd);
3675 dead_tmp(tmp);
3676 dead_tmp(rm);
3677 dead_tmp(rd);
3680 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3682 TCGv tmp, tmp2;
3684 tmp = new_tmp();
3685 tmp2 = new_tmp();
3687 tcg_gen_andi_i32(tmp, t0, 0xffff);
3688 tcg_gen_shli_i32(tmp2, t1, 16);
3689 tcg_gen_or_i32(tmp, tmp, tmp2);
3690 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3691 tcg_gen_shri_i32(tmp2, t0, 16);
3692 tcg_gen_or_i32(t1, t1, tmp2);
3693 tcg_gen_mov_i32(t0, tmp);
3695 dead_tmp(tmp2);
3696 dead_tmp(tmp);
3699 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3701 int n;
3702 TCGv t0, t1;
3704 for (n = 0; n < q + 1; n += 2) {
3705 t0 = neon_load_reg(reg, n);
3706 t1 = neon_load_reg(reg, n + 1);
3707 switch (size) {
3708 case 0: gen_neon_unzip_u8(t0, t1); break;
3709 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3710 case 2: /* no-op */; break;
3711 default: abort();
3713 neon_store_scratch(tmp + n, t0);
3714 neon_store_scratch(tmp + n + 1, t1);
3718 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3720 TCGv rd, tmp;
3722 rd = new_tmp();
3723 tmp = new_tmp();
3725 tcg_gen_shli_i32(rd, t0, 8);
3726 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3727 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3728 tcg_gen_or_i32(rd, rd, tmp);
3730 tcg_gen_shri_i32(t1, t1, 8);
3731 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3732 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3733 tcg_gen_or_i32(t1, t1, tmp);
3734 tcg_gen_mov_i32(t0, rd);
3736 dead_tmp(tmp);
3737 dead_tmp(rd);
3740 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3742 TCGv rd, tmp;
3744 rd = new_tmp();
3745 tmp = new_tmp();
3747 tcg_gen_shli_i32(rd, t0, 16);
3748 tcg_gen_andi_i32(tmp, t1, 0xffff);
3749 tcg_gen_or_i32(rd, rd, tmp);
3750 tcg_gen_shri_i32(t1, t1, 16);
3751 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3752 tcg_gen_or_i32(t1, t1, tmp);
3753 tcg_gen_mov_i32(t0, rd);
3755 dead_tmp(tmp);
3756 dead_tmp(rd);
3760 static struct {
3761 int nregs;
3762 int interleave;
3763 int spacing;
3764 } neon_ls_element_type[11] = {
3765 {4, 4, 1},
3766 {4, 4, 2},
3767 {4, 1, 1},
3768 {4, 2, 1},
3769 {3, 3, 1},
3770 {3, 3, 2},
3771 {3, 1, 1},
3772 {1, 1, 1},
3773 {2, 2, 1},
3774 {2, 2, 2},
3775 {2, 1, 1}
3778 /* Translate a NEON load/store element instruction. Return nonzero if the
3779 instruction is invalid. */
3780 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3782 int rd, rn, rm;
3783 int op;
3784 int nregs;
3785 int interleave;
3786 int spacing;
3787 int stride;
3788 int size;
3789 int reg;
3790 int pass;
3791 int load;
3792 int shift;
3793 int n;
3794 TCGv addr;
3795 TCGv tmp;
3796 TCGv tmp2;
3797 TCGv_i64 tmp64;
3799 if (!vfp_enabled(env))
3800 return 1;
3801 VFP_DREG_D(rd, insn);
3802 rn = (insn >> 16) & 0xf;
3803 rm = insn & 0xf;
3804 load = (insn & (1 << 21)) != 0;
3805 addr = new_tmp();
3806 if ((insn & (1 << 23)) == 0) {
3807 /* Load store all elements. */
3808 op = (insn >> 8) & 0xf;
3809 size = (insn >> 6) & 3;
3810 if (op > 10)
3811 return 1;
3812 nregs = neon_ls_element_type[op].nregs;
3813 interleave = neon_ls_element_type[op].interleave;
3814 spacing = neon_ls_element_type[op].spacing;
3815 if (size == 3 && (interleave | spacing) != 1)
3816 return 1;
3817 load_reg_var(s, addr, rn);
3818 stride = (1 << size) * interleave;
3819 for (reg = 0; reg < nregs; reg++) {
3820 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3821 load_reg_var(s, addr, rn);
3822 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3823 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3824 load_reg_var(s, addr, rn);
3825 tcg_gen_addi_i32(addr, addr, 1 << size);
3827 if (size == 3) {
3828 if (load) {
3829 tmp64 = gen_ld64(addr, IS_USER(s));
3830 neon_store_reg64(tmp64, rd);
3831 tcg_temp_free_i64(tmp64);
3832 } else {
3833 tmp64 = tcg_temp_new_i64();
3834 neon_load_reg64(tmp64, rd);
3835 gen_st64(tmp64, addr, IS_USER(s));
3837 tcg_gen_addi_i32(addr, addr, stride);
3838 } else {
3839 for (pass = 0; pass < 2; pass++) {
3840 if (size == 2) {
3841 if (load) {
3842 tmp = gen_ld32(addr, IS_USER(s));
3843 neon_store_reg(rd, pass, tmp);
3844 } else {
3845 tmp = neon_load_reg(rd, pass);
3846 gen_st32(tmp, addr, IS_USER(s));
3848 tcg_gen_addi_i32(addr, addr, stride);
3849 } else if (size == 1) {
3850 if (load) {
3851 tmp = gen_ld16u(addr, IS_USER(s));
3852 tcg_gen_addi_i32(addr, addr, stride);
3853 tmp2 = gen_ld16u(addr, IS_USER(s));
3854 tcg_gen_addi_i32(addr, addr, stride);
3855 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3856 dead_tmp(tmp2);
3857 neon_store_reg(rd, pass, tmp);
3858 } else {
3859 tmp = neon_load_reg(rd, pass);
3860 tmp2 = new_tmp();
3861 tcg_gen_shri_i32(tmp2, tmp, 16);
3862 gen_st16(tmp, addr, IS_USER(s));
3863 tcg_gen_addi_i32(addr, addr, stride);
3864 gen_st16(tmp2, addr, IS_USER(s));
3865 tcg_gen_addi_i32(addr, addr, stride);
3867 } else /* size == 0 */ {
3868 if (load) {
3869 TCGV_UNUSED(tmp2);
3870 for (n = 0; n < 4; n++) {
3871 tmp = gen_ld8u(addr, IS_USER(s));
3872 tcg_gen_addi_i32(addr, addr, stride);
3873 if (n == 0) {
3874 tmp2 = tmp;
3875 } else {
3876 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3877 dead_tmp(tmp);
3880 neon_store_reg(rd, pass, tmp2);
3881 } else {
3882 tmp2 = neon_load_reg(rd, pass);
3883 for (n = 0; n < 4; n++) {
3884 tmp = new_tmp();
3885 if (n == 0) {
3886 tcg_gen_mov_i32(tmp, tmp2);
3887 } else {
3888 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3890 gen_st8(tmp, addr, IS_USER(s));
3891 tcg_gen_addi_i32(addr, addr, stride);
3893 dead_tmp(tmp2);
3898 rd += spacing;
3900 stride = nregs * 8;
3901 } else {
3902 size = (insn >> 10) & 3;
3903 if (size == 3) {
3904 /* Load single element to all lanes. */
3905 if (!load)
3906 return 1;
3907 size = (insn >> 6) & 3;
3908 nregs = ((insn >> 8) & 3) + 1;
3909 stride = (insn & (1 << 5)) ? 2 : 1;
3910 load_reg_var(s, addr, rn);
3911 for (reg = 0; reg < nregs; reg++) {
3912 switch (size) {
3913 case 0:
3914 tmp = gen_ld8u(addr, IS_USER(s));
3915 gen_neon_dup_u8(tmp, 0);
3916 break;
3917 case 1:
3918 tmp = gen_ld16u(addr, IS_USER(s));
3919 gen_neon_dup_low16(tmp);
3920 break;
3921 case 2:
3922 tmp = gen_ld32(addr, IS_USER(s));
3923 break;
3924 case 3:
3925 return 1;
3926 default: /* Avoid compiler warnings. */
3927 abort();
3929 tcg_gen_addi_i32(addr, addr, 1 << size);
3930 tmp2 = new_tmp();
3931 tcg_gen_mov_i32(tmp2, tmp);
3932 neon_store_reg(rd, 0, tmp2);
3933 neon_store_reg(rd, 1, tmp);
3934 rd += stride;
3936 stride = (1 << size) * nregs;
3937 } else {
3938 /* Single element. */
3939 pass = (insn >> 7) & 1;
3940 switch (size) {
3941 case 0:
3942 shift = ((insn >> 5) & 3) * 8;
3943 stride = 1;
3944 break;
3945 case 1:
3946 shift = ((insn >> 6) & 1) * 16;
3947 stride = (insn & (1 << 5)) ? 2 : 1;
3948 break;
3949 case 2:
3950 shift = 0;
3951 stride = (insn & (1 << 6)) ? 2 : 1;
3952 break;
3953 default:
3954 abort();
3956 nregs = ((insn >> 8) & 3) + 1;
3957 load_reg_var(s, addr, rn);
3958 for (reg = 0; reg < nregs; reg++) {
3959 if (load) {
3960 switch (size) {
3961 case 0:
3962 tmp = gen_ld8u(addr, IS_USER(s));
3963 break;
3964 case 1:
3965 tmp = gen_ld16u(addr, IS_USER(s));
3966 break;
3967 case 2:
3968 tmp = gen_ld32(addr, IS_USER(s));
3969 break;
3970 default: /* Avoid compiler warnings. */
3971 abort();
3973 if (size != 2) {
3974 tmp2 = neon_load_reg(rd, pass);
3975 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3976 dead_tmp(tmp2);
3978 neon_store_reg(rd, pass, tmp);
3979 } else { /* Store */
3980 tmp = neon_load_reg(rd, pass);
3981 if (shift)
3982 tcg_gen_shri_i32(tmp, tmp, shift);
3983 switch (size) {
3984 case 0:
3985 gen_st8(tmp, addr, IS_USER(s));
3986 break;
3987 case 1:
3988 gen_st16(tmp, addr, IS_USER(s));
3989 break;
3990 case 2:
3991 gen_st32(tmp, addr, IS_USER(s));
3992 break;
3995 rd += stride;
3996 tcg_gen_addi_i32(addr, addr, 1 << size);
3998 stride = nregs * (1 << size);
4001 dead_tmp(addr);
4002 if (rm != 15) {
4003 TCGv base;
4005 base = load_reg(s, rn);
4006 if (rm == 13) {
4007 tcg_gen_addi_i32(base, base, stride);
4008 } else {
4009 TCGv index;
4010 index = load_reg(s, rm);
4011 tcg_gen_add_i32(base, base, index);
4012 dead_tmp(index);
4014 store_reg(s, rn, base);
4016 return 0;
4019 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4020 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4022 tcg_gen_and_i32(t, t, c);
4023 tcg_gen_andc_i32(f, f, c);
4024 tcg_gen_or_i32(dest, t, f);
4027 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4029 switch (size) {
4030 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4031 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4032 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4033 default: abort();
4037 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4039 switch (size) {
4040 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4041 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4042 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4043 default: abort();
4047 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4049 switch (size) {
4050 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4051 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4052 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4053 default: abort();
4057 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4058 int q, int u)
4060 if (q) {
4061 if (u) {
4062 switch (size) {
4063 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4064 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4065 default: abort();
4067 } else {
4068 switch (size) {
4069 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4070 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4071 default: abort();
4074 } else {
4075 if (u) {
4076 switch (size) {
4077 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4078 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4079 default: abort();
4081 } else {
4082 switch (size) {
4083 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4084 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4085 default: abort();
4091 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4093 if (u) {
4094 switch (size) {
4095 case 0: gen_helper_neon_widen_u8(dest, src); break;
4096 case 1: gen_helper_neon_widen_u16(dest, src); break;
4097 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4098 default: abort();
4100 } else {
4101 switch (size) {
4102 case 0: gen_helper_neon_widen_s8(dest, src); break;
4103 case 1: gen_helper_neon_widen_s16(dest, src); break;
4104 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4105 default: abort();
4108 dead_tmp(src);
4111 static inline void gen_neon_addl(int size)
4113 switch (size) {
4114 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4115 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4116 case 2: tcg_gen_add_i64(CPU_V001); break;
4117 default: abort();
4121 static inline void gen_neon_subl(int size)
4123 switch (size) {
4124 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4125 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4126 case 2: tcg_gen_sub_i64(CPU_V001); break;
4127 default: abort();
4131 static inline void gen_neon_negl(TCGv_i64 var, int size)
4133 switch (size) {
4134 case 0: gen_helper_neon_negl_u16(var, var); break;
4135 case 1: gen_helper_neon_negl_u32(var, var); break;
4136 case 2: gen_helper_neon_negl_u64(var, var); break;
4137 default: abort();
4141 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4143 switch (size) {
4144 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4145 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4146 default: abort();
4150 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4152 TCGv_i64 tmp;
4154 switch ((size << 1) | u) {
4155 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4156 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4157 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4158 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4159 case 4:
4160 tmp = gen_muls_i64_i32(a, b);
4161 tcg_gen_mov_i64(dest, tmp);
4162 break;
4163 case 5:
4164 tmp = gen_mulu_i64_i32(a, b);
4165 tcg_gen_mov_i64(dest, tmp);
4166 break;
4167 default: abort();
4171 /* Translate a NEON data processing instruction. Return nonzero if the
4172 instruction is invalid.
4173 We process data in a mixture of 32-bit and 64-bit chunks.
4174 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4176 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4178 int op;
4179 int q;
4180 int rd, rn, rm;
4181 int size;
4182 int shift;
4183 int pass;
4184 int count;
4185 int pairwise;
4186 int u;
4187 int n;
4188 uint32_t imm, mask;
4189 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4190 TCGv_i64 tmp64;
4192 if (!vfp_enabled(env))
4193 return 1;
4194 q = (insn & (1 << 6)) != 0;
4195 u = (insn >> 24) & 1;
4196 VFP_DREG_D(rd, insn);
4197 VFP_DREG_N(rn, insn);
4198 VFP_DREG_M(rm, insn);
4199 size = (insn >> 20) & 3;
4200 if ((insn & (1 << 23)) == 0) {
4201 /* Three register same length. */
4202 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4203 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4204 || op == 10 || op == 11 || op == 16)) {
4205 /* 64-bit element instructions. */
4206 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4207 neon_load_reg64(cpu_V0, rn + pass);
4208 neon_load_reg64(cpu_V1, rm + pass);
4209 switch (op) {
4210 case 1: /* VQADD */
4211 if (u) {
4212 gen_helper_neon_add_saturate_u64(CPU_V001);
4213 } else {
4214 gen_helper_neon_add_saturate_s64(CPU_V001);
4216 break;
4217 case 5: /* VQSUB */
4218 if (u) {
4219 gen_helper_neon_sub_saturate_u64(CPU_V001);
4220 } else {
4221 gen_helper_neon_sub_saturate_s64(CPU_V001);
4223 break;
4224 case 8: /* VSHL */
4225 if (u) {
4226 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4227 } else {
4228 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4230 break;
4231 case 9: /* VQSHL */
4232 if (u) {
4233 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4234 cpu_V0, cpu_V0);
4235 } else {
4236 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4237 cpu_V1, cpu_V0);
4239 break;
4240 case 10: /* VRSHL */
4241 if (u) {
4242 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4243 } else {
4244 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4246 break;
4247 case 11: /* VQRSHL */
4248 if (u) {
4249 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4250 cpu_V1, cpu_V0);
4251 } else {
4252 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4253 cpu_V1, cpu_V0);
4255 break;
4256 case 16:
4257 if (u) {
4258 tcg_gen_sub_i64(CPU_V001);
4259 } else {
4260 tcg_gen_add_i64(CPU_V001);
4262 break;
4263 default:
4264 abort();
4266 neon_store_reg64(cpu_V0, rd + pass);
4268 return 0;
4270 switch (op) {
4271 case 8: /* VSHL */
4272 case 9: /* VQSHL */
4273 case 10: /* VRSHL */
4274 case 11: /* VQRSHL */
4276 int rtmp;
4277 /* Shift instruction operands are reversed. */
4278 rtmp = rn;
4279 rn = rm;
4280 rm = rtmp;
4281 pairwise = 0;
4283 break;
4284 case 20: /* VPMAX */
4285 case 21: /* VPMIN */
4286 case 23: /* VPADD */
4287 pairwise = 1;
4288 break;
4289 case 26: /* VPADD (float) */
4290 pairwise = (u && size < 2);
4291 break;
4292 case 30: /* VPMIN/VPMAX (float) */
4293 pairwise = u;
4294 break;
4295 default:
4296 pairwise = 0;
4297 break;
4300 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4302 if (pairwise) {
4303 /* Pairwise. */
4304 if (q)
4305 n = (pass & 1) * 2;
4306 else
4307 n = 0;
4308 if (pass < q + 1) {
4309 tmp = neon_load_reg(rn, n);
4310 tmp2 = neon_load_reg(rn, n + 1);
4311 } else {
4312 tmp = neon_load_reg(rm, n);
4313 tmp2 = neon_load_reg(rm, n + 1);
4315 } else {
4316 /* Elementwise. */
4317 tmp = neon_load_reg(rn, pass);
4318 tmp2 = neon_load_reg(rm, pass);
4320 switch (op) {
4321 case 0: /* VHADD */
4322 GEN_NEON_INTEGER_OP(hadd);
4323 break;
4324 case 1: /* VQADD */
4325 GEN_NEON_INTEGER_OP_ENV(qadd);
4326 break;
4327 case 2: /* VRHADD */
4328 GEN_NEON_INTEGER_OP(rhadd);
4329 break;
4330 case 3: /* Logic ops. */
4331 switch ((u << 2) | size) {
4332 case 0: /* VAND */
4333 tcg_gen_and_i32(tmp, tmp, tmp2);
4334 break;
4335 case 1: /* BIC */
4336 tcg_gen_andc_i32(tmp, tmp, tmp2);
4337 break;
4338 case 2: /* VORR */
4339 tcg_gen_or_i32(tmp, tmp, tmp2);
4340 break;
4341 case 3: /* VORN */
4342 tcg_gen_orc_i32(tmp, tmp, tmp2);
4343 break;
4344 case 4: /* VEOR */
4345 tcg_gen_xor_i32(tmp, tmp, tmp2);
4346 break;
4347 case 5: /* VBSL */
4348 tmp3 = neon_load_reg(rd, pass);
4349 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4350 dead_tmp(tmp3);
4351 break;
4352 case 6: /* VBIT */
4353 tmp3 = neon_load_reg(rd, pass);
4354 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4355 dead_tmp(tmp3);
4356 break;
4357 case 7: /* VBIF */
4358 tmp3 = neon_load_reg(rd, pass);
4359 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4360 dead_tmp(tmp3);
4361 break;
4363 break;
4364 case 4: /* VHSUB */
4365 GEN_NEON_INTEGER_OP(hsub);
4366 break;
4367 case 5: /* VQSUB */
4368 GEN_NEON_INTEGER_OP_ENV(qsub);
4369 break;
4370 case 6: /* VCGT */
4371 GEN_NEON_INTEGER_OP(cgt);
4372 break;
4373 case 7: /* VCGE */
4374 GEN_NEON_INTEGER_OP(cge);
4375 break;
4376 case 8: /* VSHL */
4377 GEN_NEON_INTEGER_OP(shl);
4378 break;
4379 case 9: /* VQSHL */
4380 GEN_NEON_INTEGER_OP_ENV(qshl);
4381 break;
4382 case 10: /* VRSHL */
4383 GEN_NEON_INTEGER_OP(rshl);
4384 break;
4385 case 11: /* VQRSHL */
4386 GEN_NEON_INTEGER_OP_ENV(qrshl);
4387 break;
4388 case 12: /* VMAX */
4389 GEN_NEON_INTEGER_OP(max);
4390 break;
4391 case 13: /* VMIN */
4392 GEN_NEON_INTEGER_OP(min);
4393 break;
4394 case 14: /* VABD */
4395 GEN_NEON_INTEGER_OP(abd);
4396 break;
4397 case 15: /* VABA */
4398 GEN_NEON_INTEGER_OP(abd);
4399 dead_tmp(tmp2);
4400 tmp2 = neon_load_reg(rd, pass);
4401 gen_neon_add(size, tmp, tmp2);
4402 break;
4403 case 16:
4404 if (!u) { /* VADD */
4405 if (gen_neon_add(size, tmp, tmp2))
4406 return 1;
4407 } else { /* VSUB */
4408 switch (size) {
4409 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4410 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4411 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4412 default: return 1;
4415 break;
4416 case 17:
4417 if (!u) { /* VTST */
4418 switch (size) {
4419 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4420 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4421 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4422 default: return 1;
4424 } else { /* VCEQ */
4425 switch (size) {
4426 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4427 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4428 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4429 default: return 1;
4432 break;
4433 case 18: /* Multiply. */
4434 switch (size) {
4435 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4436 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4437 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4438 default: return 1;
4440 dead_tmp(tmp2);
4441 tmp2 = neon_load_reg(rd, pass);
4442 if (u) { /* VMLS */
4443 gen_neon_rsb(size, tmp, tmp2);
4444 } else { /* VMLA */
4445 gen_neon_add(size, tmp, tmp2);
4447 break;
4448 case 19: /* VMUL */
4449 if (u) { /* polynomial */
4450 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4451 } else { /* Integer */
4452 switch (size) {
4453 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4454 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4455 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4456 default: return 1;
4459 break;
4460 case 20: /* VPMAX */
4461 GEN_NEON_INTEGER_OP(pmax);
4462 break;
4463 case 21: /* VPMIN */
4464 GEN_NEON_INTEGER_OP(pmin);
4465 break;
4466 case 22: /* Hultiply high. */
4467 if (!u) { /* VQDMULH */
4468 switch (size) {
4469 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4470 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4471 default: return 1;
4473 } else { /* VQRDHMUL */
4474 switch (size) {
4475 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4476 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4477 default: return 1;
4480 break;
4481 case 23: /* VPADD */
4482 if (u)
4483 return 1;
4484 switch (size) {
4485 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4486 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4487 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4488 default: return 1;
4490 break;
4491 case 26: /* Floating point arithnetic. */
4492 switch ((u << 2) | size) {
4493 case 0: /* VADD */
4494 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4495 break;
4496 case 2: /* VSUB */
4497 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4498 break;
4499 case 4: /* VPADD */
4500 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4501 break;
4502 case 6: /* VABD */
4503 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4504 break;
4505 default:
4506 return 1;
4508 break;
4509 case 27: /* Float multiply. */
4510 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4511 if (!u) {
4512 dead_tmp(tmp2);
4513 tmp2 = neon_load_reg(rd, pass);
4514 if (size == 0) {
4515 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4516 } else {
4517 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4520 break;
4521 case 28: /* Float compare. */
4522 if (!u) {
4523 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4524 } else {
4525 if (size == 0)
4526 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4527 else
4528 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4530 break;
4531 case 29: /* Float compare absolute. */
4532 if (!u)
4533 return 1;
4534 if (size == 0)
4535 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4536 else
4537 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4538 break;
4539 case 30: /* Float min/max. */
4540 if (size == 0)
4541 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4542 else
4543 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4544 break;
4545 case 31:
4546 if (size == 0)
4547 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4548 else
4549 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4550 break;
4551 default:
4552 abort();
4554 dead_tmp(tmp2);
4556 /* Save the result. For elementwise operations we can put it
4557 straight into the destination register. For pairwise operations
4558 we have to be careful to avoid clobbering the source operands. */
4559 if (pairwise && rd == rm) {
4560 neon_store_scratch(pass, tmp);
4561 } else {
4562 neon_store_reg(rd, pass, tmp);
4565 } /* for pass */
4566 if (pairwise && rd == rm) {
4567 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4568 tmp = neon_load_scratch(pass);
4569 neon_store_reg(rd, pass, tmp);
4572 /* End of 3 register same size operations. */
4573 } else if (insn & (1 << 4)) {
4574 if ((insn & 0x00380080) != 0) {
4575 /* Two registers and shift. */
4576 op = (insn >> 8) & 0xf;
4577 if (insn & (1 << 7)) {
4578 /* 64-bit shift. */
4579 size = 3;
4580 } else {
4581 size = 2;
4582 while ((insn & (1 << (size + 19))) == 0)
4583 size--;
4585 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4586 /* To avoid excessive dumplication of ops we implement shift
4587 by immediate using the variable shift operations. */
4588 if (op < 8) {
4589 /* Shift by immediate:
4590 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4591 /* Right shifts are encoded as N - shift, where N is the
4592 element size in bits. */
4593 if (op <= 4)
4594 shift = shift - (1 << (size + 3));
4595 if (size == 3) {
4596 count = q + 1;
4597 } else {
4598 count = q ? 4: 2;
4600 switch (size) {
4601 case 0:
4602 imm = (uint8_t) shift;
4603 imm |= imm << 8;
4604 imm |= imm << 16;
4605 break;
4606 case 1:
4607 imm = (uint16_t) shift;
4608 imm |= imm << 16;
4609 break;
4610 case 2:
4611 case 3:
4612 imm = shift;
4613 break;
4614 default:
4615 abort();
4618 for (pass = 0; pass < count; pass++) {
4619 if (size == 3) {
4620 neon_load_reg64(cpu_V0, rm + pass);
4621 tcg_gen_movi_i64(cpu_V1, imm);
4622 switch (op) {
4623 case 0: /* VSHR */
4624 case 1: /* VSRA */
4625 if (u)
4626 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4627 else
4628 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4629 break;
4630 case 2: /* VRSHR */
4631 case 3: /* VRSRA */
4632 if (u)
4633 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4634 else
4635 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4636 break;
4637 case 4: /* VSRI */
4638 if (!u)
4639 return 1;
4640 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4641 break;
4642 case 5: /* VSHL, VSLI */
4643 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4644 break;
4645 case 6: /* VQSHL */
4646 if (u)
4647 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4648 else
4649 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4650 break;
4651 case 7: /* VQSHLU */
4652 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4653 break;
4655 if (op == 1 || op == 3) {
4656 /* Accumulate. */
4657 neon_load_reg64(cpu_V0, rd + pass);
4658 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4659 } else if (op == 4 || (op == 5 && u)) {
4660 /* Insert */
4661 cpu_abort(env, "VS[LR]I.64 not implemented");
4663 neon_store_reg64(cpu_V0, rd + pass);
4664 } else { /* size < 3 */
4665 /* Operands in T0 and T1. */
4666 tmp = neon_load_reg(rm, pass);
4667 tmp2 = new_tmp();
4668 tcg_gen_movi_i32(tmp2, imm);
4669 switch (op) {
4670 case 0: /* VSHR */
4671 case 1: /* VSRA */
4672 GEN_NEON_INTEGER_OP(shl);
4673 break;
4674 case 2: /* VRSHR */
4675 case 3: /* VRSRA */
4676 GEN_NEON_INTEGER_OP(rshl);
4677 break;
4678 case 4: /* VSRI */
4679 if (!u)
4680 return 1;
4681 GEN_NEON_INTEGER_OP(shl);
4682 break;
4683 case 5: /* VSHL, VSLI */
4684 switch (size) {
4685 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4686 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4687 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4688 default: return 1;
4690 break;
4691 case 6: /* VQSHL */
4692 GEN_NEON_INTEGER_OP_ENV(qshl);
4693 break;
4694 case 7: /* VQSHLU */
4695 switch (size) {
4696 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4697 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4698 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4699 default: return 1;
4701 break;
4703 dead_tmp(tmp2);
4705 if (op == 1 || op == 3) {
4706 /* Accumulate. */
4707 tmp2 = neon_load_reg(rd, pass);
4708 gen_neon_add(size, tmp2, tmp);
4709 dead_tmp(tmp2);
4710 } else if (op == 4 || (op == 5 && u)) {
4711 /* Insert */
4712 switch (size) {
4713 case 0:
4714 if (op == 4)
4715 mask = 0xff >> -shift;
4716 else
4717 mask = (uint8_t)(0xff << shift);
4718 mask |= mask << 8;
4719 mask |= mask << 16;
4720 break;
4721 case 1:
4722 if (op == 4)
4723 mask = 0xffff >> -shift;
4724 else
4725 mask = (uint16_t)(0xffff << shift);
4726 mask |= mask << 16;
4727 break;
4728 case 2:
4729 if (shift < -31 || shift > 31) {
4730 mask = 0;
4731 } else {
4732 if (op == 4)
4733 mask = 0xffffffffu >> -shift;
4734 else
4735 mask = 0xffffffffu << shift;
4737 break;
4738 default:
4739 abort();
4741 tmp2 = neon_load_reg(rd, pass);
4742 tcg_gen_andi_i32(tmp, tmp, mask);
4743 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4744 tcg_gen_or_i32(tmp, tmp, tmp2);
4745 dead_tmp(tmp2);
4747 neon_store_reg(rd, pass, tmp);
4749 } /* for pass */
4750 } else if (op < 10) {
4751 /* Shift by immediate and narrow:
4752 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4753 shift = shift - (1 << (size + 3));
4754 size++;
4755 switch (size) {
4756 case 1:
4757 imm = (uint16_t)shift;
4758 imm |= imm << 16;
4759 tmp2 = tcg_const_i32(imm);
4760 TCGV_UNUSED_I64(tmp64);
4761 break;
4762 case 2:
4763 imm = (uint32_t)shift;
4764 tmp2 = tcg_const_i32(imm);
4765 TCGV_UNUSED_I64(tmp64);
4766 break;
4767 case 3:
4768 tmp64 = tcg_const_i64(shift);
4769 TCGV_UNUSED(tmp2);
4770 break;
4771 default:
4772 abort();
4775 for (pass = 0; pass < 2; pass++) {
4776 if (size == 3) {
4777 neon_load_reg64(cpu_V0, rm + pass);
4778 if (q) {
4779 if (u)
4780 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4781 else
4782 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4783 } else {
4784 if (u)
4785 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4786 else
4787 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4789 } else {
4790 tmp = neon_load_reg(rm + pass, 0);
4791 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4792 tmp3 = neon_load_reg(rm + pass, 1);
4793 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4794 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4795 dead_tmp(tmp);
4796 dead_tmp(tmp3);
4798 tmp = new_tmp();
4799 if (op == 8 && !u) {
4800 gen_neon_narrow(size - 1, tmp, cpu_V0);
4801 } else {
4802 if (op == 8)
4803 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4804 else
4805 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4807 neon_store_reg(rd, pass, tmp);
4808 } /* for pass */
4809 if (size == 3) {
4810 tcg_temp_free_i64(tmp64);
4811 } else {
4812 dead_tmp(tmp2);
4814 } else if (op == 10) {
4815 /* VSHLL */
4816 if (q || size == 3)
4817 return 1;
4818 tmp = neon_load_reg(rm, 0);
4819 tmp2 = neon_load_reg(rm, 1);
4820 for (pass = 0; pass < 2; pass++) {
4821 if (pass == 1)
4822 tmp = tmp2;
4824 gen_neon_widen(cpu_V0, tmp, size, u);
4826 if (shift != 0) {
4827 /* The shift is less than the width of the source
4828 type, so we can just shift the whole register. */
4829 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4830 if (size < 2 || !u) {
4831 uint64_t imm64;
4832 if (size == 0) {
4833 imm = (0xffu >> (8 - shift));
4834 imm |= imm << 16;
4835 } else {
4836 imm = 0xffff >> (16 - shift);
4838 imm64 = imm | (((uint64_t)imm) << 32);
4839 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4842 neon_store_reg64(cpu_V0, rd + pass);
4844 } else if (op == 15 || op == 16) {
4845 /* VCVT fixed-point. */
4846 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4847 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4848 if (op & 1) {
4849 if (u)
4850 gen_vfp_ulto(0, shift);
4851 else
4852 gen_vfp_slto(0, shift);
4853 } else {
4854 if (u)
4855 gen_vfp_toul(0, shift);
4856 else
4857 gen_vfp_tosl(0, shift);
4859 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4861 } else {
4862 return 1;
4864 } else { /* (insn & 0x00380080) == 0 */
4865 int invert;
4867 op = (insn >> 8) & 0xf;
4868 /* One register and immediate. */
4869 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4870 invert = (insn & (1 << 5)) != 0;
4871 switch (op) {
4872 case 0: case 1:
4873 /* no-op */
4874 break;
4875 case 2: case 3:
4876 imm <<= 8;
4877 break;
4878 case 4: case 5:
4879 imm <<= 16;
4880 break;
4881 case 6: case 7:
4882 imm <<= 24;
4883 break;
4884 case 8: case 9:
4885 imm |= imm << 16;
4886 break;
4887 case 10: case 11:
4888 imm = (imm << 8) | (imm << 24);
4889 break;
4890 case 12:
4891 imm = (imm < 8) | 0xff;
4892 break;
4893 case 13:
4894 imm = (imm << 16) | 0xffff;
4895 break;
4896 case 14:
4897 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4898 if (invert)
4899 imm = ~imm;
4900 break;
4901 case 15:
4902 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4903 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4904 break;
4906 if (invert)
4907 imm = ~imm;
4909 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4910 if (op & 1 && op < 12) {
4911 tmp = neon_load_reg(rd, pass);
4912 if (invert) {
4913 /* The immediate value has already been inverted, so
4914 BIC becomes AND. */
4915 tcg_gen_andi_i32(tmp, tmp, imm);
4916 } else {
4917 tcg_gen_ori_i32(tmp, tmp, imm);
4919 } else {
4920 /* VMOV, VMVN. */
4921 tmp = new_tmp();
4922 if (op == 14 && invert) {
4923 uint32_t val;
4924 val = 0;
4925 for (n = 0; n < 4; n++) {
4926 if (imm & (1 << (n + (pass & 1) * 4)))
4927 val |= 0xff << (n * 8);
4929 tcg_gen_movi_i32(tmp, val);
4930 } else {
4931 tcg_gen_movi_i32(tmp, imm);
4934 neon_store_reg(rd, pass, tmp);
4937 } else { /* (insn & 0x00800010 == 0x00800000) */
4938 if (size != 3) {
4939 op = (insn >> 8) & 0xf;
4940 if ((insn & (1 << 6)) == 0) {
4941 /* Three registers of different lengths. */
4942 int src1_wide;
4943 int src2_wide;
4944 int prewiden;
4945 /* prewiden, src1_wide, src2_wide */
4946 static const int neon_3reg_wide[16][3] = {
4947 {1, 0, 0}, /* VADDL */
4948 {1, 1, 0}, /* VADDW */
4949 {1, 0, 0}, /* VSUBL */
4950 {1, 1, 0}, /* VSUBW */
4951 {0, 1, 1}, /* VADDHN */
4952 {0, 0, 0}, /* VABAL */
4953 {0, 1, 1}, /* VSUBHN */
4954 {0, 0, 0}, /* VABDL */
4955 {0, 0, 0}, /* VMLAL */
4956 {0, 0, 0}, /* VQDMLAL */
4957 {0, 0, 0}, /* VMLSL */
4958 {0, 0, 0}, /* VQDMLSL */
4959 {0, 0, 0}, /* Integer VMULL */
4960 {0, 0, 0}, /* VQDMULL */
4961 {0, 0, 0} /* Polynomial VMULL */
4964 prewiden = neon_3reg_wide[op][0];
4965 src1_wide = neon_3reg_wide[op][1];
4966 src2_wide = neon_3reg_wide[op][2];
4968 if (size == 0 && (op == 9 || op == 11 || op == 13))
4969 return 1;
4971 /* Avoid overlapping operands. Wide source operands are
4972 always aligned so will never overlap with wide
4973 destinations in problematic ways. */
4974 if (rd == rm && !src2_wide) {
4975 tmp = neon_load_reg(rm, 1);
4976 neon_store_scratch(2, tmp);
4977 } else if (rd == rn && !src1_wide) {
4978 tmp = neon_load_reg(rn, 1);
4979 neon_store_scratch(2, tmp);
4981 TCGV_UNUSED(tmp3);
4982 for (pass = 0; pass < 2; pass++) {
4983 if (src1_wide) {
4984 neon_load_reg64(cpu_V0, rn + pass);
4985 TCGV_UNUSED(tmp);
4986 } else {
4987 if (pass == 1 && rd == rn) {
4988 tmp = neon_load_scratch(2);
4989 } else {
4990 tmp = neon_load_reg(rn, pass);
4992 if (prewiden) {
4993 gen_neon_widen(cpu_V0, tmp, size, u);
4996 if (src2_wide) {
4997 neon_load_reg64(cpu_V1, rm + pass);
4998 TCGV_UNUSED(tmp2);
4999 } else {
5000 if (pass == 1 && rd == rm) {
5001 tmp2 = neon_load_scratch(2);
5002 } else {
5003 tmp2 = neon_load_reg(rm, pass);
5005 if (prewiden) {
5006 gen_neon_widen(cpu_V1, tmp2, size, u);
5009 switch (op) {
5010 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5011 gen_neon_addl(size);
5012 break;
5013 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5014 gen_neon_subl(size);
5015 break;
5016 case 5: case 7: /* VABAL, VABDL */
5017 switch ((size << 1) | u) {
5018 case 0:
5019 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5020 break;
5021 case 1:
5022 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5023 break;
5024 case 2:
5025 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5026 break;
5027 case 3:
5028 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5029 break;
5030 case 4:
5031 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5032 break;
5033 case 5:
5034 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5035 break;
5036 default: abort();
5038 dead_tmp(tmp2);
5039 dead_tmp(tmp);
5040 break;
5041 case 8: case 9: case 10: case 11: case 12: case 13:
5042 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5043 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5044 dead_tmp(tmp2);
5045 dead_tmp(tmp);
5046 break;
5047 case 14: /* Polynomial VMULL */
5048 cpu_abort(env, "Polynomial VMULL not implemented");
5050 default: /* 15 is RESERVED. */
5051 return 1;
5053 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
5054 /* Accumulate. */
5055 if (op == 10 || op == 11) {
5056 gen_neon_negl(cpu_V0, size);
5059 if (op != 13) {
5060 neon_load_reg64(cpu_V1, rd + pass);
5063 switch (op) {
5064 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5065 gen_neon_addl(size);
5066 break;
5067 case 9: case 11: /* VQDMLAL, VQDMLSL */
5068 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5069 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5070 break;
5071 /* Fall through. */
5072 case 13: /* VQDMULL */
5073 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5074 break;
5075 default:
5076 abort();
5078 neon_store_reg64(cpu_V0, rd + pass);
5079 } else if (op == 4 || op == 6) {
5080 /* Narrowing operation. */
5081 tmp = new_tmp();
5082 if (!u) {
5083 switch (size) {
5084 case 0:
5085 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5086 break;
5087 case 1:
5088 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5089 break;
5090 case 2:
5091 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5092 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5093 break;
5094 default: abort();
5096 } else {
5097 switch (size) {
5098 case 0:
5099 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5100 break;
5101 case 1:
5102 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5103 break;
5104 case 2:
5105 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5106 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5107 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5108 break;
5109 default: abort();
5112 if (pass == 0) {
5113 tmp3 = tmp;
5114 } else {
5115 neon_store_reg(rd, 0, tmp3);
5116 neon_store_reg(rd, 1, tmp);
5118 } else {
5119 /* Write back the result. */
5120 neon_store_reg64(cpu_V0, rd + pass);
5123 } else {
5124 /* Two registers and a scalar. */
5125 switch (op) {
5126 case 0: /* Integer VMLA scalar */
5127 case 1: /* Float VMLA scalar */
5128 case 4: /* Integer VMLS scalar */
5129 case 5: /* Floating point VMLS scalar */
5130 case 8: /* Integer VMUL scalar */
5131 case 9: /* Floating point VMUL scalar */
5132 case 12: /* VQDMULH scalar */
5133 case 13: /* VQRDMULH scalar */
5134 tmp = neon_get_scalar(size, rm);
5135 neon_store_scratch(0, tmp);
5136 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5137 tmp = neon_load_scratch(0);
5138 tmp2 = neon_load_reg(rn, pass);
5139 if (op == 12) {
5140 if (size == 1) {
5141 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5142 } else {
5143 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5145 } else if (op == 13) {
5146 if (size == 1) {
5147 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5148 } else {
5149 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5151 } else if (op & 1) {
5152 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5153 } else {
5154 switch (size) {
5155 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5156 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5157 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5158 default: return 1;
5161 dead_tmp(tmp2);
5162 if (op < 8) {
5163 /* Accumulate. */
5164 tmp2 = neon_load_reg(rd, pass);
5165 switch (op) {
5166 case 0:
5167 gen_neon_add(size, tmp, tmp2);
5168 break;
5169 case 1:
5170 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5171 break;
5172 case 4:
5173 gen_neon_rsb(size, tmp, tmp2);
5174 break;
5175 case 5:
5176 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5177 break;
5178 default:
5179 abort();
5181 dead_tmp(tmp2);
5183 neon_store_reg(rd, pass, tmp);
5185 break;
5186 case 2: /* VMLAL sclar */
5187 case 3: /* VQDMLAL scalar */
5188 case 6: /* VMLSL scalar */
5189 case 7: /* VQDMLSL scalar */
5190 case 10: /* VMULL scalar */
5191 case 11: /* VQDMULL scalar */
5192 if (size == 0 && (op == 3 || op == 7 || op == 11))
5193 return 1;
5195 tmp2 = neon_get_scalar(size, rm);
5196 tmp3 = neon_load_reg(rn, 1);
5198 for (pass = 0; pass < 2; pass++) {
5199 if (pass == 0) {
5200 tmp = neon_load_reg(rn, 0);
5201 } else {
5202 tmp = tmp3;
5204 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5205 dead_tmp(tmp);
5206 if (op == 6 || op == 7) {
5207 gen_neon_negl(cpu_V0, size);
5209 if (op != 11) {
5210 neon_load_reg64(cpu_V1, rd + pass);
5212 switch (op) {
5213 case 2: case 6:
5214 gen_neon_addl(size);
5215 break;
5216 case 3: case 7:
5217 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5218 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5219 break;
5220 case 10:
5221 /* no-op */
5222 break;
5223 case 11:
5224 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5225 break;
5226 default:
5227 abort();
5229 neon_store_reg64(cpu_V0, rd + pass);
5232 dead_tmp(tmp2);
5234 break;
5235 default: /* 14 and 15 are RESERVED */
5236 return 1;
5239 } else { /* size == 3 */
5240 if (!u) {
5241 /* Extract. */
5242 imm = (insn >> 8) & 0xf;
5243 count = q + 1;
5245 if (imm > 7 && !q)
5246 return 1;
5248 if (imm == 0) {
5249 neon_load_reg64(cpu_V0, rn);
5250 if (q) {
5251 neon_load_reg64(cpu_V1, rn + 1);
5253 } else if (imm == 8) {
5254 neon_load_reg64(cpu_V0, rn + 1);
5255 if (q) {
5256 neon_load_reg64(cpu_V1, rm);
5258 } else if (q) {
5259 tmp64 = tcg_temp_new_i64();
5260 if (imm < 8) {
5261 neon_load_reg64(cpu_V0, rn);
5262 neon_load_reg64(tmp64, rn + 1);
5263 } else {
5264 neon_load_reg64(cpu_V0, rn + 1);
5265 neon_load_reg64(tmp64, rm);
5267 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5268 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5269 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5270 if (imm < 8) {
5271 neon_load_reg64(cpu_V1, rm);
5272 } else {
5273 neon_load_reg64(cpu_V1, rm + 1);
5274 imm -= 8;
5276 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5277 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5278 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5279 tcg_temp_free_i64(tmp64);
5280 } else {
5281 /* BUGFIX */
5282 neon_load_reg64(cpu_V0, rn);
5283 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5284 neon_load_reg64(cpu_V1, rm);
5285 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5286 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5288 neon_store_reg64(cpu_V0, rd);
5289 if (q) {
5290 neon_store_reg64(cpu_V1, rd + 1);
5292 } else if ((insn & (1 << 11)) == 0) {
5293 /* Two register misc. */
5294 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5295 size = (insn >> 18) & 3;
5296 switch (op) {
5297 case 0: /* VREV64 */
5298 if (size == 3)
5299 return 1;
5300 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5301 tmp = neon_load_reg(rm, pass * 2);
5302 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5303 switch (size) {
5304 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5305 case 1: gen_swap_half(tmp); break;
5306 case 2: /* no-op */ break;
5307 default: abort();
5309 neon_store_reg(rd, pass * 2 + 1, tmp);
5310 if (size == 2) {
5311 neon_store_reg(rd, pass * 2, tmp2);
5312 } else {
5313 switch (size) {
5314 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5315 case 1: gen_swap_half(tmp2); break;
5316 default: abort();
5318 neon_store_reg(rd, pass * 2, tmp2);
5321 break;
5322 case 4: case 5: /* VPADDL */
5323 case 12: case 13: /* VPADAL */
5324 if (size == 3)
5325 return 1;
5326 for (pass = 0; pass < q + 1; pass++) {
5327 tmp = neon_load_reg(rm, pass * 2);
5328 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5329 tmp = neon_load_reg(rm, pass * 2 + 1);
5330 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5331 switch (size) {
5332 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5333 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5334 case 2: tcg_gen_add_i64(CPU_V001); break;
5335 default: abort();
5337 if (op >= 12) {
5338 /* Accumulate. */
5339 neon_load_reg64(cpu_V1, rd + pass);
5340 gen_neon_addl(size);
5342 neon_store_reg64(cpu_V0, rd + pass);
5344 break;
5345 case 33: /* VTRN */
5346 if (size == 2) {
5347 for (n = 0; n < (q ? 4 : 2); n += 2) {
5348 tmp = neon_load_reg(rm, n);
5349 tmp2 = neon_load_reg(rd, n + 1);
5350 neon_store_reg(rm, n, tmp2);
5351 neon_store_reg(rd, n + 1, tmp);
5353 } else {
5354 goto elementwise;
5356 break;
5357 case 34: /* VUZP */
5358 /* Reg Before After
5359 Rd A3 A2 A1 A0 B2 B0 A2 A0
5360 Rm B3 B2 B1 B0 B3 B1 A3 A1
5362 if (size == 3)
5363 return 1;
5364 gen_neon_unzip(rd, q, 0, size);
5365 gen_neon_unzip(rm, q, 4, size);
5366 if (q) {
5367 static int unzip_order_q[8] =
5368 {0, 2, 4, 6, 1, 3, 5, 7};
5369 for (n = 0; n < 8; n++) {
5370 int reg = (n < 4) ? rd : rm;
5371 tmp = neon_load_scratch(unzip_order_q[n]);
5372 neon_store_reg(reg, n % 4, tmp);
5374 } else {
5375 static int unzip_order[4] =
5376 {0, 4, 1, 5};
5377 for (n = 0; n < 4; n++) {
5378 int reg = (n < 2) ? rd : rm;
5379 tmp = neon_load_scratch(unzip_order[n]);
5380 neon_store_reg(reg, n % 2, tmp);
5383 break;
5384 case 35: /* VZIP */
5385 /* Reg Before After
5386 Rd A3 A2 A1 A0 B1 A1 B0 A0
5387 Rm B3 B2 B1 B0 B3 A3 B2 A2
5389 if (size == 3)
5390 return 1;
5391 count = (q ? 4 : 2);
5392 for (n = 0; n < count; n++) {
5393 tmp = neon_load_reg(rd, n);
5394 tmp2 = neon_load_reg(rd, n);
5395 switch (size) {
5396 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5397 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5398 case 2: /* no-op */; break;
5399 default: abort();
5401 neon_store_scratch(n * 2, tmp);
5402 neon_store_scratch(n * 2 + 1, tmp2);
5404 for (n = 0; n < count * 2; n++) {
5405 int reg = (n < count) ? rd : rm;
5406 tmp = neon_load_scratch(n);
5407 neon_store_reg(reg, n % count, tmp);
5409 break;
5410 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5411 if (size == 3)
5412 return 1;
5413 TCGV_UNUSED(tmp2);
5414 for (pass = 0; pass < 2; pass++) {
5415 neon_load_reg64(cpu_V0, rm + pass);
5416 tmp = new_tmp();
5417 if (op == 36 && q == 0) {
5418 gen_neon_narrow(size, tmp, cpu_V0);
5419 } else if (q) {
5420 gen_neon_narrow_satu(size, tmp, cpu_V0);
5421 } else {
5422 gen_neon_narrow_sats(size, tmp, cpu_V0);
5424 if (pass == 0) {
5425 tmp2 = tmp;
5426 } else {
5427 neon_store_reg(rd, 0, tmp2);
5428 neon_store_reg(rd, 1, tmp);
5431 break;
5432 case 38: /* VSHLL */
5433 if (q || size == 3)
5434 return 1;
5435 tmp = neon_load_reg(rm, 0);
5436 tmp2 = neon_load_reg(rm, 1);
5437 for (pass = 0; pass < 2; pass++) {
5438 if (pass == 1)
5439 tmp = tmp2;
5440 gen_neon_widen(cpu_V0, tmp, size, 1);
5441 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5442 neon_store_reg64(cpu_V0, rd + pass);
5444 break;
5445 case 44: /* VCVT.F16.F32 */
5446 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5447 return 1;
5448 tmp = new_tmp();
5449 tmp2 = new_tmp();
5450 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5451 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5452 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5453 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5454 tcg_gen_shli_i32(tmp2, tmp2, 16);
5455 tcg_gen_or_i32(tmp2, tmp2, tmp);
5456 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5457 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5458 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5459 neon_store_reg(rd, 0, tmp2);
5460 tmp2 = new_tmp();
5461 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5462 tcg_gen_shli_i32(tmp2, tmp2, 16);
5463 tcg_gen_or_i32(tmp2, tmp2, tmp);
5464 neon_store_reg(rd, 1, tmp2);
5465 dead_tmp(tmp);
5466 break;
5467 case 46: /* VCVT.F32.F16 */
5468 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5469 return 1;
5470 tmp3 = new_tmp();
5471 tmp = neon_load_reg(rm, 0);
5472 tmp2 = neon_load_reg(rm, 1);
5473 tcg_gen_ext16u_i32(tmp3, tmp);
5474 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5475 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5476 tcg_gen_shri_i32(tmp3, tmp, 16);
5477 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5478 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5479 dead_tmp(tmp);
5480 tcg_gen_ext16u_i32(tmp3, tmp2);
5481 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5482 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5483 tcg_gen_shri_i32(tmp3, tmp2, 16);
5484 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5485 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5486 dead_tmp(tmp2);
5487 dead_tmp(tmp3);
5488 break;
5489 default:
5490 elementwise:
5491 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5492 if (op == 30 || op == 31 || op >= 58) {
5493 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5494 neon_reg_offset(rm, pass));
5495 TCGV_UNUSED(tmp);
5496 } else {
5497 tmp = neon_load_reg(rm, pass);
5499 switch (op) {
5500 case 1: /* VREV32 */
5501 switch (size) {
5502 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5503 case 1: gen_swap_half(tmp); break;
5504 default: return 1;
5506 break;
5507 case 2: /* VREV16 */
5508 if (size != 0)
5509 return 1;
5510 gen_rev16(tmp);
5511 break;
5512 case 8: /* CLS */
5513 switch (size) {
5514 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5515 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5516 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5517 default: return 1;
5519 break;
5520 case 9: /* CLZ */
5521 switch (size) {
5522 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5523 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5524 case 2: gen_helper_clz(tmp, tmp); break;
5525 default: return 1;
5527 break;
5528 case 10: /* CNT */
5529 if (size != 0)
5530 return 1;
5531 gen_helper_neon_cnt_u8(tmp, tmp);
5532 break;
5533 case 11: /* VNOT */
5534 if (size != 0)
5535 return 1;
5536 tcg_gen_not_i32(tmp, tmp);
5537 break;
5538 case 14: /* VQABS */
5539 switch (size) {
5540 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5541 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5542 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5543 default: return 1;
5545 break;
5546 case 15: /* VQNEG */
5547 switch (size) {
5548 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5549 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5550 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5551 default: return 1;
5553 break;
5554 case 16: case 19: /* VCGT #0, VCLE #0 */
5555 tmp2 = tcg_const_i32(0);
5556 switch(size) {
5557 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5558 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5559 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5560 default: return 1;
5562 tcg_temp_free(tmp2);
5563 if (op == 19)
5564 tcg_gen_not_i32(tmp, tmp);
5565 break;
5566 case 17: case 20: /* VCGE #0, VCLT #0 */
5567 tmp2 = tcg_const_i32(0);
5568 switch(size) {
5569 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5570 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5571 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5572 default: return 1;
5574 tcg_temp_free(tmp2);
5575 if (op == 20)
5576 tcg_gen_not_i32(tmp, tmp);
5577 break;
5578 case 18: /* VCEQ #0 */
5579 tmp2 = tcg_const_i32(0);
5580 switch(size) {
5581 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5582 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5583 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5584 default: return 1;
5586 tcg_temp_free(tmp2);
5587 break;
5588 case 22: /* VABS */
5589 switch(size) {
5590 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5591 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5592 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5593 default: return 1;
5595 break;
5596 case 23: /* VNEG */
5597 if (size == 3)
5598 return 1;
5599 tmp2 = tcg_const_i32(0);
5600 gen_neon_rsb(size, tmp, tmp2);
5601 tcg_temp_free(tmp2);
5602 break;
5603 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5604 tmp2 = tcg_const_i32(0);
5605 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5606 tcg_temp_free(tmp2);
5607 if (op == 27)
5608 tcg_gen_not_i32(tmp, tmp);
5609 break;
5610 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5611 tmp2 = tcg_const_i32(0);
5612 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5613 tcg_temp_free(tmp2);
5614 if (op == 28)
5615 tcg_gen_not_i32(tmp, tmp);
5616 break;
5617 case 26: /* Float VCEQ #0 */
5618 tmp2 = tcg_const_i32(0);
5619 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5620 tcg_temp_free(tmp2);
5621 break;
5622 case 30: /* Float VABS */
5623 gen_vfp_abs(0);
5624 break;
5625 case 31: /* Float VNEG */
5626 gen_vfp_neg(0);
5627 break;
5628 case 32: /* VSWP */
5629 tmp2 = neon_load_reg(rd, pass);
5630 neon_store_reg(rm, pass, tmp2);
5631 break;
5632 case 33: /* VTRN */
5633 tmp2 = neon_load_reg(rd, pass);
5634 switch (size) {
5635 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5636 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5637 case 2: abort();
5638 default: return 1;
5640 neon_store_reg(rm, pass, tmp2);
5641 break;
5642 case 56: /* Integer VRECPE */
5643 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5644 break;
5645 case 57: /* Integer VRSQRTE */
5646 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5647 break;
5648 case 58: /* Float VRECPE */
5649 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5650 break;
5651 case 59: /* Float VRSQRTE */
5652 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5653 break;
5654 case 60: /* VCVT.F32.S32 */
5655 gen_vfp_tosiz(0);
5656 break;
5657 case 61: /* VCVT.F32.U32 */
5658 gen_vfp_touiz(0);
5659 break;
5660 case 62: /* VCVT.S32.F32 */
5661 gen_vfp_sito(0);
5662 break;
5663 case 63: /* VCVT.U32.F32 */
5664 gen_vfp_uito(0);
5665 break;
5666 default:
5667 /* Reserved: 21, 29, 39-56 */
5668 return 1;
5670 if (op == 30 || op == 31 || op >= 58) {
5671 tcg_gen_st_f32(cpu_F0s, cpu_env,
5672 neon_reg_offset(rd, pass));
5673 } else {
5674 neon_store_reg(rd, pass, tmp);
5677 break;
5679 } else if ((insn & (1 << 10)) == 0) {
5680 /* VTBL, VTBX. */
5681 n = ((insn >> 5) & 0x18) + 8;
5682 if (insn & (1 << 6)) {
5683 tmp = neon_load_reg(rd, 0);
5684 } else {
5685 tmp = new_tmp();
5686 tcg_gen_movi_i32(tmp, 0);
5688 tmp2 = neon_load_reg(rm, 0);
5689 tmp4 = tcg_const_i32(rn);
5690 tmp5 = tcg_const_i32(n);
5691 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5692 dead_tmp(tmp);
5693 if (insn & (1 << 6)) {
5694 tmp = neon_load_reg(rd, 1);
5695 } else {
5696 tmp = new_tmp();
5697 tcg_gen_movi_i32(tmp, 0);
5699 tmp3 = neon_load_reg(rm, 1);
5700 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5701 tcg_temp_free_i32(tmp5);
5702 tcg_temp_free_i32(tmp4);
5703 neon_store_reg(rd, 0, tmp2);
5704 neon_store_reg(rd, 1, tmp3);
5705 dead_tmp(tmp);
5706 } else if ((insn & 0x380) == 0) {
5707 /* VDUP */
5708 if (insn & (1 << 19)) {
5709 tmp = neon_load_reg(rm, 1);
5710 } else {
5711 tmp = neon_load_reg(rm, 0);
5713 if (insn & (1 << 16)) {
5714 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5715 } else if (insn & (1 << 17)) {
5716 if ((insn >> 18) & 1)
5717 gen_neon_dup_high16(tmp);
5718 else
5719 gen_neon_dup_low16(tmp);
5721 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5722 tmp2 = new_tmp();
5723 tcg_gen_mov_i32(tmp2, tmp);
5724 neon_store_reg(rd, pass, tmp2);
5726 dead_tmp(tmp);
5727 } else {
5728 return 1;
5732 return 0;
5735 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5737 int crn = (insn >> 16) & 0xf;
5738 int crm = insn & 0xf;
5739 int op1 = (insn >> 21) & 7;
5740 int op2 = (insn >> 5) & 7;
5741 int rt = (insn >> 12) & 0xf;
5742 TCGv tmp;
5744 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5745 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5746 /* TEECR */
5747 if (IS_USER(s))
5748 return 1;
5749 tmp = load_cpu_field(teecr);
5750 store_reg(s, rt, tmp);
5751 return 0;
5753 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5754 /* TEEHBR */
5755 if (IS_USER(s) && (env->teecr & 1))
5756 return 1;
5757 tmp = load_cpu_field(teehbr);
5758 store_reg(s, rt, tmp);
5759 return 0;
5762 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5763 op1, crn, crm, op2);
5764 return 1;
5767 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5769 int crn = (insn >> 16) & 0xf;
5770 int crm = insn & 0xf;
5771 int op1 = (insn >> 21) & 7;
5772 int op2 = (insn >> 5) & 7;
5773 int rt = (insn >> 12) & 0xf;
5774 TCGv tmp;
5776 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5777 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5778 /* TEECR */
5779 if (IS_USER(s))
5780 return 1;
5781 tmp = load_reg(s, rt);
5782 gen_helper_set_teecr(cpu_env, tmp);
5783 dead_tmp(tmp);
5784 return 0;
5786 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5787 /* TEEHBR */
5788 if (IS_USER(s) && (env->teecr & 1))
5789 return 1;
5790 tmp = load_reg(s, rt);
5791 store_cpu_field(tmp, teehbr);
5792 return 0;
5795 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5796 op1, crn, crm, op2);
5797 return 1;
5800 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5802 int cpnum;
5804 cpnum = (insn >> 8) & 0xf;
5805 if (arm_feature(env, ARM_FEATURE_XSCALE)
5806 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5807 return 1;
5809 switch (cpnum) {
5810 case 0:
5811 case 1:
5812 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5813 return disas_iwmmxt_insn(env, s, insn);
5814 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5815 return disas_dsp_insn(env, s, insn);
5817 return 1;
5818 case 10:
5819 case 11:
5820 return disas_vfp_insn (env, s, insn);
5821 case 14:
5822 /* Coprocessors 7-15 are architecturally reserved by ARM.
5823 Unfortunately Intel decided to ignore this. */
5824 if (arm_feature(env, ARM_FEATURE_XSCALE))
5825 goto board;
5826 if (insn & (1 << 20))
5827 return disas_cp14_read(env, s, insn);
5828 else
5829 return disas_cp14_write(env, s, insn);
5830 case 15:
5831 return disas_cp15_insn (env, s, insn);
5832 default:
5833 board:
5834 /* Unknown coprocessor. See if the board has hooked it. */
5835 return disas_cp_insn (env, s, insn);
5840 /* Store a 64-bit value to a register pair. Clobbers val. */
5841 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5843 TCGv tmp;
5844 tmp = new_tmp();
5845 tcg_gen_trunc_i64_i32(tmp, val);
5846 store_reg(s, rlow, tmp);
5847 tmp = new_tmp();
5848 tcg_gen_shri_i64(val, val, 32);
5849 tcg_gen_trunc_i64_i32(tmp, val);
5850 store_reg(s, rhigh, tmp);
5853 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5854 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5856 TCGv_i64 tmp;
5857 TCGv tmp2;
5859 /* Load value and extend to 64 bits. */
5860 tmp = tcg_temp_new_i64();
5861 tmp2 = load_reg(s, rlow);
5862 tcg_gen_extu_i32_i64(tmp, tmp2);
5863 dead_tmp(tmp2);
5864 tcg_gen_add_i64(val, val, tmp);
5865 tcg_temp_free_i64(tmp);
5868 /* load and add a 64-bit value from a register pair. */
5869 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5871 TCGv_i64 tmp;
5872 TCGv tmpl;
5873 TCGv tmph;
5875 /* Load 64-bit value rd:rn. */
5876 tmpl = load_reg(s, rlow);
5877 tmph = load_reg(s, rhigh);
5878 tmp = tcg_temp_new_i64();
5879 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5880 dead_tmp(tmpl);
5881 dead_tmp(tmph);
5882 tcg_gen_add_i64(val, val, tmp);
5883 tcg_temp_free_i64(tmp);
5886 /* Set N and Z flags from a 64-bit value. */
5887 static void gen_logicq_cc(TCGv_i64 val)
5889 TCGv tmp = new_tmp();
5890 gen_helper_logicq_cc(tmp, val);
5891 gen_logic_CC(tmp);
5892 dead_tmp(tmp);
5895 /* Load/Store exclusive instructions are implemented by remembering
5896 the value/address loaded, and seeing if these are the same
5897 when the store is performed. This should be is sufficient to implement
5898 the architecturally mandated semantics, and avoids having to monitor
5899 regular stores.
5901 In system emulation mode only one CPU will be running at once, so
5902 this sequence is effectively atomic. In user emulation mode we
5903 throw an exception and handle the atomic operation elsewhere. */
5904 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
5905 TCGv addr, int size)
5907 TCGv tmp;
5909 switch (size) {
5910 case 0:
5911 tmp = gen_ld8u(addr, IS_USER(s));
5912 break;
5913 case 1:
5914 tmp = gen_ld16u(addr, IS_USER(s));
5915 break;
5916 case 2:
5917 case 3:
5918 tmp = gen_ld32(addr, IS_USER(s));
5919 break;
5920 default:
5921 abort();
5923 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
5924 store_reg(s, rt, tmp);
5925 if (size == 3) {
5926 tcg_gen_addi_i32(addr, addr, 4);
5927 tmp = gen_ld32(addr, IS_USER(s));
5928 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
5929 store_reg(s, rt2, tmp);
5931 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
5934 static void gen_clrex(DisasContext *s)
5936 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
5939 #ifdef CONFIG_USER_ONLY
5940 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5941 TCGv addr, int size)
5943 tcg_gen_mov_i32(cpu_exclusive_test, addr);
5944 tcg_gen_movi_i32(cpu_exclusive_info,
5945 size | (rd << 4) | (rt << 8) | (rt2 << 12));
5946 gen_set_condexec(s);
5947 gen_set_pc_im(s->pc - 4);
5948 gen_exception(EXCP_STREX);
5949 s->is_jmp = DISAS_JUMP;
5951 #else
5952 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5953 TCGv addr, int size)
5955 TCGv tmp;
5956 int done_label;
5957 int fail_label;
5959 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5960 [addr] = {Rt};
5961 {Rd} = 0;
5962 } else {
5963 {Rd} = 1;
5964 } */
5965 fail_label = gen_new_label();
5966 done_label = gen_new_label();
5967 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
5968 switch (size) {
5969 case 0:
5970 tmp = gen_ld8u(addr, IS_USER(s));
5971 break;
5972 case 1:
5973 tmp = gen_ld16u(addr, IS_USER(s));
5974 break;
5975 case 2:
5976 case 3:
5977 tmp = gen_ld32(addr, IS_USER(s));
5978 break;
5979 default:
5980 abort();
5982 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
5983 dead_tmp(tmp);
5984 if (size == 3) {
5985 TCGv tmp2 = new_tmp();
5986 tcg_gen_addi_i32(tmp2, addr, 4);
5987 tmp = gen_ld32(addr, IS_USER(s));
5988 dead_tmp(tmp2);
5989 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
5990 dead_tmp(tmp);
5992 tmp = load_reg(s, rt);
5993 switch (size) {
5994 case 0:
5995 gen_st8(tmp, addr, IS_USER(s));
5996 break;
5997 case 1:
5998 gen_st16(tmp, addr, IS_USER(s));
5999 break;
6000 case 2:
6001 case 3:
6002 gen_st32(tmp, addr, IS_USER(s));
6003 break;
6004 default:
6005 abort();
6007 if (size == 3) {
6008 tcg_gen_addi_i32(addr, addr, 4);
6009 tmp = load_reg(s, rt2);
6010 gen_st32(tmp, addr, IS_USER(s));
6012 tcg_gen_movi_i32(cpu_R[rd], 0);
6013 tcg_gen_br(done_label);
6014 gen_set_label(fail_label);
6015 tcg_gen_movi_i32(cpu_R[rd], 1);
6016 gen_set_label(done_label);
6017 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6019 #endif
6021 static void disas_arm_insn(CPUState * env, DisasContext *s)
6023 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6024 TCGv tmp;
6025 TCGv tmp2;
6026 TCGv tmp3;
6027 TCGv addr;
6028 TCGv_i64 tmp64;
6030 insn = ldl_code(s->pc);
6031 s->pc += 4;
6033 /* M variants do not implement ARM mode. */
6034 if (IS_M(env))
6035 goto illegal_op;
6036 cond = insn >> 28;
6037 if (cond == 0xf){
6038 /* Unconditional instructions. */
6039 if (((insn >> 25) & 7) == 1) {
6040 /* NEON Data processing. */
6041 if (!arm_feature(env, ARM_FEATURE_NEON))
6042 goto illegal_op;
6044 if (disas_neon_data_insn(env, s, insn))
6045 goto illegal_op;
6046 return;
6048 if ((insn & 0x0f100000) == 0x04000000) {
6049 /* NEON load/store. */
6050 if (!arm_feature(env, ARM_FEATURE_NEON))
6051 goto illegal_op;
6053 if (disas_neon_ls_insn(env, s, insn))
6054 goto illegal_op;
6055 return;
6057 if ((insn & 0x0d70f000) == 0x0550f000)
6058 return; /* PLD */
6059 else if ((insn & 0x0ffffdff) == 0x01010000) {
6060 ARCH(6);
6061 /* setend */
6062 if (insn & (1 << 9)) {
6063 /* BE8 mode not implemented. */
6064 goto illegal_op;
6066 return;
6067 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6068 switch ((insn >> 4) & 0xf) {
6069 case 1: /* clrex */
6070 ARCH(6K);
6071 gen_clrex(s);
6072 return;
6073 case 4: /* dsb */
6074 case 5: /* dmb */
6075 case 6: /* isb */
6076 ARCH(7);
6077 /* We don't emulate caches so these are a no-op. */
6078 return;
6079 default:
6080 goto illegal_op;
6082 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6083 /* srs */
6084 int32_t offset;
6085 if (IS_USER(s))
6086 goto illegal_op;
6087 ARCH(6);
6088 op1 = (insn & 0x1f);
6089 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6090 addr = load_reg(s, 13);
6091 } else {
6092 addr = new_tmp();
6093 tmp = tcg_const_i32(op1);
6094 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6095 tcg_temp_free_i32(tmp);
6097 i = (insn >> 23) & 3;
6098 switch (i) {
6099 case 0: offset = -4; break; /* DA */
6100 case 1: offset = 0; break; /* IA */
6101 case 2: offset = -8; break; /* DB */
6102 case 3: offset = 4; break; /* IB */
6103 default: abort();
6105 if (offset)
6106 tcg_gen_addi_i32(addr, addr, offset);
6107 tmp = load_reg(s, 14);
6108 gen_st32(tmp, addr, 0);
6109 tmp = load_cpu_field(spsr);
6110 tcg_gen_addi_i32(addr, addr, 4);
6111 gen_st32(tmp, addr, 0);
6112 if (insn & (1 << 21)) {
6113 /* Base writeback. */
6114 switch (i) {
6115 case 0: offset = -8; break;
6116 case 1: offset = 4; break;
6117 case 2: offset = -4; break;
6118 case 3: offset = 0; break;
6119 default: abort();
6121 if (offset)
6122 tcg_gen_addi_i32(addr, addr, offset);
6123 if (op1 == (env->uncached_cpsr & CPSR_M)) {
6124 store_reg(s, 13, addr);
6125 } else {
6126 tmp = tcg_const_i32(op1);
6127 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6128 tcg_temp_free_i32(tmp);
6129 dead_tmp(addr);
6131 } else {
6132 dead_tmp(addr);
6134 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
6135 /* rfe */
6136 int32_t offset;
6137 if (IS_USER(s))
6138 goto illegal_op;
6139 ARCH(6);
6140 rn = (insn >> 16) & 0xf;
6141 addr = load_reg(s, rn);
6142 i = (insn >> 23) & 3;
6143 switch (i) {
6144 case 0: offset = -4; break; /* DA */
6145 case 1: offset = 0; break; /* IA */
6146 case 2: offset = -8; break; /* DB */
6147 case 3: offset = 4; break; /* IB */
6148 default: abort();
6150 if (offset)
6151 tcg_gen_addi_i32(addr, addr, offset);
6152 /* Load PC into tmp and CPSR into tmp2. */
6153 tmp = gen_ld32(addr, 0);
6154 tcg_gen_addi_i32(addr, addr, 4);
6155 tmp2 = gen_ld32(addr, 0);
6156 if (insn & (1 << 21)) {
6157 /* Base writeback. */
6158 switch (i) {
6159 case 0: offset = -8; break;
6160 case 1: offset = 4; break;
6161 case 2: offset = -4; break;
6162 case 3: offset = 0; break;
6163 default: abort();
6165 if (offset)
6166 tcg_gen_addi_i32(addr, addr, offset);
6167 store_reg(s, rn, addr);
6168 } else {
6169 dead_tmp(addr);
6171 gen_rfe(s, tmp, tmp2);
6172 return;
6173 } else if ((insn & 0x0e000000) == 0x0a000000) {
6174 /* branch link and change to thumb (blx <offset>) */
6175 int32_t offset;
6177 val = (uint32_t)s->pc;
6178 tmp = new_tmp();
6179 tcg_gen_movi_i32(tmp, val);
6180 store_reg(s, 14, tmp);
6181 /* Sign-extend the 24-bit offset */
6182 offset = (((int32_t)insn) << 8) >> 8;
6183 /* offset * 4 + bit24 * 2 + (thumb bit) */
6184 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6185 /* pipeline offset */
6186 val += 4;
6187 gen_bx_im(s, val);
6188 return;
6189 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6190 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6191 /* iWMMXt register transfer. */
6192 if (env->cp15.c15_cpar & (1 << 1))
6193 if (!disas_iwmmxt_insn(env, s, insn))
6194 return;
6196 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6197 /* Coprocessor double register transfer. */
6198 } else if ((insn & 0x0f000010) == 0x0e000010) {
6199 /* Additional coprocessor register transfer. */
6200 } else if ((insn & 0x0ff10020) == 0x01000000) {
6201 uint32_t mask;
6202 uint32_t val;
6203 /* cps (privileged) */
6204 if (IS_USER(s))
6205 return;
6206 mask = val = 0;
6207 if (insn & (1 << 19)) {
6208 if (insn & (1 << 8))
6209 mask |= CPSR_A;
6210 if (insn & (1 << 7))
6211 mask |= CPSR_I;
6212 if (insn & (1 << 6))
6213 mask |= CPSR_F;
6214 if (insn & (1 << 18))
6215 val |= mask;
6217 if (insn & (1 << 17)) {
6218 mask |= CPSR_M;
6219 val |= (insn & 0x1f);
6221 if (mask) {
6222 gen_set_psr_im(s, mask, 0, val);
6224 return;
6226 goto illegal_op;
6228 if (cond != 0xe) {
6229 /* if not always execute, we generate a conditional jump to
6230 next instruction */
6231 s->condlabel = gen_new_label();
6232 gen_test_cc(cond ^ 1, s->condlabel);
6233 s->condjmp = 1;
6235 if ((insn & 0x0f900000) == 0x03000000) {
6236 if ((insn & (1 << 21)) == 0) {
6237 ARCH(6T2);
6238 rd = (insn >> 12) & 0xf;
6239 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6240 if ((insn & (1 << 22)) == 0) {
6241 /* MOVW */
6242 tmp = new_tmp();
6243 tcg_gen_movi_i32(tmp, val);
6244 } else {
6245 /* MOVT */
6246 tmp = load_reg(s, rd);
6247 tcg_gen_ext16u_i32(tmp, tmp);
6248 tcg_gen_ori_i32(tmp, tmp, val << 16);
6250 store_reg(s, rd, tmp);
6251 } else {
6252 if (((insn >> 12) & 0xf) != 0xf)
6253 goto illegal_op;
6254 if (((insn >> 16) & 0xf) == 0) {
6255 gen_nop_hint(s, insn & 0xff);
6256 } else {
6257 /* CPSR = immediate */
6258 val = insn & 0xff;
6259 shift = ((insn >> 8) & 0xf) * 2;
6260 if (shift)
6261 val = (val >> shift) | (val << (32 - shift));
6262 i = ((insn & (1 << 22)) != 0);
6263 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6264 goto illegal_op;
6267 } else if ((insn & 0x0f900000) == 0x01000000
6268 && (insn & 0x00000090) != 0x00000090) {
6269 /* miscellaneous instructions */
6270 op1 = (insn >> 21) & 3;
6271 sh = (insn >> 4) & 0xf;
6272 rm = insn & 0xf;
6273 switch (sh) {
6274 case 0x0: /* move program status register */
6275 if (op1 & 1) {
6276 /* PSR = reg */
6277 tmp = load_reg(s, rm);
6278 i = ((op1 & 2) != 0);
6279 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6280 goto illegal_op;
6281 } else {
6282 /* reg = PSR */
6283 rd = (insn >> 12) & 0xf;
6284 if (op1 & 2) {
6285 if (IS_USER(s))
6286 goto illegal_op;
6287 tmp = load_cpu_field(spsr);
6288 } else {
6289 tmp = new_tmp();
6290 gen_helper_cpsr_read(tmp);
6292 store_reg(s, rd, tmp);
6294 break;
6295 case 0x1:
6296 if (op1 == 1) {
6297 /* branch/exchange thumb (bx). */
6298 tmp = load_reg(s, rm);
6299 gen_bx(s, tmp);
6300 } else if (op1 == 3) {
6301 /* clz */
6302 rd = (insn >> 12) & 0xf;
6303 tmp = load_reg(s, rm);
6304 gen_helper_clz(tmp, tmp);
6305 store_reg(s, rd, tmp);
6306 } else {
6307 goto illegal_op;
6309 break;
6310 case 0x2:
6311 if (op1 == 1) {
6312 ARCH(5J); /* bxj */
6313 /* Trivial implementation equivalent to bx. */
6314 tmp = load_reg(s, rm);
6315 gen_bx(s, tmp);
6316 } else {
6317 goto illegal_op;
6319 break;
6320 case 0x3:
6321 if (op1 != 1)
6322 goto illegal_op;
6324 /* branch link/exchange thumb (blx) */
6325 tmp = load_reg(s, rm);
6326 tmp2 = new_tmp();
6327 tcg_gen_movi_i32(tmp2, s->pc);
6328 store_reg(s, 14, tmp2);
6329 gen_bx(s, tmp);
6330 break;
6331 case 0x5: /* saturating add/subtract */
6332 rd = (insn >> 12) & 0xf;
6333 rn = (insn >> 16) & 0xf;
6334 tmp = load_reg(s, rm);
6335 tmp2 = load_reg(s, rn);
6336 if (op1 & 2)
6337 gen_helper_double_saturate(tmp2, tmp2);
6338 if (op1 & 1)
6339 gen_helper_sub_saturate(tmp, tmp, tmp2);
6340 else
6341 gen_helper_add_saturate(tmp, tmp, tmp2);
6342 dead_tmp(tmp2);
6343 store_reg(s, rd, tmp);
6344 break;
6345 case 7: /* bkpt */
6346 gen_set_condexec(s);
6347 gen_set_pc_im(s->pc - 4);
6348 gen_exception(EXCP_BKPT);
6349 s->is_jmp = DISAS_JUMP;
6350 break;
6351 case 0x8: /* signed multiply */
6352 case 0xa:
6353 case 0xc:
6354 case 0xe:
6355 rs = (insn >> 8) & 0xf;
6356 rn = (insn >> 12) & 0xf;
6357 rd = (insn >> 16) & 0xf;
6358 if (op1 == 1) {
6359 /* (32 * 16) >> 16 */
6360 tmp = load_reg(s, rm);
6361 tmp2 = load_reg(s, rs);
6362 if (sh & 4)
6363 tcg_gen_sari_i32(tmp2, tmp2, 16);
6364 else
6365 gen_sxth(tmp2);
6366 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6367 tcg_gen_shri_i64(tmp64, tmp64, 16);
6368 tmp = new_tmp();
6369 tcg_gen_trunc_i64_i32(tmp, tmp64);
6370 tcg_temp_free_i64(tmp64);
6371 if ((sh & 2) == 0) {
6372 tmp2 = load_reg(s, rn);
6373 gen_helper_add_setq(tmp, tmp, tmp2);
6374 dead_tmp(tmp2);
6376 store_reg(s, rd, tmp);
6377 } else {
6378 /* 16 * 16 */
6379 tmp = load_reg(s, rm);
6380 tmp2 = load_reg(s, rs);
6381 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6382 dead_tmp(tmp2);
6383 if (op1 == 2) {
6384 tmp64 = tcg_temp_new_i64();
6385 tcg_gen_ext_i32_i64(tmp64, tmp);
6386 dead_tmp(tmp);
6387 gen_addq(s, tmp64, rn, rd);
6388 gen_storeq_reg(s, rn, rd, tmp64);
6389 tcg_temp_free_i64(tmp64);
6390 } else {
6391 if (op1 == 0) {
6392 tmp2 = load_reg(s, rn);
6393 gen_helper_add_setq(tmp, tmp, tmp2);
6394 dead_tmp(tmp2);
6396 store_reg(s, rd, tmp);
6399 break;
6400 default:
6401 goto illegal_op;
6403 } else if (((insn & 0x0e000000) == 0 &&
6404 (insn & 0x00000090) != 0x90) ||
6405 ((insn & 0x0e000000) == (1 << 25))) {
6406 int set_cc, logic_cc, shiftop;
6408 op1 = (insn >> 21) & 0xf;
6409 set_cc = (insn >> 20) & 1;
6410 logic_cc = table_logic_cc[op1] & set_cc;
6412 /* data processing instruction */
6413 if (insn & (1 << 25)) {
6414 /* immediate operand */
6415 val = insn & 0xff;
6416 shift = ((insn >> 8) & 0xf) * 2;
6417 if (shift) {
6418 val = (val >> shift) | (val << (32 - shift));
6420 tmp2 = new_tmp();
6421 tcg_gen_movi_i32(tmp2, val);
6422 if (logic_cc && shift) {
6423 gen_set_CF_bit31(tmp2);
6425 } else {
6426 /* register */
6427 rm = (insn) & 0xf;
6428 tmp2 = load_reg(s, rm);
6429 shiftop = (insn >> 5) & 3;
6430 if (!(insn & (1 << 4))) {
6431 shift = (insn >> 7) & 0x1f;
6432 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6433 } else {
6434 rs = (insn >> 8) & 0xf;
6435 tmp = load_reg(s, rs);
6436 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6439 if (op1 != 0x0f && op1 != 0x0d) {
6440 rn = (insn >> 16) & 0xf;
6441 tmp = load_reg(s, rn);
6442 } else {
6443 TCGV_UNUSED(tmp);
6445 rd = (insn >> 12) & 0xf;
6446 switch(op1) {
6447 case 0x00:
6448 tcg_gen_and_i32(tmp, tmp, tmp2);
6449 if (logic_cc) {
6450 gen_logic_CC(tmp);
6452 store_reg_bx(env, s, rd, tmp);
6453 break;
6454 case 0x01:
6455 tcg_gen_xor_i32(tmp, tmp, tmp2);
6456 if (logic_cc) {
6457 gen_logic_CC(tmp);
6459 store_reg_bx(env, s, rd, tmp);
6460 break;
6461 case 0x02:
6462 if (set_cc && rd == 15) {
6463 /* SUBS r15, ... is used for exception return. */
6464 if (IS_USER(s)) {
6465 goto illegal_op;
6467 gen_helper_sub_cc(tmp, tmp, tmp2);
6468 gen_exception_return(s, tmp);
6469 } else {
6470 if (set_cc) {
6471 gen_helper_sub_cc(tmp, tmp, tmp2);
6472 } else {
6473 tcg_gen_sub_i32(tmp, tmp, tmp2);
6475 store_reg_bx(env, s, rd, tmp);
6477 break;
6478 case 0x03:
6479 if (set_cc) {
6480 gen_helper_sub_cc(tmp, tmp2, tmp);
6481 } else {
6482 tcg_gen_sub_i32(tmp, tmp2, tmp);
6484 store_reg_bx(env, s, rd, tmp);
6485 break;
6486 case 0x04:
6487 if (set_cc) {
6488 gen_helper_add_cc(tmp, tmp, tmp2);
6489 } else {
6490 tcg_gen_add_i32(tmp, tmp, tmp2);
6492 store_reg_bx(env, s, rd, tmp);
6493 break;
6494 case 0x05:
6495 if (set_cc) {
6496 gen_helper_adc_cc(tmp, tmp, tmp2);
6497 } else {
6498 gen_add_carry(tmp, tmp, tmp2);
6500 store_reg_bx(env, s, rd, tmp);
6501 break;
6502 case 0x06:
6503 if (set_cc) {
6504 gen_helper_sbc_cc(tmp, tmp, tmp2);
6505 } else {
6506 gen_sub_carry(tmp, tmp, tmp2);
6508 store_reg_bx(env, s, rd, tmp);
6509 break;
6510 case 0x07:
6511 if (set_cc) {
6512 gen_helper_sbc_cc(tmp, tmp2, tmp);
6513 } else {
6514 gen_sub_carry(tmp, tmp2, tmp);
6516 store_reg_bx(env, s, rd, tmp);
6517 break;
6518 case 0x08:
6519 if (set_cc) {
6520 tcg_gen_and_i32(tmp, tmp, tmp2);
6521 gen_logic_CC(tmp);
6523 dead_tmp(tmp);
6524 break;
6525 case 0x09:
6526 if (set_cc) {
6527 tcg_gen_xor_i32(tmp, tmp, tmp2);
6528 gen_logic_CC(tmp);
6530 dead_tmp(tmp);
6531 break;
6532 case 0x0a:
6533 if (set_cc) {
6534 gen_helper_sub_cc(tmp, tmp, tmp2);
6536 dead_tmp(tmp);
6537 break;
6538 case 0x0b:
6539 if (set_cc) {
6540 gen_helper_add_cc(tmp, tmp, tmp2);
6542 dead_tmp(tmp);
6543 break;
6544 case 0x0c:
6545 tcg_gen_or_i32(tmp, tmp, tmp2);
6546 if (logic_cc) {
6547 gen_logic_CC(tmp);
6549 store_reg_bx(env, s, rd, tmp);
6550 break;
6551 case 0x0d:
6552 if (logic_cc && rd == 15) {
6553 /* MOVS r15, ... is used for exception return. */
6554 if (IS_USER(s)) {
6555 goto illegal_op;
6557 gen_exception_return(s, tmp2);
6558 } else {
6559 if (logic_cc) {
6560 gen_logic_CC(tmp2);
6562 store_reg_bx(env, s, rd, tmp2);
6564 break;
6565 case 0x0e:
6566 tcg_gen_andc_i32(tmp, tmp, tmp2);
6567 if (logic_cc) {
6568 gen_logic_CC(tmp);
6570 store_reg_bx(env, s, rd, tmp);
6571 break;
6572 default:
6573 case 0x0f:
6574 tcg_gen_not_i32(tmp2, tmp2);
6575 if (logic_cc) {
6576 gen_logic_CC(tmp2);
6578 store_reg_bx(env, s, rd, tmp2);
6579 break;
6581 if (op1 != 0x0f && op1 != 0x0d) {
6582 dead_tmp(tmp2);
6584 } else {
6585 /* other instructions */
6586 op1 = (insn >> 24) & 0xf;
6587 switch(op1) {
6588 case 0x0:
6589 case 0x1:
6590 /* multiplies, extra load/stores */
6591 sh = (insn >> 5) & 3;
6592 if (sh == 0) {
6593 if (op1 == 0x0) {
6594 rd = (insn >> 16) & 0xf;
6595 rn = (insn >> 12) & 0xf;
6596 rs = (insn >> 8) & 0xf;
6597 rm = (insn) & 0xf;
6598 op1 = (insn >> 20) & 0xf;
6599 switch (op1) {
6600 case 0: case 1: case 2: case 3: case 6:
6601 /* 32 bit mul */
6602 tmp = load_reg(s, rs);
6603 tmp2 = load_reg(s, rm);
6604 tcg_gen_mul_i32(tmp, tmp, tmp2);
6605 dead_tmp(tmp2);
6606 if (insn & (1 << 22)) {
6607 /* Subtract (mls) */
6608 ARCH(6T2);
6609 tmp2 = load_reg(s, rn);
6610 tcg_gen_sub_i32(tmp, tmp2, tmp);
6611 dead_tmp(tmp2);
6612 } else if (insn & (1 << 21)) {
6613 /* Add */
6614 tmp2 = load_reg(s, rn);
6615 tcg_gen_add_i32(tmp, tmp, tmp2);
6616 dead_tmp(tmp2);
6618 if (insn & (1 << 20))
6619 gen_logic_CC(tmp);
6620 store_reg(s, rd, tmp);
6621 break;
6622 default:
6623 /* 64 bit mul */
6624 tmp = load_reg(s, rs);
6625 tmp2 = load_reg(s, rm);
6626 if (insn & (1 << 22))
6627 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6628 else
6629 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6630 if (insn & (1 << 21)) /* mult accumulate */
6631 gen_addq(s, tmp64, rn, rd);
6632 if (!(insn & (1 << 23))) { /* double accumulate */
6633 ARCH(6);
6634 gen_addq_lo(s, tmp64, rn);
6635 gen_addq_lo(s, tmp64, rd);
6637 if (insn & (1 << 20))
6638 gen_logicq_cc(tmp64);
6639 gen_storeq_reg(s, rn, rd, tmp64);
6640 tcg_temp_free_i64(tmp64);
6641 break;
6643 } else {
6644 rn = (insn >> 16) & 0xf;
6645 rd = (insn >> 12) & 0xf;
6646 if (insn & (1 << 23)) {
6647 /* load/store exclusive */
6648 op1 = (insn >> 21) & 0x3;
6649 if (op1)
6650 ARCH(6K);
6651 else
6652 ARCH(6);
6653 addr = tcg_temp_local_new_i32();
6654 load_reg_var(s, addr, rn);
6655 if (insn & (1 << 20)) {
6656 switch (op1) {
6657 case 0: /* ldrex */
6658 gen_load_exclusive(s, rd, 15, addr, 2);
6659 break;
6660 case 1: /* ldrexd */
6661 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6662 break;
6663 case 2: /* ldrexb */
6664 gen_load_exclusive(s, rd, 15, addr, 0);
6665 break;
6666 case 3: /* ldrexh */
6667 gen_load_exclusive(s, rd, 15, addr, 1);
6668 break;
6669 default:
6670 abort();
6672 } else {
6673 rm = insn & 0xf;
6674 switch (op1) {
6675 case 0: /* strex */
6676 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6677 break;
6678 case 1: /* strexd */
6679 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6680 break;
6681 case 2: /* strexb */
6682 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6683 break;
6684 case 3: /* strexh */
6685 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6686 break;
6687 default:
6688 abort();
6691 tcg_temp_free(addr);
6692 } else {
6693 /* SWP instruction */
6694 rm = (insn) & 0xf;
6696 /* ??? This is not really atomic. However we know
6697 we never have multiple CPUs running in parallel,
6698 so it is good enough. */
6699 addr = load_reg(s, rn);
6700 tmp = load_reg(s, rm);
6701 if (insn & (1 << 22)) {
6702 tmp2 = gen_ld8u(addr, IS_USER(s));
6703 gen_st8(tmp, addr, IS_USER(s));
6704 } else {
6705 tmp2 = gen_ld32(addr, IS_USER(s));
6706 gen_st32(tmp, addr, IS_USER(s));
6708 dead_tmp(addr);
6709 store_reg(s, rd, tmp2);
6712 } else {
6713 int address_offset;
6714 int load;
6715 /* Misc load/store */
6716 rn = (insn >> 16) & 0xf;
6717 rd = (insn >> 12) & 0xf;
6718 addr = load_reg(s, rn);
6719 if (insn & (1 << 24))
6720 gen_add_datah_offset(s, insn, 0, addr);
6721 address_offset = 0;
6722 if (insn & (1 << 20)) {
6723 /* load */
6724 switch(sh) {
6725 case 1:
6726 tmp = gen_ld16u(addr, IS_USER(s));
6727 break;
6728 case 2:
6729 tmp = gen_ld8s(addr, IS_USER(s));
6730 break;
6731 default:
6732 case 3:
6733 tmp = gen_ld16s(addr, IS_USER(s));
6734 break;
6736 load = 1;
6737 } else if (sh & 2) {
6738 /* doubleword */
6739 if (sh & 1) {
6740 /* store */
6741 tmp = load_reg(s, rd);
6742 gen_st32(tmp, addr, IS_USER(s));
6743 tcg_gen_addi_i32(addr, addr, 4);
6744 tmp = load_reg(s, rd + 1);
6745 gen_st32(tmp, addr, IS_USER(s));
6746 load = 0;
6747 } else {
6748 /* load */
6749 tmp = gen_ld32(addr, IS_USER(s));
6750 store_reg(s, rd, tmp);
6751 tcg_gen_addi_i32(addr, addr, 4);
6752 tmp = gen_ld32(addr, IS_USER(s));
6753 rd++;
6754 load = 1;
6756 address_offset = -4;
6757 } else {
6758 /* store */
6759 tmp = load_reg(s, rd);
6760 gen_st16(tmp, addr, IS_USER(s));
6761 load = 0;
6763 /* Perform base writeback before the loaded value to
6764 ensure correct behavior with overlapping index registers.
6765 ldrd with base writeback is is undefined if the
6766 destination and index registers overlap. */
6767 if (!(insn & (1 << 24))) {
6768 gen_add_datah_offset(s, insn, address_offset, addr);
6769 store_reg(s, rn, addr);
6770 } else if (insn & (1 << 21)) {
6771 if (address_offset)
6772 tcg_gen_addi_i32(addr, addr, address_offset);
6773 store_reg(s, rn, addr);
6774 } else {
6775 dead_tmp(addr);
6777 if (load) {
6778 /* Complete the load. */
6779 store_reg(s, rd, tmp);
6782 break;
6783 case 0x4:
6784 case 0x5:
6785 goto do_ldst;
6786 case 0x6:
6787 case 0x7:
6788 if (insn & (1 << 4)) {
6789 ARCH(6);
6790 /* Armv6 Media instructions. */
6791 rm = insn & 0xf;
6792 rn = (insn >> 16) & 0xf;
6793 rd = (insn >> 12) & 0xf;
6794 rs = (insn >> 8) & 0xf;
6795 switch ((insn >> 23) & 3) {
6796 case 0: /* Parallel add/subtract. */
6797 op1 = (insn >> 20) & 7;
6798 tmp = load_reg(s, rn);
6799 tmp2 = load_reg(s, rm);
6800 sh = (insn >> 5) & 7;
6801 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6802 goto illegal_op;
6803 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6804 dead_tmp(tmp2);
6805 store_reg(s, rd, tmp);
6806 break;
6807 case 1:
6808 if ((insn & 0x00700020) == 0) {
6809 /* Halfword pack. */
6810 tmp = load_reg(s, rn);
6811 tmp2 = load_reg(s, rm);
6812 shift = (insn >> 7) & 0x1f;
6813 if (insn & (1 << 6)) {
6814 /* pkhtb */
6815 if (shift == 0)
6816 shift = 31;
6817 tcg_gen_sari_i32(tmp2, tmp2, shift);
6818 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6819 tcg_gen_ext16u_i32(tmp2, tmp2);
6820 } else {
6821 /* pkhbt */
6822 if (shift)
6823 tcg_gen_shli_i32(tmp2, tmp2, shift);
6824 tcg_gen_ext16u_i32(tmp, tmp);
6825 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6827 tcg_gen_or_i32(tmp, tmp, tmp2);
6828 dead_tmp(tmp2);
6829 store_reg(s, rd, tmp);
6830 } else if ((insn & 0x00200020) == 0x00200000) {
6831 /* [us]sat */
6832 tmp = load_reg(s, rm);
6833 shift = (insn >> 7) & 0x1f;
6834 if (insn & (1 << 6)) {
6835 if (shift == 0)
6836 shift = 31;
6837 tcg_gen_sari_i32(tmp, tmp, shift);
6838 } else {
6839 tcg_gen_shli_i32(tmp, tmp, shift);
6841 sh = (insn >> 16) & 0x1f;
6842 if (sh != 0) {
6843 tmp2 = tcg_const_i32(sh);
6844 if (insn & (1 << 22))
6845 gen_helper_usat(tmp, tmp, tmp2);
6846 else
6847 gen_helper_ssat(tmp, tmp, tmp2);
6848 tcg_temp_free_i32(tmp2);
6850 store_reg(s, rd, tmp);
6851 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6852 /* [us]sat16 */
6853 tmp = load_reg(s, rm);
6854 sh = (insn >> 16) & 0x1f;
6855 if (sh != 0) {
6856 tmp2 = tcg_const_i32(sh);
6857 if (insn & (1 << 22))
6858 gen_helper_usat16(tmp, tmp, tmp2);
6859 else
6860 gen_helper_ssat16(tmp, tmp, tmp2);
6861 tcg_temp_free_i32(tmp2);
6863 store_reg(s, rd, tmp);
6864 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6865 /* Select bytes. */
6866 tmp = load_reg(s, rn);
6867 tmp2 = load_reg(s, rm);
6868 tmp3 = new_tmp();
6869 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6870 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6871 dead_tmp(tmp3);
6872 dead_tmp(tmp2);
6873 store_reg(s, rd, tmp);
6874 } else if ((insn & 0x000003e0) == 0x00000060) {
6875 tmp = load_reg(s, rm);
6876 shift = (insn >> 10) & 3;
6877 /* ??? In many cases it's not neccessary to do a
6878 rotate, a shift is sufficient. */
6879 if (shift != 0)
6880 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6881 op1 = (insn >> 20) & 7;
6882 switch (op1) {
6883 case 0: gen_sxtb16(tmp); break;
6884 case 2: gen_sxtb(tmp); break;
6885 case 3: gen_sxth(tmp); break;
6886 case 4: gen_uxtb16(tmp); break;
6887 case 6: gen_uxtb(tmp); break;
6888 case 7: gen_uxth(tmp); break;
6889 default: goto illegal_op;
6891 if (rn != 15) {
6892 tmp2 = load_reg(s, rn);
6893 if ((op1 & 3) == 0) {
6894 gen_add16(tmp, tmp2);
6895 } else {
6896 tcg_gen_add_i32(tmp, tmp, tmp2);
6897 dead_tmp(tmp2);
6900 store_reg(s, rd, tmp);
6901 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6902 /* rev */
6903 tmp = load_reg(s, rm);
6904 if (insn & (1 << 22)) {
6905 if (insn & (1 << 7)) {
6906 gen_revsh(tmp);
6907 } else {
6908 ARCH(6T2);
6909 gen_helper_rbit(tmp, tmp);
6911 } else {
6912 if (insn & (1 << 7))
6913 gen_rev16(tmp);
6914 else
6915 tcg_gen_bswap32_i32(tmp, tmp);
6917 store_reg(s, rd, tmp);
6918 } else {
6919 goto illegal_op;
6921 break;
6922 case 2: /* Multiplies (Type 3). */
6923 tmp = load_reg(s, rm);
6924 tmp2 = load_reg(s, rs);
6925 if (insn & (1 << 20)) {
6926 /* Signed multiply most significant [accumulate]. */
6927 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6928 if (insn & (1 << 5))
6929 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6930 tcg_gen_shri_i64(tmp64, tmp64, 32);
6931 tmp = new_tmp();
6932 tcg_gen_trunc_i64_i32(tmp, tmp64);
6933 tcg_temp_free_i64(tmp64);
6934 if (rd != 15) {
6935 tmp2 = load_reg(s, rd);
6936 if (insn & (1 << 6)) {
6937 tcg_gen_sub_i32(tmp, tmp, tmp2);
6938 } else {
6939 tcg_gen_add_i32(tmp, tmp, tmp2);
6941 dead_tmp(tmp2);
6943 store_reg(s, rn, tmp);
6944 } else {
6945 if (insn & (1 << 5))
6946 gen_swap_half(tmp2);
6947 gen_smul_dual(tmp, tmp2);
6948 /* This addition cannot overflow. */
6949 if (insn & (1 << 6)) {
6950 tcg_gen_sub_i32(tmp, tmp, tmp2);
6951 } else {
6952 tcg_gen_add_i32(tmp, tmp, tmp2);
6954 dead_tmp(tmp2);
6955 if (insn & (1 << 22)) {
6956 /* smlald, smlsld */
6957 tmp64 = tcg_temp_new_i64();
6958 tcg_gen_ext_i32_i64(tmp64, tmp);
6959 dead_tmp(tmp);
6960 gen_addq(s, tmp64, rd, rn);
6961 gen_storeq_reg(s, rd, rn, tmp64);
6962 tcg_temp_free_i64(tmp64);
6963 } else {
6964 /* smuad, smusd, smlad, smlsd */
6965 if (rd != 15)
6967 tmp2 = load_reg(s, rd);
6968 gen_helper_add_setq(tmp, tmp, tmp2);
6969 dead_tmp(tmp2);
6971 store_reg(s, rn, tmp);
6974 break;
6975 case 3:
6976 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6977 switch (op1) {
6978 case 0: /* Unsigned sum of absolute differences. */
6979 ARCH(6);
6980 tmp = load_reg(s, rm);
6981 tmp2 = load_reg(s, rs);
6982 gen_helper_usad8(tmp, tmp, tmp2);
6983 dead_tmp(tmp2);
6984 if (rd != 15) {
6985 tmp2 = load_reg(s, rd);
6986 tcg_gen_add_i32(tmp, tmp, tmp2);
6987 dead_tmp(tmp2);
6989 store_reg(s, rn, tmp);
6990 break;
6991 case 0x20: case 0x24: case 0x28: case 0x2c:
6992 /* Bitfield insert/clear. */
6993 ARCH(6T2);
6994 shift = (insn >> 7) & 0x1f;
6995 i = (insn >> 16) & 0x1f;
6996 i = i + 1 - shift;
6997 if (rm == 15) {
6998 tmp = new_tmp();
6999 tcg_gen_movi_i32(tmp, 0);
7000 } else {
7001 tmp = load_reg(s, rm);
7003 if (i != 32) {
7004 tmp2 = load_reg(s, rd);
7005 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7006 dead_tmp(tmp2);
7008 store_reg(s, rd, tmp);
7009 break;
7010 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7011 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7012 ARCH(6T2);
7013 tmp = load_reg(s, rm);
7014 shift = (insn >> 7) & 0x1f;
7015 i = ((insn >> 16) & 0x1f) + 1;
7016 if (shift + i > 32)
7017 goto illegal_op;
7018 if (i < 32) {
7019 if (op1 & 0x20) {
7020 gen_ubfx(tmp, shift, (1u << i) - 1);
7021 } else {
7022 gen_sbfx(tmp, shift, i);
7025 store_reg(s, rd, tmp);
7026 break;
7027 default:
7028 goto illegal_op;
7030 break;
7032 break;
7034 do_ldst:
7035 /* Check for undefined extension instructions
7036 * per the ARM Bible IE:
7037 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7039 sh = (0xf << 20) | (0xf << 4);
7040 if (op1 == 0x7 && ((insn & sh) == sh))
7042 goto illegal_op;
7044 /* load/store byte/word */
7045 rn = (insn >> 16) & 0xf;
7046 rd = (insn >> 12) & 0xf;
7047 tmp2 = load_reg(s, rn);
7048 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7049 if (insn & (1 << 24))
7050 gen_add_data_offset(s, insn, tmp2);
7051 if (insn & (1 << 20)) {
7052 /* load */
7053 if (insn & (1 << 22)) {
7054 tmp = gen_ld8u(tmp2, i);
7055 } else {
7056 tmp = gen_ld32(tmp2, i);
7058 } else {
7059 /* store */
7060 tmp = load_reg(s, rd);
7061 if (insn & (1 << 22))
7062 gen_st8(tmp, tmp2, i);
7063 else
7064 gen_st32(tmp, tmp2, i);
7066 if (!(insn & (1 << 24))) {
7067 gen_add_data_offset(s, insn, tmp2);
7068 store_reg(s, rn, tmp2);
7069 } else if (insn & (1 << 21)) {
7070 store_reg(s, rn, tmp2);
7071 } else {
7072 dead_tmp(tmp2);
7074 if (insn & (1 << 20)) {
7075 /* Complete the load. */
7076 if (rd == 15)
7077 gen_bx(s, tmp);
7078 else
7079 store_reg(s, rd, tmp);
7081 break;
7082 case 0x08:
7083 case 0x09:
7085 int j, n, user, loaded_base;
7086 TCGv loaded_var;
7087 /* load/store multiple words */
7088 /* XXX: store correct base if write back */
7089 user = 0;
7090 if (insn & (1 << 22)) {
7091 if (IS_USER(s))
7092 goto illegal_op; /* only usable in supervisor mode */
7094 if ((insn & (1 << 15)) == 0)
7095 user = 1;
7097 rn = (insn >> 16) & 0xf;
7098 addr = load_reg(s, rn);
7100 /* compute total size */
7101 loaded_base = 0;
7102 TCGV_UNUSED(loaded_var);
7103 n = 0;
7104 for(i=0;i<16;i++) {
7105 if (insn & (1 << i))
7106 n++;
7108 /* XXX: test invalid n == 0 case ? */
7109 if (insn & (1 << 23)) {
7110 if (insn & (1 << 24)) {
7111 /* pre increment */
7112 tcg_gen_addi_i32(addr, addr, 4);
7113 } else {
7114 /* post increment */
7116 } else {
7117 if (insn & (1 << 24)) {
7118 /* pre decrement */
7119 tcg_gen_addi_i32(addr, addr, -(n * 4));
7120 } else {
7121 /* post decrement */
7122 if (n != 1)
7123 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7126 j = 0;
7127 for(i=0;i<16;i++) {
7128 if (insn & (1 << i)) {
7129 if (insn & (1 << 20)) {
7130 /* load */
7131 tmp = gen_ld32(addr, IS_USER(s));
7132 if (i == 15) {
7133 gen_bx(s, tmp);
7134 } else if (user) {
7135 tmp2 = tcg_const_i32(i);
7136 gen_helper_set_user_reg(tmp2, tmp);
7137 tcg_temp_free_i32(tmp2);
7138 dead_tmp(tmp);
7139 } else if (i == rn) {
7140 loaded_var = tmp;
7141 loaded_base = 1;
7142 } else {
7143 store_reg(s, i, tmp);
7145 } else {
7146 /* store */
7147 if (i == 15) {
7148 /* special case: r15 = PC + 8 */
7149 val = (long)s->pc + 4;
7150 tmp = new_tmp();
7151 tcg_gen_movi_i32(tmp, val);
7152 } else if (user) {
7153 tmp = new_tmp();
7154 tmp2 = tcg_const_i32(i);
7155 gen_helper_get_user_reg(tmp, tmp2);
7156 tcg_temp_free_i32(tmp2);
7157 } else {
7158 tmp = load_reg(s, i);
7160 gen_st32(tmp, addr, IS_USER(s));
7162 j++;
7163 /* no need to add after the last transfer */
7164 if (j != n)
7165 tcg_gen_addi_i32(addr, addr, 4);
7168 if (insn & (1 << 21)) {
7169 /* write back */
7170 if (insn & (1 << 23)) {
7171 if (insn & (1 << 24)) {
7172 /* pre increment */
7173 } else {
7174 /* post increment */
7175 tcg_gen_addi_i32(addr, addr, 4);
7177 } else {
7178 if (insn & (1 << 24)) {
7179 /* pre decrement */
7180 if (n != 1)
7181 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7182 } else {
7183 /* post decrement */
7184 tcg_gen_addi_i32(addr, addr, -(n * 4));
7187 store_reg(s, rn, addr);
7188 } else {
7189 dead_tmp(addr);
7191 if (loaded_base) {
7192 store_reg(s, rn, loaded_var);
7194 if ((insn & (1 << 22)) && !user) {
7195 /* Restore CPSR from SPSR. */
7196 tmp = load_cpu_field(spsr);
7197 gen_set_cpsr(tmp, 0xffffffff);
7198 dead_tmp(tmp);
7199 s->is_jmp = DISAS_UPDATE;
7202 break;
7203 case 0xa:
7204 case 0xb:
7206 int32_t offset;
7208 /* branch (and link) */
7209 val = (int32_t)s->pc;
7210 if (insn & (1 << 24)) {
7211 tmp = new_tmp();
7212 tcg_gen_movi_i32(tmp, val);
7213 store_reg(s, 14, tmp);
7215 offset = (((int32_t)insn << 8) >> 8);
7216 val += (offset << 2) + 4;
7217 gen_jmp(s, val);
7219 break;
7220 case 0xc:
7221 case 0xd:
7222 case 0xe:
7223 /* Coprocessor. */
7224 if (disas_coproc_insn(env, s, insn))
7225 goto illegal_op;
7226 break;
7227 case 0xf:
7228 /* swi */
7229 gen_set_pc_im(s->pc);
7230 s->is_jmp = DISAS_SWI;
7231 break;
7232 default:
7233 illegal_op:
7234 gen_set_condexec(s);
7235 gen_set_pc_im(s->pc - 4);
7236 gen_exception(EXCP_UDEF);
7237 s->is_jmp = DISAS_JUMP;
7238 break;
7243 /* Return true if this is a Thumb-2 logical op. */
7244 static int
7245 thumb2_logic_op(int op)
7247 return (op < 8);
7250 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7251 then set condition code flags based on the result of the operation.
7252 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7253 to the high bit of T1.
7254 Returns zero if the opcode is valid. */
7256 static int
7257 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7259 int logic_cc;
7261 logic_cc = 0;
7262 switch (op) {
7263 case 0: /* and */
7264 tcg_gen_and_i32(t0, t0, t1);
7265 logic_cc = conds;
7266 break;
7267 case 1: /* bic */
7268 tcg_gen_andc_i32(t0, t0, t1);
7269 logic_cc = conds;
7270 break;
7271 case 2: /* orr */
7272 tcg_gen_or_i32(t0, t0, t1);
7273 logic_cc = conds;
7274 break;
7275 case 3: /* orn */
7276 tcg_gen_not_i32(t1, t1);
7277 tcg_gen_or_i32(t0, t0, t1);
7278 logic_cc = conds;
7279 break;
7280 case 4: /* eor */
7281 tcg_gen_xor_i32(t0, t0, t1);
7282 logic_cc = conds;
7283 break;
7284 case 8: /* add */
7285 if (conds)
7286 gen_helper_add_cc(t0, t0, t1);
7287 else
7288 tcg_gen_add_i32(t0, t0, t1);
7289 break;
7290 case 10: /* adc */
7291 if (conds)
7292 gen_helper_adc_cc(t0, t0, t1);
7293 else
7294 gen_adc(t0, t1);
7295 break;
7296 case 11: /* sbc */
7297 if (conds)
7298 gen_helper_sbc_cc(t0, t0, t1);
7299 else
7300 gen_sub_carry(t0, t0, t1);
7301 break;
7302 case 13: /* sub */
7303 if (conds)
7304 gen_helper_sub_cc(t0, t0, t1);
7305 else
7306 tcg_gen_sub_i32(t0, t0, t1);
7307 break;
7308 case 14: /* rsb */
7309 if (conds)
7310 gen_helper_sub_cc(t0, t1, t0);
7311 else
7312 tcg_gen_sub_i32(t0, t1, t0);
7313 break;
7314 default: /* 5, 6, 7, 9, 12, 15. */
7315 return 1;
7317 if (logic_cc) {
7318 gen_logic_CC(t0);
7319 if (shifter_out)
7320 gen_set_CF_bit31(t1);
7322 return 0;
7325 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7326 is not legal. */
7327 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7329 uint32_t insn, imm, shift, offset;
7330 uint32_t rd, rn, rm, rs;
7331 TCGv tmp;
7332 TCGv tmp2;
7333 TCGv tmp3;
7334 TCGv addr;
7335 TCGv_i64 tmp64;
7336 int op;
7337 int shiftop;
7338 int conds;
7339 int logic_cc;
7341 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7342 || arm_feature (env, ARM_FEATURE_M))) {
7343 /* Thumb-1 cores may need to treat bl and blx as a pair of
7344 16-bit instructions to get correct prefetch abort behavior. */
7345 insn = insn_hw1;
7346 if ((insn & (1 << 12)) == 0) {
7347 /* Second half of blx. */
7348 offset = ((insn & 0x7ff) << 1);
7349 tmp = load_reg(s, 14);
7350 tcg_gen_addi_i32(tmp, tmp, offset);
7351 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7353 tmp2 = new_tmp();
7354 tcg_gen_movi_i32(tmp2, s->pc | 1);
7355 store_reg(s, 14, tmp2);
7356 gen_bx(s, tmp);
7357 return 0;
7359 if (insn & (1 << 11)) {
7360 /* Second half of bl. */
7361 offset = ((insn & 0x7ff) << 1) | 1;
7362 tmp = load_reg(s, 14);
7363 tcg_gen_addi_i32(tmp, tmp, offset);
7365 tmp2 = new_tmp();
7366 tcg_gen_movi_i32(tmp2, s->pc | 1);
7367 store_reg(s, 14, tmp2);
7368 gen_bx(s, tmp);
7369 return 0;
7371 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7372 /* Instruction spans a page boundary. Implement it as two
7373 16-bit instructions in case the second half causes an
7374 prefetch abort. */
7375 offset = ((int32_t)insn << 21) >> 9;
7376 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7377 return 0;
7379 /* Fall through to 32-bit decode. */
7382 insn = lduw_code(s->pc);
7383 s->pc += 2;
7384 insn |= (uint32_t)insn_hw1 << 16;
7386 if ((insn & 0xf800e800) != 0xf000e800) {
7387 ARCH(6T2);
7390 rn = (insn >> 16) & 0xf;
7391 rs = (insn >> 12) & 0xf;
7392 rd = (insn >> 8) & 0xf;
7393 rm = insn & 0xf;
7394 switch ((insn >> 25) & 0xf) {
7395 case 0: case 1: case 2: case 3:
7396 /* 16-bit instructions. Should never happen. */
7397 abort();
7398 case 4:
7399 if (insn & (1 << 22)) {
7400 /* Other load/store, table branch. */
7401 if (insn & 0x01200000) {
7402 /* Load/store doubleword. */
7403 if (rn == 15) {
7404 addr = new_tmp();
7405 tcg_gen_movi_i32(addr, s->pc & ~3);
7406 } else {
7407 addr = load_reg(s, rn);
7409 offset = (insn & 0xff) * 4;
7410 if ((insn & (1 << 23)) == 0)
7411 offset = -offset;
7412 if (insn & (1 << 24)) {
7413 tcg_gen_addi_i32(addr, addr, offset);
7414 offset = 0;
7416 if (insn & (1 << 20)) {
7417 /* ldrd */
7418 tmp = gen_ld32(addr, IS_USER(s));
7419 store_reg(s, rs, tmp);
7420 tcg_gen_addi_i32(addr, addr, 4);
7421 tmp = gen_ld32(addr, IS_USER(s));
7422 store_reg(s, rd, tmp);
7423 } else {
7424 /* strd */
7425 tmp = load_reg(s, rs);
7426 gen_st32(tmp, addr, IS_USER(s));
7427 tcg_gen_addi_i32(addr, addr, 4);
7428 tmp = load_reg(s, rd);
7429 gen_st32(tmp, addr, IS_USER(s));
7431 if (insn & (1 << 21)) {
7432 /* Base writeback. */
7433 if (rn == 15)
7434 goto illegal_op;
7435 tcg_gen_addi_i32(addr, addr, offset - 4);
7436 store_reg(s, rn, addr);
7437 } else {
7438 dead_tmp(addr);
7440 } else if ((insn & (1 << 23)) == 0) {
7441 /* Load/store exclusive word. */
7442 addr = tcg_temp_local_new();
7443 load_reg_var(s, addr, rn);
7444 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7445 if (insn & (1 << 20)) {
7446 gen_load_exclusive(s, rs, 15, addr, 2);
7447 } else {
7448 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7450 tcg_temp_free(addr);
7451 } else if ((insn & (1 << 6)) == 0) {
7452 /* Table Branch. */
7453 if (rn == 15) {
7454 addr = new_tmp();
7455 tcg_gen_movi_i32(addr, s->pc);
7456 } else {
7457 addr = load_reg(s, rn);
7459 tmp = load_reg(s, rm);
7460 tcg_gen_add_i32(addr, addr, tmp);
7461 if (insn & (1 << 4)) {
7462 /* tbh */
7463 tcg_gen_add_i32(addr, addr, tmp);
7464 dead_tmp(tmp);
7465 tmp = gen_ld16u(addr, IS_USER(s));
7466 } else { /* tbb */
7467 dead_tmp(tmp);
7468 tmp = gen_ld8u(addr, IS_USER(s));
7470 dead_tmp(addr);
7471 tcg_gen_shli_i32(tmp, tmp, 1);
7472 tcg_gen_addi_i32(tmp, tmp, s->pc);
7473 store_reg(s, 15, tmp);
7474 } else {
7475 /* Load/store exclusive byte/halfword/doubleword. */
7476 ARCH(7);
7477 op = (insn >> 4) & 0x3;
7478 if (op == 2) {
7479 goto illegal_op;
7481 addr = tcg_temp_local_new();
7482 load_reg_var(s, addr, rn);
7483 if (insn & (1 << 20)) {
7484 gen_load_exclusive(s, rs, rd, addr, op);
7485 } else {
7486 gen_store_exclusive(s, rm, rs, rd, addr, op);
7488 tcg_temp_free(addr);
7490 } else {
7491 /* Load/store multiple, RFE, SRS. */
7492 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7493 /* Not available in user mode. */
7494 if (IS_USER(s))
7495 goto illegal_op;
7496 if (insn & (1 << 20)) {
7497 /* rfe */
7498 addr = load_reg(s, rn);
7499 if ((insn & (1 << 24)) == 0)
7500 tcg_gen_addi_i32(addr, addr, -8);
7501 /* Load PC into tmp and CPSR into tmp2. */
7502 tmp = gen_ld32(addr, 0);
7503 tcg_gen_addi_i32(addr, addr, 4);
7504 tmp2 = gen_ld32(addr, 0);
7505 if (insn & (1 << 21)) {
7506 /* Base writeback. */
7507 if (insn & (1 << 24)) {
7508 tcg_gen_addi_i32(addr, addr, 4);
7509 } else {
7510 tcg_gen_addi_i32(addr, addr, -4);
7512 store_reg(s, rn, addr);
7513 } else {
7514 dead_tmp(addr);
7516 gen_rfe(s, tmp, tmp2);
7517 } else {
7518 /* srs */
7519 op = (insn & 0x1f);
7520 if (op == (env->uncached_cpsr & CPSR_M)) {
7521 addr = load_reg(s, 13);
7522 } else {
7523 addr = new_tmp();
7524 tmp = tcg_const_i32(op);
7525 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7526 tcg_temp_free_i32(tmp);
7528 if ((insn & (1 << 24)) == 0) {
7529 tcg_gen_addi_i32(addr, addr, -8);
7531 tmp = load_reg(s, 14);
7532 gen_st32(tmp, addr, 0);
7533 tcg_gen_addi_i32(addr, addr, 4);
7534 tmp = new_tmp();
7535 gen_helper_cpsr_read(tmp);
7536 gen_st32(tmp, addr, 0);
7537 if (insn & (1 << 21)) {
7538 if ((insn & (1 << 24)) == 0) {
7539 tcg_gen_addi_i32(addr, addr, -4);
7540 } else {
7541 tcg_gen_addi_i32(addr, addr, 4);
7543 if (op == (env->uncached_cpsr & CPSR_M)) {
7544 store_reg(s, 13, addr);
7545 } else {
7546 tmp = tcg_const_i32(op);
7547 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7548 tcg_temp_free_i32(tmp);
7550 } else {
7551 dead_tmp(addr);
7554 } else {
7555 int i;
7556 /* Load/store multiple. */
7557 addr = load_reg(s, rn);
7558 offset = 0;
7559 for (i = 0; i < 16; i++) {
7560 if (insn & (1 << i))
7561 offset += 4;
7563 if (insn & (1 << 24)) {
7564 tcg_gen_addi_i32(addr, addr, -offset);
7567 for (i = 0; i < 16; i++) {
7568 if ((insn & (1 << i)) == 0)
7569 continue;
7570 if (insn & (1 << 20)) {
7571 /* Load. */
7572 tmp = gen_ld32(addr, IS_USER(s));
7573 if (i == 15) {
7574 gen_bx(s, tmp);
7575 } else {
7576 store_reg(s, i, tmp);
7578 } else {
7579 /* Store. */
7580 tmp = load_reg(s, i);
7581 gen_st32(tmp, addr, IS_USER(s));
7583 tcg_gen_addi_i32(addr, addr, 4);
7585 if (insn & (1 << 21)) {
7586 /* Base register writeback. */
7587 if (insn & (1 << 24)) {
7588 tcg_gen_addi_i32(addr, addr, -offset);
7590 /* Fault if writeback register is in register list. */
7591 if (insn & (1 << rn))
7592 goto illegal_op;
7593 store_reg(s, rn, addr);
7594 } else {
7595 dead_tmp(addr);
7599 break;
7600 case 5: /* Data processing register constant shift. */
7601 if (rn == 15) {
7602 tmp = new_tmp();
7603 tcg_gen_movi_i32(tmp, 0);
7604 } else {
7605 tmp = load_reg(s, rn);
7607 tmp2 = load_reg(s, rm);
7608 op = (insn >> 21) & 0xf;
7609 shiftop = (insn >> 4) & 3;
7610 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7611 conds = (insn & (1 << 20)) != 0;
7612 logic_cc = (conds && thumb2_logic_op(op));
7613 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7614 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7615 goto illegal_op;
7616 dead_tmp(tmp2);
7617 if (rd != 15) {
7618 store_reg(s, rd, tmp);
7619 } else {
7620 dead_tmp(tmp);
7622 break;
7623 case 13: /* Misc data processing. */
7624 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7625 if (op < 4 && (insn & 0xf000) != 0xf000)
7626 goto illegal_op;
7627 switch (op) {
7628 case 0: /* Register controlled shift. */
7629 tmp = load_reg(s, rn);
7630 tmp2 = load_reg(s, rm);
7631 if ((insn & 0x70) != 0)
7632 goto illegal_op;
7633 op = (insn >> 21) & 3;
7634 logic_cc = (insn & (1 << 20)) != 0;
7635 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7636 if (logic_cc)
7637 gen_logic_CC(tmp);
7638 store_reg_bx(env, s, rd, tmp);
7639 break;
7640 case 1: /* Sign/zero extend. */
7641 tmp = load_reg(s, rm);
7642 shift = (insn >> 4) & 3;
7643 /* ??? In many cases it's not neccessary to do a
7644 rotate, a shift is sufficient. */
7645 if (shift != 0)
7646 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7647 op = (insn >> 20) & 7;
7648 switch (op) {
7649 case 0: gen_sxth(tmp); break;
7650 case 1: gen_uxth(tmp); break;
7651 case 2: gen_sxtb16(tmp); break;
7652 case 3: gen_uxtb16(tmp); break;
7653 case 4: gen_sxtb(tmp); break;
7654 case 5: gen_uxtb(tmp); break;
7655 default: goto illegal_op;
7657 if (rn != 15) {
7658 tmp2 = load_reg(s, rn);
7659 if ((op >> 1) == 1) {
7660 gen_add16(tmp, tmp2);
7661 } else {
7662 tcg_gen_add_i32(tmp, tmp, tmp2);
7663 dead_tmp(tmp2);
7666 store_reg(s, rd, tmp);
7667 break;
7668 case 2: /* SIMD add/subtract. */
7669 op = (insn >> 20) & 7;
7670 shift = (insn >> 4) & 7;
7671 if ((op & 3) == 3 || (shift & 3) == 3)
7672 goto illegal_op;
7673 tmp = load_reg(s, rn);
7674 tmp2 = load_reg(s, rm);
7675 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7676 dead_tmp(tmp2);
7677 store_reg(s, rd, tmp);
7678 break;
7679 case 3: /* Other data processing. */
7680 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7681 if (op < 4) {
7682 /* Saturating add/subtract. */
7683 tmp = load_reg(s, rn);
7684 tmp2 = load_reg(s, rm);
7685 if (op & 2)
7686 gen_helper_double_saturate(tmp, tmp);
7687 if (op & 1)
7688 gen_helper_sub_saturate(tmp, tmp2, tmp);
7689 else
7690 gen_helper_add_saturate(tmp, tmp, tmp2);
7691 dead_tmp(tmp2);
7692 } else {
7693 tmp = load_reg(s, rn);
7694 switch (op) {
7695 case 0x0a: /* rbit */
7696 gen_helper_rbit(tmp, tmp);
7697 break;
7698 case 0x08: /* rev */
7699 tcg_gen_bswap32_i32(tmp, tmp);
7700 break;
7701 case 0x09: /* rev16 */
7702 gen_rev16(tmp);
7703 break;
7704 case 0x0b: /* revsh */
7705 gen_revsh(tmp);
7706 break;
7707 case 0x10: /* sel */
7708 tmp2 = load_reg(s, rm);
7709 tmp3 = new_tmp();
7710 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7711 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7712 dead_tmp(tmp3);
7713 dead_tmp(tmp2);
7714 break;
7715 case 0x18: /* clz */
7716 gen_helper_clz(tmp, tmp);
7717 break;
7718 default:
7719 goto illegal_op;
7722 store_reg(s, rd, tmp);
7723 break;
7724 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7725 op = (insn >> 4) & 0xf;
7726 tmp = load_reg(s, rn);
7727 tmp2 = load_reg(s, rm);
7728 switch ((insn >> 20) & 7) {
7729 case 0: /* 32 x 32 -> 32 */
7730 tcg_gen_mul_i32(tmp, tmp, tmp2);
7731 dead_tmp(tmp2);
7732 if (rs != 15) {
7733 tmp2 = load_reg(s, rs);
7734 if (op)
7735 tcg_gen_sub_i32(tmp, tmp2, tmp);
7736 else
7737 tcg_gen_add_i32(tmp, tmp, tmp2);
7738 dead_tmp(tmp2);
7740 break;
7741 case 1: /* 16 x 16 -> 32 */
7742 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7743 dead_tmp(tmp2);
7744 if (rs != 15) {
7745 tmp2 = load_reg(s, rs);
7746 gen_helper_add_setq(tmp, tmp, tmp2);
7747 dead_tmp(tmp2);
7749 break;
7750 case 2: /* Dual multiply add. */
7751 case 4: /* Dual multiply subtract. */
7752 if (op)
7753 gen_swap_half(tmp2);
7754 gen_smul_dual(tmp, tmp2);
7755 /* This addition cannot overflow. */
7756 if (insn & (1 << 22)) {
7757 tcg_gen_sub_i32(tmp, tmp, tmp2);
7758 } else {
7759 tcg_gen_add_i32(tmp, tmp, tmp2);
7761 dead_tmp(tmp2);
7762 if (rs != 15)
7764 tmp2 = load_reg(s, rs);
7765 gen_helper_add_setq(tmp, tmp, tmp2);
7766 dead_tmp(tmp2);
7768 break;
7769 case 3: /* 32 * 16 -> 32msb */
7770 if (op)
7771 tcg_gen_sari_i32(tmp2, tmp2, 16);
7772 else
7773 gen_sxth(tmp2);
7774 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7775 tcg_gen_shri_i64(tmp64, tmp64, 16);
7776 tmp = new_tmp();
7777 tcg_gen_trunc_i64_i32(tmp, tmp64);
7778 tcg_temp_free_i64(tmp64);
7779 if (rs != 15)
7781 tmp2 = load_reg(s, rs);
7782 gen_helper_add_setq(tmp, tmp, tmp2);
7783 dead_tmp(tmp2);
7785 break;
7786 case 5: case 6: /* 32 * 32 -> 32msb */
7787 gen_imull(tmp, tmp2);
7788 if (insn & (1 << 5)) {
7789 gen_roundqd(tmp, tmp2);
7790 dead_tmp(tmp2);
7791 } else {
7792 dead_tmp(tmp);
7793 tmp = tmp2;
7795 if (rs != 15) {
7796 tmp2 = load_reg(s, rs);
7797 if (insn & (1 << 21)) {
7798 tcg_gen_add_i32(tmp, tmp, tmp2);
7799 } else {
7800 tcg_gen_sub_i32(tmp, tmp2, tmp);
7802 dead_tmp(tmp2);
7804 break;
7805 case 7: /* Unsigned sum of absolute differences. */
7806 gen_helper_usad8(tmp, tmp, tmp2);
7807 dead_tmp(tmp2);
7808 if (rs != 15) {
7809 tmp2 = load_reg(s, rs);
7810 tcg_gen_add_i32(tmp, tmp, tmp2);
7811 dead_tmp(tmp2);
7813 break;
7815 store_reg(s, rd, tmp);
7816 break;
7817 case 6: case 7: /* 64-bit multiply, Divide. */
7818 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7819 tmp = load_reg(s, rn);
7820 tmp2 = load_reg(s, rm);
7821 if ((op & 0x50) == 0x10) {
7822 /* sdiv, udiv */
7823 if (!arm_feature(env, ARM_FEATURE_DIV))
7824 goto illegal_op;
7825 if (op & 0x20)
7826 gen_helper_udiv(tmp, tmp, tmp2);
7827 else
7828 gen_helper_sdiv(tmp, tmp, tmp2);
7829 dead_tmp(tmp2);
7830 store_reg(s, rd, tmp);
7831 } else if ((op & 0xe) == 0xc) {
7832 /* Dual multiply accumulate long. */
7833 if (op & 1)
7834 gen_swap_half(tmp2);
7835 gen_smul_dual(tmp, tmp2);
7836 if (op & 0x10) {
7837 tcg_gen_sub_i32(tmp, tmp, tmp2);
7838 } else {
7839 tcg_gen_add_i32(tmp, tmp, tmp2);
7841 dead_tmp(tmp2);
7842 /* BUGFIX */
7843 tmp64 = tcg_temp_new_i64();
7844 tcg_gen_ext_i32_i64(tmp64, tmp);
7845 dead_tmp(tmp);
7846 gen_addq(s, tmp64, rs, rd);
7847 gen_storeq_reg(s, rs, rd, tmp64);
7848 tcg_temp_free_i64(tmp64);
7849 } else {
7850 if (op & 0x20) {
7851 /* Unsigned 64-bit multiply */
7852 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7853 } else {
7854 if (op & 8) {
7855 /* smlalxy */
7856 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7857 dead_tmp(tmp2);
7858 tmp64 = tcg_temp_new_i64();
7859 tcg_gen_ext_i32_i64(tmp64, tmp);
7860 dead_tmp(tmp);
7861 } else {
7862 /* Signed 64-bit multiply */
7863 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7866 if (op & 4) {
7867 /* umaal */
7868 gen_addq_lo(s, tmp64, rs);
7869 gen_addq_lo(s, tmp64, rd);
7870 } else if (op & 0x40) {
7871 /* 64-bit accumulate. */
7872 gen_addq(s, tmp64, rs, rd);
7874 gen_storeq_reg(s, rs, rd, tmp64);
7875 tcg_temp_free_i64(tmp64);
7877 break;
7879 break;
7880 case 6: case 7: case 14: case 15:
7881 /* Coprocessor. */
7882 if (((insn >> 24) & 3) == 3) {
7883 /* Translate into the equivalent ARM encoding. */
7884 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7885 if (disas_neon_data_insn(env, s, insn))
7886 goto illegal_op;
7887 } else {
7888 if (insn & (1 << 28))
7889 goto illegal_op;
7890 if (disas_coproc_insn (env, s, insn))
7891 goto illegal_op;
7893 break;
7894 case 8: case 9: case 10: case 11:
7895 if (insn & (1 << 15)) {
7896 /* Branches, misc control. */
7897 if (insn & 0x5000) {
7898 /* Unconditional branch. */
7899 /* signextend(hw1[10:0]) -> offset[:12]. */
7900 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7901 /* hw1[10:0] -> offset[11:1]. */
7902 offset |= (insn & 0x7ff) << 1;
7903 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7904 offset[24:22] already have the same value because of the
7905 sign extension above. */
7906 offset ^= ((~insn) & (1 << 13)) << 10;
7907 offset ^= ((~insn) & (1 << 11)) << 11;
7909 if (insn & (1 << 14)) {
7910 /* Branch and link. */
7911 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7914 offset += s->pc;
7915 if (insn & (1 << 12)) {
7916 /* b/bl */
7917 gen_jmp(s, offset);
7918 } else {
7919 /* blx */
7920 offset &= ~(uint32_t)2;
7921 gen_bx_im(s, offset);
7923 } else if (((insn >> 23) & 7) == 7) {
7924 /* Misc control */
7925 if (insn & (1 << 13))
7926 goto illegal_op;
7928 if (insn & (1 << 26)) {
7929 /* Secure monitor call (v6Z) */
7930 goto illegal_op; /* not implemented. */
7931 } else {
7932 op = (insn >> 20) & 7;
7933 switch (op) {
7934 case 0: /* msr cpsr. */
7935 if (IS_M(env)) {
7936 tmp = load_reg(s, rn);
7937 addr = tcg_const_i32(insn & 0xff);
7938 gen_helper_v7m_msr(cpu_env, addr, tmp);
7939 tcg_temp_free_i32(addr);
7940 dead_tmp(tmp);
7941 gen_lookup_tb(s);
7942 break;
7944 /* fall through */
7945 case 1: /* msr spsr. */
7946 if (IS_M(env))
7947 goto illegal_op;
7948 tmp = load_reg(s, rn);
7949 if (gen_set_psr(s,
7950 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7951 op == 1, tmp))
7952 goto illegal_op;
7953 break;
7954 case 2: /* cps, nop-hint. */
7955 if (((insn >> 8) & 7) == 0) {
7956 gen_nop_hint(s, insn & 0xff);
7958 /* Implemented as NOP in user mode. */
7959 if (IS_USER(s))
7960 break;
7961 offset = 0;
7962 imm = 0;
7963 if (insn & (1 << 10)) {
7964 if (insn & (1 << 7))
7965 offset |= CPSR_A;
7966 if (insn & (1 << 6))
7967 offset |= CPSR_I;
7968 if (insn & (1 << 5))
7969 offset |= CPSR_F;
7970 if (insn & (1 << 9))
7971 imm = CPSR_A | CPSR_I | CPSR_F;
7973 if (insn & (1 << 8)) {
7974 offset |= 0x1f;
7975 imm |= (insn & 0x1f);
7977 if (offset) {
7978 gen_set_psr_im(s, offset, 0, imm);
7980 break;
7981 case 3: /* Special control operations. */
7982 ARCH(7);
7983 op = (insn >> 4) & 0xf;
7984 switch (op) {
7985 case 2: /* clrex */
7986 gen_clrex(s);
7987 break;
7988 case 4: /* dsb */
7989 case 5: /* dmb */
7990 case 6: /* isb */
7991 /* These execute as NOPs. */
7992 break;
7993 default:
7994 goto illegal_op;
7996 break;
7997 case 4: /* bxj */
7998 /* Trivial implementation equivalent to bx. */
7999 tmp = load_reg(s, rn);
8000 gen_bx(s, tmp);
8001 break;
8002 case 5: /* Exception return. */
8003 if (IS_USER(s)) {
8004 goto illegal_op;
8006 if (rn != 14 || rd != 15) {
8007 goto illegal_op;
8009 tmp = load_reg(s, rn);
8010 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8011 gen_exception_return(s, tmp);
8012 break;
8013 case 6: /* mrs cpsr. */
8014 tmp = new_tmp();
8015 if (IS_M(env)) {
8016 addr = tcg_const_i32(insn & 0xff);
8017 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8018 tcg_temp_free_i32(addr);
8019 } else {
8020 gen_helper_cpsr_read(tmp);
8022 store_reg(s, rd, tmp);
8023 break;
8024 case 7: /* mrs spsr. */
8025 /* Not accessible in user mode. */
8026 if (IS_USER(s) || IS_M(env))
8027 goto illegal_op;
8028 tmp = load_cpu_field(spsr);
8029 store_reg(s, rd, tmp);
8030 break;
8033 } else {
8034 /* Conditional branch. */
8035 op = (insn >> 22) & 0xf;
8036 /* Generate a conditional jump to next instruction. */
8037 s->condlabel = gen_new_label();
8038 gen_test_cc(op ^ 1, s->condlabel);
8039 s->condjmp = 1;
8041 /* offset[11:1] = insn[10:0] */
8042 offset = (insn & 0x7ff) << 1;
8043 /* offset[17:12] = insn[21:16]. */
8044 offset |= (insn & 0x003f0000) >> 4;
8045 /* offset[31:20] = insn[26]. */
8046 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8047 /* offset[18] = insn[13]. */
8048 offset |= (insn & (1 << 13)) << 5;
8049 /* offset[19] = insn[11]. */
8050 offset |= (insn & (1 << 11)) << 8;
8052 /* jump to the offset */
8053 gen_jmp(s, s->pc + offset);
8055 } else {
8056 /* Data processing immediate. */
8057 if (insn & (1 << 25)) {
8058 if (insn & (1 << 24)) {
8059 if (insn & (1 << 20))
8060 goto illegal_op;
8061 /* Bitfield/Saturate. */
8062 op = (insn >> 21) & 7;
8063 imm = insn & 0x1f;
8064 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8065 if (rn == 15) {
8066 tmp = new_tmp();
8067 tcg_gen_movi_i32(tmp, 0);
8068 } else {
8069 tmp = load_reg(s, rn);
8071 switch (op) {
8072 case 2: /* Signed bitfield extract. */
8073 imm++;
8074 if (shift + imm > 32)
8075 goto illegal_op;
8076 if (imm < 32)
8077 gen_sbfx(tmp, shift, imm);
8078 break;
8079 case 6: /* Unsigned bitfield extract. */
8080 imm++;
8081 if (shift + imm > 32)
8082 goto illegal_op;
8083 if (imm < 32)
8084 gen_ubfx(tmp, shift, (1u << imm) - 1);
8085 break;
8086 case 3: /* Bitfield insert/clear. */
8087 if (imm < shift)
8088 goto illegal_op;
8089 imm = imm + 1 - shift;
8090 if (imm != 32) {
8091 tmp2 = load_reg(s, rd);
8092 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8093 dead_tmp(tmp2);
8095 break;
8096 case 7:
8097 goto illegal_op;
8098 default: /* Saturate. */
8099 if (shift) {
8100 if (op & 1)
8101 tcg_gen_sari_i32(tmp, tmp, shift);
8102 else
8103 tcg_gen_shli_i32(tmp, tmp, shift);
8105 tmp2 = tcg_const_i32(imm);
8106 if (op & 4) {
8107 /* Unsigned. */
8108 if ((op & 1) && shift == 0)
8109 gen_helper_usat16(tmp, tmp, tmp2);
8110 else
8111 gen_helper_usat(tmp, tmp, tmp2);
8112 } else {
8113 /* Signed. */
8114 if ((op & 1) && shift == 0)
8115 gen_helper_ssat16(tmp, tmp, tmp2);
8116 else
8117 gen_helper_ssat(tmp, tmp, tmp2);
8119 tcg_temp_free_i32(tmp2);
8120 break;
8122 store_reg(s, rd, tmp);
8123 } else {
8124 imm = ((insn & 0x04000000) >> 15)
8125 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8126 if (insn & (1 << 22)) {
8127 /* 16-bit immediate. */
8128 imm |= (insn >> 4) & 0xf000;
8129 if (insn & (1 << 23)) {
8130 /* movt */
8131 tmp = load_reg(s, rd);
8132 tcg_gen_ext16u_i32(tmp, tmp);
8133 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8134 } else {
8135 /* movw */
8136 tmp = new_tmp();
8137 tcg_gen_movi_i32(tmp, imm);
8139 } else {
8140 /* Add/sub 12-bit immediate. */
8141 if (rn == 15) {
8142 offset = s->pc & ~(uint32_t)3;
8143 if (insn & (1 << 23))
8144 offset -= imm;
8145 else
8146 offset += imm;
8147 tmp = new_tmp();
8148 tcg_gen_movi_i32(tmp, offset);
8149 } else {
8150 tmp = load_reg(s, rn);
8151 if (insn & (1 << 23))
8152 tcg_gen_subi_i32(tmp, tmp, imm);
8153 else
8154 tcg_gen_addi_i32(tmp, tmp, imm);
8157 store_reg(s, rd, tmp);
8159 } else {
8160 int shifter_out = 0;
8161 /* modified 12-bit immediate. */
8162 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8163 imm = (insn & 0xff);
8164 switch (shift) {
8165 case 0: /* XY */
8166 /* Nothing to do. */
8167 break;
8168 case 1: /* 00XY00XY */
8169 imm |= imm << 16;
8170 break;
8171 case 2: /* XY00XY00 */
8172 imm |= imm << 16;
8173 imm <<= 8;
8174 break;
8175 case 3: /* XYXYXYXY */
8176 imm |= imm << 16;
8177 imm |= imm << 8;
8178 break;
8179 default: /* Rotated constant. */
8180 shift = (shift << 1) | (imm >> 7);
8181 imm |= 0x80;
8182 imm = imm << (32 - shift);
8183 shifter_out = 1;
8184 break;
8186 tmp2 = new_tmp();
8187 tcg_gen_movi_i32(tmp2, imm);
8188 rn = (insn >> 16) & 0xf;
8189 if (rn == 15) {
8190 tmp = new_tmp();
8191 tcg_gen_movi_i32(tmp, 0);
8192 } else {
8193 tmp = load_reg(s, rn);
8195 op = (insn >> 21) & 0xf;
8196 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8197 shifter_out, tmp, tmp2))
8198 goto illegal_op;
8199 dead_tmp(tmp2);
8200 rd = (insn >> 8) & 0xf;
8201 if (rd != 15) {
8202 store_reg(s, rd, tmp);
8203 } else {
8204 dead_tmp(tmp);
8208 break;
8209 case 12: /* Load/store single data item. */
8211 int postinc = 0;
8212 int writeback = 0;
8213 int user;
8214 if ((insn & 0x01100000) == 0x01000000) {
8215 if (disas_neon_ls_insn(env, s, insn))
8216 goto illegal_op;
8217 break;
8219 user = IS_USER(s);
8220 if (rn == 15) {
8221 addr = new_tmp();
8222 /* PC relative. */
8223 /* s->pc has already been incremented by 4. */
8224 imm = s->pc & 0xfffffffc;
8225 if (insn & (1 << 23))
8226 imm += insn & 0xfff;
8227 else
8228 imm -= insn & 0xfff;
8229 tcg_gen_movi_i32(addr, imm);
8230 } else {
8231 addr = load_reg(s, rn);
8232 if (insn & (1 << 23)) {
8233 /* Positive offset. */
8234 imm = insn & 0xfff;
8235 tcg_gen_addi_i32(addr, addr, imm);
8236 } else {
8237 op = (insn >> 8) & 7;
8238 imm = insn & 0xff;
8239 switch (op) {
8240 case 0: case 8: /* Shifted Register. */
8241 shift = (insn >> 4) & 0xf;
8242 if (shift > 3)
8243 goto illegal_op;
8244 tmp = load_reg(s, rm);
8245 if (shift)
8246 tcg_gen_shli_i32(tmp, tmp, shift);
8247 tcg_gen_add_i32(addr, addr, tmp);
8248 dead_tmp(tmp);
8249 break;
8250 case 4: /* Negative offset. */
8251 tcg_gen_addi_i32(addr, addr, -imm);
8252 break;
8253 case 6: /* User privilege. */
8254 tcg_gen_addi_i32(addr, addr, imm);
8255 user = 1;
8256 break;
8257 case 1: /* Post-decrement. */
8258 imm = -imm;
8259 /* Fall through. */
8260 case 3: /* Post-increment. */
8261 postinc = 1;
8262 writeback = 1;
8263 break;
8264 case 5: /* Pre-decrement. */
8265 imm = -imm;
8266 /* Fall through. */
8267 case 7: /* Pre-increment. */
8268 tcg_gen_addi_i32(addr, addr, imm);
8269 writeback = 1;
8270 break;
8271 default:
8272 goto illegal_op;
8276 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8277 if (insn & (1 << 20)) {
8278 /* Load. */
8279 if (rs == 15 && op != 2) {
8280 if (op & 2)
8281 goto illegal_op;
8282 /* Memory hint. Implemented as NOP. */
8283 } else {
8284 switch (op) {
8285 case 0: tmp = gen_ld8u(addr, user); break;
8286 case 4: tmp = gen_ld8s(addr, user); break;
8287 case 1: tmp = gen_ld16u(addr, user); break;
8288 case 5: tmp = gen_ld16s(addr, user); break;
8289 case 2: tmp = gen_ld32(addr, user); break;
8290 default: goto illegal_op;
8292 if (rs == 15) {
8293 gen_bx(s, tmp);
8294 } else {
8295 store_reg(s, rs, tmp);
8298 } else {
8299 /* Store. */
8300 if (rs == 15)
8301 goto illegal_op;
8302 tmp = load_reg(s, rs);
8303 switch (op) {
8304 case 0: gen_st8(tmp, addr, user); break;
8305 case 1: gen_st16(tmp, addr, user); break;
8306 case 2: gen_st32(tmp, addr, user); break;
8307 default: goto illegal_op;
8310 if (postinc)
8311 tcg_gen_addi_i32(addr, addr, imm);
8312 if (writeback) {
8313 store_reg(s, rn, addr);
8314 } else {
8315 dead_tmp(addr);
8318 break;
8319 default:
8320 goto illegal_op;
8322 return 0;
8323 illegal_op:
8324 return 1;
8327 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8329 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8330 int32_t offset;
8331 int i;
8332 TCGv tmp;
8333 TCGv tmp2;
8334 TCGv addr;
8336 if (s->condexec_mask) {
8337 cond = s->condexec_cond;
8338 s->condlabel = gen_new_label();
8339 gen_test_cc(cond ^ 1, s->condlabel);
8340 s->condjmp = 1;
8343 insn = lduw_code(s->pc);
8344 s->pc += 2;
8346 switch (insn >> 12) {
8347 case 0: case 1:
8349 rd = insn & 7;
8350 op = (insn >> 11) & 3;
8351 if (op == 3) {
8352 /* add/subtract */
8353 rn = (insn >> 3) & 7;
8354 tmp = load_reg(s, rn);
8355 if (insn & (1 << 10)) {
8356 /* immediate */
8357 tmp2 = new_tmp();
8358 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8359 } else {
8360 /* reg */
8361 rm = (insn >> 6) & 7;
8362 tmp2 = load_reg(s, rm);
8364 if (insn & (1 << 9)) {
8365 if (s->condexec_mask)
8366 tcg_gen_sub_i32(tmp, tmp, tmp2);
8367 else
8368 gen_helper_sub_cc(tmp, tmp, tmp2);
8369 } else {
8370 if (s->condexec_mask)
8371 tcg_gen_add_i32(tmp, tmp, tmp2);
8372 else
8373 gen_helper_add_cc(tmp, tmp, tmp2);
8375 dead_tmp(tmp2);
8376 store_reg(s, rd, tmp);
8377 } else {
8378 /* shift immediate */
8379 rm = (insn >> 3) & 7;
8380 shift = (insn >> 6) & 0x1f;
8381 tmp = load_reg(s, rm);
8382 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8383 if (!s->condexec_mask)
8384 gen_logic_CC(tmp);
8385 store_reg(s, rd, tmp);
8387 break;
8388 case 2: case 3:
8389 /* arithmetic large immediate */
8390 op = (insn >> 11) & 3;
8391 rd = (insn >> 8) & 0x7;
8392 if (op == 0) { /* mov */
8393 tmp = new_tmp();
8394 tcg_gen_movi_i32(tmp, insn & 0xff);
8395 if (!s->condexec_mask)
8396 gen_logic_CC(tmp);
8397 store_reg(s, rd, tmp);
8398 } else {
8399 tmp = load_reg(s, rd);
8400 tmp2 = new_tmp();
8401 tcg_gen_movi_i32(tmp2, insn & 0xff);
8402 switch (op) {
8403 case 1: /* cmp */
8404 gen_helper_sub_cc(tmp, tmp, tmp2);
8405 dead_tmp(tmp);
8406 dead_tmp(tmp2);
8407 break;
8408 case 2: /* add */
8409 if (s->condexec_mask)
8410 tcg_gen_add_i32(tmp, tmp, tmp2);
8411 else
8412 gen_helper_add_cc(tmp, tmp, tmp2);
8413 dead_tmp(tmp2);
8414 store_reg(s, rd, tmp);
8415 break;
8416 case 3: /* sub */
8417 if (s->condexec_mask)
8418 tcg_gen_sub_i32(tmp, tmp, tmp2);
8419 else
8420 gen_helper_sub_cc(tmp, tmp, tmp2);
8421 dead_tmp(tmp2);
8422 store_reg(s, rd, tmp);
8423 break;
8426 break;
8427 case 4:
8428 if (insn & (1 << 11)) {
8429 rd = (insn >> 8) & 7;
8430 /* load pc-relative. Bit 1 of PC is ignored. */
8431 val = s->pc + 2 + ((insn & 0xff) * 4);
8432 val &= ~(uint32_t)2;
8433 addr = new_tmp();
8434 tcg_gen_movi_i32(addr, val);
8435 tmp = gen_ld32(addr, IS_USER(s));
8436 dead_tmp(addr);
8437 store_reg(s, rd, tmp);
8438 break;
8440 if (insn & (1 << 10)) {
8441 /* data processing extended or blx */
8442 rd = (insn & 7) | ((insn >> 4) & 8);
8443 rm = (insn >> 3) & 0xf;
8444 op = (insn >> 8) & 3;
8445 switch (op) {
8446 case 0: /* add */
8447 tmp = load_reg(s, rd);
8448 tmp2 = load_reg(s, rm);
8449 tcg_gen_add_i32(tmp, tmp, tmp2);
8450 dead_tmp(tmp2);
8451 store_reg(s, rd, tmp);
8452 break;
8453 case 1: /* cmp */
8454 tmp = load_reg(s, rd);
8455 tmp2 = load_reg(s, rm);
8456 gen_helper_sub_cc(tmp, tmp, tmp2);
8457 dead_tmp(tmp2);
8458 dead_tmp(tmp);
8459 break;
8460 case 2: /* mov/cpy */
8461 tmp = load_reg(s, rm);
8462 store_reg(s, rd, tmp);
8463 break;
8464 case 3:/* branch [and link] exchange thumb register */
8465 tmp = load_reg(s, rm);
8466 if (insn & (1 << 7)) {
8467 val = (uint32_t)s->pc | 1;
8468 tmp2 = new_tmp();
8469 tcg_gen_movi_i32(tmp2, val);
8470 store_reg(s, 14, tmp2);
8472 gen_bx(s, tmp);
8473 break;
8475 break;
8478 /* data processing register */
8479 rd = insn & 7;
8480 rm = (insn >> 3) & 7;
8481 op = (insn >> 6) & 0xf;
8482 if (op == 2 || op == 3 || op == 4 || op == 7) {
8483 /* the shift/rotate ops want the operands backwards */
8484 val = rm;
8485 rm = rd;
8486 rd = val;
8487 val = 1;
8488 } else {
8489 val = 0;
8492 if (op == 9) { /* neg */
8493 tmp = new_tmp();
8494 tcg_gen_movi_i32(tmp, 0);
8495 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8496 tmp = load_reg(s, rd);
8497 } else {
8498 TCGV_UNUSED(tmp);
8501 tmp2 = load_reg(s, rm);
8502 switch (op) {
8503 case 0x0: /* and */
8504 tcg_gen_and_i32(tmp, tmp, tmp2);
8505 if (!s->condexec_mask)
8506 gen_logic_CC(tmp);
8507 break;
8508 case 0x1: /* eor */
8509 tcg_gen_xor_i32(tmp, tmp, tmp2);
8510 if (!s->condexec_mask)
8511 gen_logic_CC(tmp);
8512 break;
8513 case 0x2: /* lsl */
8514 if (s->condexec_mask) {
8515 gen_helper_shl(tmp2, tmp2, tmp);
8516 } else {
8517 gen_helper_shl_cc(tmp2, tmp2, tmp);
8518 gen_logic_CC(tmp2);
8520 break;
8521 case 0x3: /* lsr */
8522 if (s->condexec_mask) {
8523 gen_helper_shr(tmp2, tmp2, tmp);
8524 } else {
8525 gen_helper_shr_cc(tmp2, tmp2, tmp);
8526 gen_logic_CC(tmp2);
8528 break;
8529 case 0x4: /* asr */
8530 if (s->condexec_mask) {
8531 gen_helper_sar(tmp2, tmp2, tmp);
8532 } else {
8533 gen_helper_sar_cc(tmp2, tmp2, tmp);
8534 gen_logic_CC(tmp2);
8536 break;
8537 case 0x5: /* adc */
8538 if (s->condexec_mask)
8539 gen_adc(tmp, tmp2);
8540 else
8541 gen_helper_adc_cc(tmp, tmp, tmp2);
8542 break;
8543 case 0x6: /* sbc */
8544 if (s->condexec_mask)
8545 gen_sub_carry(tmp, tmp, tmp2);
8546 else
8547 gen_helper_sbc_cc(tmp, tmp, tmp2);
8548 break;
8549 case 0x7: /* ror */
8550 if (s->condexec_mask) {
8551 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8552 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8553 } else {
8554 gen_helper_ror_cc(tmp2, tmp2, tmp);
8555 gen_logic_CC(tmp2);
8557 break;
8558 case 0x8: /* tst */
8559 tcg_gen_and_i32(tmp, tmp, tmp2);
8560 gen_logic_CC(tmp);
8561 rd = 16;
8562 break;
8563 case 0x9: /* neg */
8564 if (s->condexec_mask)
8565 tcg_gen_neg_i32(tmp, tmp2);
8566 else
8567 gen_helper_sub_cc(tmp, tmp, tmp2);
8568 break;
8569 case 0xa: /* cmp */
8570 gen_helper_sub_cc(tmp, tmp, tmp2);
8571 rd = 16;
8572 break;
8573 case 0xb: /* cmn */
8574 gen_helper_add_cc(tmp, tmp, tmp2);
8575 rd = 16;
8576 break;
8577 case 0xc: /* orr */
8578 tcg_gen_or_i32(tmp, tmp, tmp2);
8579 if (!s->condexec_mask)
8580 gen_logic_CC(tmp);
8581 break;
8582 case 0xd: /* mul */
8583 tcg_gen_mul_i32(tmp, tmp, tmp2);
8584 if (!s->condexec_mask)
8585 gen_logic_CC(tmp);
8586 break;
8587 case 0xe: /* bic */
8588 tcg_gen_andc_i32(tmp, tmp, tmp2);
8589 if (!s->condexec_mask)
8590 gen_logic_CC(tmp);
8591 break;
8592 case 0xf: /* mvn */
8593 tcg_gen_not_i32(tmp2, tmp2);
8594 if (!s->condexec_mask)
8595 gen_logic_CC(tmp2);
8596 val = 1;
8597 rm = rd;
8598 break;
8600 if (rd != 16) {
8601 if (val) {
8602 store_reg(s, rm, tmp2);
8603 if (op != 0xf)
8604 dead_tmp(tmp);
8605 } else {
8606 store_reg(s, rd, tmp);
8607 dead_tmp(tmp2);
8609 } else {
8610 dead_tmp(tmp);
8611 dead_tmp(tmp2);
8613 break;
8615 case 5:
8616 /* load/store register offset. */
8617 rd = insn & 7;
8618 rn = (insn >> 3) & 7;
8619 rm = (insn >> 6) & 7;
8620 op = (insn >> 9) & 7;
8621 addr = load_reg(s, rn);
8622 tmp = load_reg(s, rm);
8623 tcg_gen_add_i32(addr, addr, tmp);
8624 dead_tmp(tmp);
8626 if (op < 3) /* store */
8627 tmp = load_reg(s, rd);
8629 switch (op) {
8630 case 0: /* str */
8631 gen_st32(tmp, addr, IS_USER(s));
8632 break;
8633 case 1: /* strh */
8634 gen_st16(tmp, addr, IS_USER(s));
8635 break;
8636 case 2: /* strb */
8637 gen_st8(tmp, addr, IS_USER(s));
8638 break;
8639 case 3: /* ldrsb */
8640 tmp = gen_ld8s(addr, IS_USER(s));
8641 break;
8642 case 4: /* ldr */
8643 tmp = gen_ld32(addr, IS_USER(s));
8644 break;
8645 case 5: /* ldrh */
8646 tmp = gen_ld16u(addr, IS_USER(s));
8647 break;
8648 case 6: /* ldrb */
8649 tmp = gen_ld8u(addr, IS_USER(s));
8650 break;
8651 case 7: /* ldrsh */
8652 tmp = gen_ld16s(addr, IS_USER(s));
8653 break;
8655 if (op >= 3) /* load */
8656 store_reg(s, rd, tmp);
8657 dead_tmp(addr);
8658 break;
8660 case 6:
8661 /* load/store word immediate offset */
8662 rd = insn & 7;
8663 rn = (insn >> 3) & 7;
8664 addr = load_reg(s, rn);
8665 val = (insn >> 4) & 0x7c;
8666 tcg_gen_addi_i32(addr, addr, val);
8668 if (insn & (1 << 11)) {
8669 /* load */
8670 tmp = gen_ld32(addr, IS_USER(s));
8671 store_reg(s, rd, tmp);
8672 } else {
8673 /* store */
8674 tmp = load_reg(s, rd);
8675 gen_st32(tmp, addr, IS_USER(s));
8677 dead_tmp(addr);
8678 break;
8680 case 7:
8681 /* load/store byte immediate offset */
8682 rd = insn & 7;
8683 rn = (insn >> 3) & 7;
8684 addr = load_reg(s, rn);
8685 val = (insn >> 6) & 0x1f;
8686 tcg_gen_addi_i32(addr, addr, val);
8688 if (insn & (1 << 11)) {
8689 /* load */
8690 tmp = gen_ld8u(addr, IS_USER(s));
8691 store_reg(s, rd, tmp);
8692 } else {
8693 /* store */
8694 tmp = load_reg(s, rd);
8695 gen_st8(tmp, addr, IS_USER(s));
8697 dead_tmp(addr);
8698 break;
8700 case 8:
8701 /* load/store halfword immediate offset */
8702 rd = insn & 7;
8703 rn = (insn >> 3) & 7;
8704 addr = load_reg(s, rn);
8705 val = (insn >> 5) & 0x3e;
8706 tcg_gen_addi_i32(addr, addr, val);
8708 if (insn & (1 << 11)) {
8709 /* load */
8710 tmp = gen_ld16u(addr, IS_USER(s));
8711 store_reg(s, rd, tmp);
8712 } else {
8713 /* store */
8714 tmp = load_reg(s, rd);
8715 gen_st16(tmp, addr, IS_USER(s));
8717 dead_tmp(addr);
8718 break;
8720 case 9:
8721 /* load/store from stack */
8722 rd = (insn >> 8) & 7;
8723 addr = load_reg(s, 13);
8724 val = (insn & 0xff) * 4;
8725 tcg_gen_addi_i32(addr, addr, val);
8727 if (insn & (1 << 11)) {
8728 /* load */
8729 tmp = gen_ld32(addr, IS_USER(s));
8730 store_reg(s, rd, tmp);
8731 } else {
8732 /* store */
8733 tmp = load_reg(s, rd);
8734 gen_st32(tmp, addr, IS_USER(s));
8736 dead_tmp(addr);
8737 break;
8739 case 10:
8740 /* add to high reg */
8741 rd = (insn >> 8) & 7;
8742 if (insn & (1 << 11)) {
8743 /* SP */
8744 tmp = load_reg(s, 13);
8745 } else {
8746 /* PC. bit 1 is ignored. */
8747 tmp = new_tmp();
8748 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8750 val = (insn & 0xff) * 4;
8751 tcg_gen_addi_i32(tmp, tmp, val);
8752 store_reg(s, rd, tmp);
8753 break;
8755 case 11:
8756 /* misc */
8757 op = (insn >> 8) & 0xf;
8758 switch (op) {
8759 case 0:
8760 /* adjust stack pointer */
8761 tmp = load_reg(s, 13);
8762 val = (insn & 0x7f) * 4;
8763 if (insn & (1 << 7))
8764 val = -(int32_t)val;
8765 tcg_gen_addi_i32(tmp, tmp, val);
8766 store_reg(s, 13, tmp);
8767 break;
8769 case 2: /* sign/zero extend. */
8770 ARCH(6);
8771 rd = insn & 7;
8772 rm = (insn >> 3) & 7;
8773 tmp = load_reg(s, rm);
8774 switch ((insn >> 6) & 3) {
8775 case 0: gen_sxth(tmp); break;
8776 case 1: gen_sxtb(tmp); break;
8777 case 2: gen_uxth(tmp); break;
8778 case 3: gen_uxtb(tmp); break;
8780 store_reg(s, rd, tmp);
8781 break;
8782 case 4: case 5: case 0xc: case 0xd:
8783 /* push/pop */
8784 addr = load_reg(s, 13);
8785 if (insn & (1 << 8))
8786 offset = 4;
8787 else
8788 offset = 0;
8789 for (i = 0; i < 8; i++) {
8790 if (insn & (1 << i))
8791 offset += 4;
8793 if ((insn & (1 << 11)) == 0) {
8794 tcg_gen_addi_i32(addr, addr, -offset);
8796 for (i = 0; i < 8; i++) {
8797 if (insn & (1 << i)) {
8798 if (insn & (1 << 11)) {
8799 /* pop */
8800 tmp = gen_ld32(addr, IS_USER(s));
8801 store_reg(s, i, tmp);
8802 } else {
8803 /* push */
8804 tmp = load_reg(s, i);
8805 gen_st32(tmp, addr, IS_USER(s));
8807 /* advance to the next address. */
8808 tcg_gen_addi_i32(addr, addr, 4);
8811 TCGV_UNUSED(tmp);
8812 if (insn & (1 << 8)) {
8813 if (insn & (1 << 11)) {
8814 /* pop pc */
8815 tmp = gen_ld32(addr, IS_USER(s));
8816 /* don't set the pc until the rest of the instruction
8817 has completed */
8818 } else {
8819 /* push lr */
8820 tmp = load_reg(s, 14);
8821 gen_st32(tmp, addr, IS_USER(s));
8823 tcg_gen_addi_i32(addr, addr, 4);
8825 if ((insn & (1 << 11)) == 0) {
8826 tcg_gen_addi_i32(addr, addr, -offset);
8828 /* write back the new stack pointer */
8829 store_reg(s, 13, addr);
8830 /* set the new PC value */
8831 if ((insn & 0x0900) == 0x0900)
8832 gen_bx(s, tmp);
8833 break;
8835 case 1: case 3: case 9: case 11: /* czb */
8836 rm = insn & 7;
8837 tmp = load_reg(s, rm);
8838 s->condlabel = gen_new_label();
8839 s->condjmp = 1;
8840 if (insn & (1 << 11))
8841 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8842 else
8843 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8844 dead_tmp(tmp);
8845 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8846 val = (uint32_t)s->pc + 2;
8847 val += offset;
8848 gen_jmp(s, val);
8849 break;
8851 case 15: /* IT, nop-hint. */
8852 if ((insn & 0xf) == 0) {
8853 gen_nop_hint(s, (insn >> 4) & 0xf);
8854 break;
8856 /* If Then. */
8857 s->condexec_cond = (insn >> 4) & 0xe;
8858 s->condexec_mask = insn & 0x1f;
8859 /* No actual code generated for this insn, just setup state. */
8860 break;
8862 case 0xe: /* bkpt */
8863 gen_set_condexec(s);
8864 gen_set_pc_im(s->pc - 2);
8865 gen_exception(EXCP_BKPT);
8866 s->is_jmp = DISAS_JUMP;
8867 break;
8869 case 0xa: /* rev */
8870 ARCH(6);
8871 rn = (insn >> 3) & 0x7;
8872 rd = insn & 0x7;
8873 tmp = load_reg(s, rn);
8874 switch ((insn >> 6) & 3) {
8875 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8876 case 1: gen_rev16(tmp); break;
8877 case 3: gen_revsh(tmp); break;
8878 default: goto illegal_op;
8880 store_reg(s, rd, tmp);
8881 break;
8883 case 6: /* cps */
8884 ARCH(6);
8885 if (IS_USER(s))
8886 break;
8887 if (IS_M(env)) {
8888 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8889 /* PRIMASK */
8890 if (insn & 1) {
8891 addr = tcg_const_i32(16);
8892 gen_helper_v7m_msr(cpu_env, addr, tmp);
8893 tcg_temp_free_i32(addr);
8895 /* FAULTMASK */
8896 if (insn & 2) {
8897 addr = tcg_const_i32(17);
8898 gen_helper_v7m_msr(cpu_env, addr, tmp);
8899 tcg_temp_free_i32(addr);
8901 tcg_temp_free_i32(tmp);
8902 gen_lookup_tb(s);
8903 } else {
8904 if (insn & (1 << 4))
8905 shift = CPSR_A | CPSR_I | CPSR_F;
8906 else
8907 shift = 0;
8908 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8910 break;
8912 default:
8913 goto undef;
8915 break;
8917 case 12:
8918 /* load/store multiple */
8919 rn = (insn >> 8) & 0x7;
8920 addr = load_reg(s, rn);
8921 for (i = 0; i < 8; i++) {
8922 if (insn & (1 << i)) {
8923 if (insn & (1 << 11)) {
8924 /* load */
8925 tmp = gen_ld32(addr, IS_USER(s));
8926 store_reg(s, i, tmp);
8927 } else {
8928 /* store */
8929 tmp = load_reg(s, i);
8930 gen_st32(tmp, addr, IS_USER(s));
8932 /* advance to the next address */
8933 tcg_gen_addi_i32(addr, addr, 4);
8936 /* Base register writeback. */
8937 if ((insn & (1 << rn)) == 0) {
8938 store_reg(s, rn, addr);
8939 } else {
8940 dead_tmp(addr);
8942 break;
8944 case 13:
8945 /* conditional branch or swi */
8946 cond = (insn >> 8) & 0xf;
8947 if (cond == 0xe)
8948 goto undef;
8950 if (cond == 0xf) {
8951 /* swi */
8952 gen_set_condexec(s);
8953 gen_set_pc_im(s->pc);
8954 s->is_jmp = DISAS_SWI;
8955 break;
8957 /* generate a conditional jump to next instruction */
8958 s->condlabel = gen_new_label();
8959 gen_test_cc(cond ^ 1, s->condlabel);
8960 s->condjmp = 1;
8962 /* jump to the offset */
8963 val = (uint32_t)s->pc + 2;
8964 offset = ((int32_t)insn << 24) >> 24;
8965 val += offset << 1;
8966 gen_jmp(s, val);
8967 break;
8969 case 14:
8970 if (insn & (1 << 11)) {
8971 if (disas_thumb2_insn(env, s, insn))
8972 goto undef32;
8973 break;
8975 /* unconditional branch */
8976 val = (uint32_t)s->pc;
8977 offset = ((int32_t)insn << 21) >> 21;
8978 val += (offset << 1) + 2;
8979 gen_jmp(s, val);
8980 break;
8982 case 15:
8983 if (disas_thumb2_insn(env, s, insn))
8984 goto undef32;
8985 break;
8987 return;
8988 undef32:
8989 gen_set_condexec(s);
8990 gen_set_pc_im(s->pc - 4);
8991 gen_exception(EXCP_UDEF);
8992 s->is_jmp = DISAS_JUMP;
8993 return;
8994 illegal_op:
8995 undef:
8996 gen_set_condexec(s);
8997 gen_set_pc_im(s->pc - 2);
8998 gen_exception(EXCP_UDEF);
8999 s->is_jmp = DISAS_JUMP;
9002 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9003 basic block 'tb'. If search_pc is TRUE, also generate PC
9004 information for each intermediate instruction. */
9005 static inline void gen_intermediate_code_internal(CPUState *env,
9006 TranslationBlock *tb,
9007 int search_pc)
9009 DisasContext dc1, *dc = &dc1;
9010 CPUBreakpoint *bp;
9011 uint16_t *gen_opc_end;
9012 int j, lj;
9013 target_ulong pc_start;
9014 uint32_t next_page_start;
9015 int num_insns;
9016 int max_insns;
9018 /* generate intermediate code */
9019 num_temps = 0;
9021 pc_start = tb->pc;
9023 dc->tb = tb;
9025 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9027 dc->is_jmp = DISAS_NEXT;
9028 dc->pc = pc_start;
9029 dc->singlestep_enabled = env->singlestep_enabled;
9030 dc->condjmp = 0;
9031 dc->thumb = env->thumb;
9032 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
9033 dc->condexec_cond = env->condexec_bits >> 4;
9034 #if !defined(CONFIG_USER_ONLY)
9035 if (IS_M(env)) {
9036 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
9037 } else {
9038 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
9040 #endif
9041 cpu_F0s = tcg_temp_new_i32();
9042 cpu_F1s = tcg_temp_new_i32();
9043 cpu_F0d = tcg_temp_new_i64();
9044 cpu_F1d = tcg_temp_new_i64();
9045 cpu_V0 = cpu_F0d;
9046 cpu_V1 = cpu_F1d;
9047 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9048 cpu_M0 = tcg_temp_new_i64();
9049 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9050 lj = -1;
9051 num_insns = 0;
9052 max_insns = tb->cflags & CF_COUNT_MASK;
9053 if (max_insns == 0)
9054 max_insns = CF_COUNT_MASK;
9056 gen_icount_start();
9057 /* Reset the conditional execution bits immediately. This avoids
9058 complications trying to do it at the end of the block. */
9059 if (env->condexec_bits)
9061 TCGv tmp = new_tmp();
9062 tcg_gen_movi_i32(tmp, 0);
9063 store_cpu_field(tmp, condexec_bits);
9065 do {
9066 #ifdef CONFIG_USER_ONLY
9067 /* Intercept jump to the magic kernel page. */
9068 if (dc->pc >= 0xffff0000) {
9069 /* We always get here via a jump, so know we are not in a
9070 conditional execution block. */
9071 gen_exception(EXCP_KERNEL_TRAP);
9072 dc->is_jmp = DISAS_UPDATE;
9073 break;
9075 #else
9076 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9077 /* We always get here via a jump, so know we are not in a
9078 conditional execution block. */
9079 gen_exception(EXCP_EXCEPTION_EXIT);
9080 dc->is_jmp = DISAS_UPDATE;
9081 break;
9083 #endif
9085 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9086 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9087 if (bp->pc == dc->pc) {
9088 gen_set_condexec(dc);
9089 gen_set_pc_im(dc->pc);
9090 gen_exception(EXCP_DEBUG);
9091 dc->is_jmp = DISAS_JUMP;
9092 /* Advance PC so that clearing the breakpoint will
9093 invalidate this TB. */
9094 dc->pc += 2;
9095 goto done_generating;
9096 break;
9100 if (search_pc) {
9101 j = gen_opc_ptr - gen_opc_buf;
9102 if (lj < j) {
9103 lj++;
9104 while (lj < j)
9105 gen_opc_instr_start[lj++] = 0;
9107 gen_opc_pc[lj] = dc->pc;
9108 gen_opc_instr_start[lj] = 1;
9109 gen_opc_icount[lj] = num_insns;
9112 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9113 gen_io_start();
9115 if (env->thumb) {
9116 disas_thumb_insn(env, dc);
9117 if (dc->condexec_mask) {
9118 dc->condexec_cond = (dc->condexec_cond & 0xe)
9119 | ((dc->condexec_mask >> 4) & 1);
9120 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9121 if (dc->condexec_mask == 0) {
9122 dc->condexec_cond = 0;
9125 } else {
9126 disas_arm_insn(env, dc);
9128 if (num_temps) {
9129 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
9130 num_temps = 0;
9133 if (dc->condjmp && !dc->is_jmp) {
9134 gen_set_label(dc->condlabel);
9135 dc->condjmp = 0;
9137 /* Translation stops when a conditional branch is encountered.
9138 * Otherwise the subsequent code could get translated several times.
9139 * Also stop translation when a page boundary is reached. This
9140 * ensures prefetch aborts occur at the right place. */
9141 num_insns ++;
9142 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9143 !env->singlestep_enabled &&
9144 !singlestep &&
9145 dc->pc < next_page_start &&
9146 num_insns < max_insns);
9148 if (tb->cflags & CF_LAST_IO) {
9149 if (dc->condjmp) {
9150 /* FIXME: This can theoretically happen with self-modifying
9151 code. */
9152 cpu_abort(env, "IO on conditional branch instruction");
9154 gen_io_end();
9157 /* At this stage dc->condjmp will only be set when the skipped
9158 instruction was a conditional branch or trap, and the PC has
9159 already been written. */
9160 if (unlikely(env->singlestep_enabled)) {
9161 /* Make sure the pc is updated, and raise a debug exception. */
9162 if (dc->condjmp) {
9163 gen_set_condexec(dc);
9164 if (dc->is_jmp == DISAS_SWI) {
9165 gen_exception(EXCP_SWI);
9166 } else {
9167 gen_exception(EXCP_DEBUG);
9169 gen_set_label(dc->condlabel);
9171 if (dc->condjmp || !dc->is_jmp) {
9172 gen_set_pc_im(dc->pc);
9173 dc->condjmp = 0;
9175 gen_set_condexec(dc);
9176 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9177 gen_exception(EXCP_SWI);
9178 } else {
9179 /* FIXME: Single stepping a WFI insn will not halt
9180 the CPU. */
9181 gen_exception(EXCP_DEBUG);
9183 } else {
9184 /* While branches must always occur at the end of an IT block,
9185 there are a few other things that can cause us to terminate
9186 the TB in the middel of an IT block:
9187 - Exception generating instructions (bkpt, swi, undefined).
9188 - Page boundaries.
9189 - Hardware watchpoints.
9190 Hardware breakpoints have already been handled and skip this code.
9192 gen_set_condexec(dc);
9193 switch(dc->is_jmp) {
9194 case DISAS_NEXT:
9195 gen_goto_tb(dc, 1, dc->pc);
9196 break;
9197 default:
9198 case DISAS_JUMP:
9199 case DISAS_UPDATE:
9200 /* indicate that the hash table must be used to find the next TB */
9201 tcg_gen_exit_tb(0);
9202 break;
9203 case DISAS_TB_JUMP:
9204 /* nothing more to generate */
9205 break;
9206 case DISAS_WFI:
9207 gen_helper_wfi();
9208 break;
9209 case DISAS_SWI:
9210 gen_exception(EXCP_SWI);
9211 break;
9213 if (dc->condjmp) {
9214 gen_set_label(dc->condlabel);
9215 gen_set_condexec(dc);
9216 gen_goto_tb(dc, 1, dc->pc);
9217 dc->condjmp = 0;
9221 done_generating:
9222 gen_icount_end(tb, num_insns);
9223 *gen_opc_ptr = INDEX_op_end;
9225 #ifdef DEBUG_DISAS
9226 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9227 qemu_log("----------------\n");
9228 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9229 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9230 qemu_log("\n");
9232 #endif
9233 if (search_pc) {
9234 j = gen_opc_ptr - gen_opc_buf;
9235 lj++;
9236 while (lj <= j)
9237 gen_opc_instr_start[lj++] = 0;
9238 } else {
9239 tb->size = dc->pc - pc_start;
9240 tb->icount = num_insns;
9244 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9246 gen_intermediate_code_internal(env, tb, 0);
9249 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9251 gen_intermediate_code_internal(env, tb, 1);
9254 static const char *cpu_mode_names[16] = {
9255 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9256 "???", "???", "???", "und", "???", "???", "???", "sys"
9259 void cpu_dump_state(CPUState *env, FILE *f,
9260 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9261 int flags)
9263 int i;
9264 #if 0
9265 union {
9266 uint32_t i;
9267 float s;
9268 } s0, s1;
9269 CPU_DoubleU d;
9270 /* ??? This assumes float64 and double have the same layout.
9271 Oh well, it's only debug dumps. */
9272 union {
9273 float64 f64;
9274 double d;
9275 } d0;
9276 #endif
9277 uint32_t psr;
9279 for(i=0;i<16;i++) {
9280 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9281 if ((i % 4) == 3)
9282 cpu_fprintf(f, "\n");
9283 else
9284 cpu_fprintf(f, " ");
9286 psr = cpsr_read(env);
9287 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9288 psr,
9289 psr & (1 << 31) ? 'N' : '-',
9290 psr & (1 << 30) ? 'Z' : '-',
9291 psr & (1 << 29) ? 'C' : '-',
9292 psr & (1 << 28) ? 'V' : '-',
9293 psr & CPSR_T ? 'T' : 'A',
9294 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9296 #if 0
9297 for (i = 0; i < 16; i++) {
9298 d.d = env->vfp.regs[i];
9299 s0.i = d.l.lower;
9300 s1.i = d.l.upper;
9301 d0.f64 = d.d;
9302 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9303 i * 2, (int)s0.i, s0.s,
9304 i * 2 + 1, (int)s1.i, s1.s,
9305 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9306 d0.d);
9308 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9309 #endif
9312 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9313 unsigned long searched_pc, int pc_pos, void *puc)
9315 env->regs[15] = gen_opc_pc[pc_pos];