Convert CPSR pseudo-registers into TCG registers.
[qemu/navara.git] / target-arm / translate.c
blobbbdd5b483e35d2d4d7bc51085b684635c3692f2b
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_5 arm_feature(env, ARM_FEATURE_V5)
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext {
48 target_ulong pc;
49 int is_jmp;
50 /* Nonzero if this instruction has been conditionally skipped. */
51 int condjmp;
52 /* The label that will be jumped to when the instruction is skipped. */
53 int condlabel;
54 /* Thumb-2 condtional execution bits. */
55 int condexec_mask;
56 int condexec_cond;
57 struct TranslationBlock *tb;
58 int singlestep_enabled;
59 int thumb;
60 #if !defined(CONFIG_USER_ONLY)
61 int user;
62 #endif
63 } DisasContext;
65 #if defined(CONFIG_USER_ONLY)
66 #define IS_USER(s) 1
67 #else
68 #define IS_USER(s) (s->user)
69 #endif
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
73 #define DISAS_WFI 4
74 #define DISAS_SWI 5
76 static TCGv_ptr cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
79 static TCGv_i32 cpu_R[16];
80 /* CPSR flags, used for efficiency */
81 static TCGv_i32 cpu_CF, cpu_VF, cpu_NF, cpu_ZF;
83 /* FIXME: These should be removed. */
84 static TCGv cpu_F0s, cpu_F1s;
85 static TCGv_i64 cpu_F0d, cpu_F1d;
87 #include "gen-icount.h"
89 static const char *regnames[] =
90 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
91 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
93 /* initialize TCG globals. */
94 void arm_translate_init(void)
96 int i;
98 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
100 for (i = 0; i < 16; i++) {
101 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
102 offsetof(CPUState, regs[i]),
103 regnames[i]);
106 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, CF), "CF");
107 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, VF), "VF");
108 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, NF), "NF");
109 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, ZF), "ZF");
111 #define GEN_HELPER 2
112 #include "helpers.h"
115 static int num_temps;
117 /* Allocate a temporary variable. */
118 static TCGv_i32 new_tmp(void)
120 num_temps++;
121 return tcg_temp_new_i32();
124 /* Release a temporary variable. */
125 static void dead_tmp(TCGv tmp)
127 tcg_temp_free(tmp);
128 num_temps--;
131 static inline TCGv load_cpu_offset(int offset)
133 TCGv tmp = new_tmp();
134 tcg_gen_ld_i32(tmp, cpu_env, offset);
135 return tmp;
138 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
140 static inline void store_cpu_offset(TCGv var, int offset)
142 tcg_gen_st_i32(var, cpu_env, offset);
143 dead_tmp(var);
146 #define store_cpu_field(var, name) \
147 store_cpu_offset(var, offsetof(CPUState, name))
149 /* Set a variable to the value of a CPU register. */
150 static void load_reg_var(DisasContext *s, TCGv var, int reg)
152 if (reg == 15) {
153 uint32_t addr;
154 /* normaly, since we updated PC, we need only to add one insn */
155 if (s->thumb)
156 addr = (long)s->pc + 2;
157 else
158 addr = (long)s->pc + 4;
159 tcg_gen_movi_i32(var, addr);
160 } else {
161 tcg_gen_mov_i32(var, cpu_R[reg]);
165 /* Create a new temporary and set it to the value of a CPU register. */
166 static inline TCGv load_reg(DisasContext *s, int reg)
168 TCGv tmp = new_tmp();
169 load_reg_var(s, tmp, reg);
170 return tmp;
173 /* Set a CPU register. The source must be a temporary and will be
174 marked as dead. */
175 static void store_reg(DisasContext *s, int reg, TCGv var)
177 if (reg == 15) {
178 tcg_gen_andi_i32(var, var, ~1);
179 s->is_jmp = DISAS_JUMP;
181 tcg_gen_mov_i32(cpu_R[reg], var);
182 dead_tmp(var);
185 /* Value extensions. */
186 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
187 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
188 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
189 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
191 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
192 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
195 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
196 /* Set NZCV flags from the high 4 bits of var. */
197 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
199 static void gen_exception(int excp)
201 TCGv tmp = new_tmp();
202 tcg_gen_movi_i32(tmp, excp);
203 gen_helper_exception(tmp);
204 dead_tmp(tmp);
207 static void gen_smul_dual(TCGv a, TCGv b)
209 TCGv tmp1 = new_tmp();
210 TCGv tmp2 = new_tmp();
211 tcg_gen_ext16s_i32(tmp1, a);
212 tcg_gen_ext16s_i32(tmp2, b);
213 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
214 dead_tmp(tmp2);
215 tcg_gen_sari_i32(a, a, 16);
216 tcg_gen_sari_i32(b, b, 16);
217 tcg_gen_mul_i32(b, b, a);
218 tcg_gen_mov_i32(a, tmp1);
219 dead_tmp(tmp1);
222 /* Byteswap each halfword. */
223 static void gen_rev16(TCGv var)
225 TCGv tmp = new_tmp();
226 tcg_gen_shri_i32(tmp, var, 8);
227 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
228 tcg_gen_shli_i32(var, var, 8);
229 tcg_gen_andi_i32(var, var, 0xff00ff00);
230 tcg_gen_or_i32(var, var, tmp);
231 dead_tmp(tmp);
234 /* Byteswap low halfword and sign extend. */
235 static void gen_revsh(TCGv var)
237 TCGv tmp = new_tmp();
238 tcg_gen_shri_i32(tmp, var, 8);
239 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
240 tcg_gen_shli_i32(var, var, 8);
241 tcg_gen_ext8s_i32(var, var);
242 tcg_gen_or_i32(var, var, tmp);
243 dead_tmp(tmp);
246 /* Unsigned bitfield extract. */
247 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
249 if (shift)
250 tcg_gen_shri_i32(var, var, shift);
251 tcg_gen_andi_i32(var, var, mask);
254 /* Signed bitfield extract. */
255 static void gen_sbfx(TCGv var, int shift, int width)
257 uint32_t signbit;
259 if (shift)
260 tcg_gen_sari_i32(var, var, shift);
261 if (shift + width < 32) {
262 signbit = 1u << (width - 1);
263 tcg_gen_andi_i32(var, var, (1u << width) - 1);
264 tcg_gen_xori_i32(var, var, signbit);
265 tcg_gen_subi_i32(var, var, signbit);
269 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
270 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
272 tcg_gen_andi_i32(val, val, mask);
273 tcg_gen_shli_i32(val, val, shift);
274 tcg_gen_andi_i32(base, base, ~(mask << shift));
275 tcg_gen_or_i32(dest, base, val);
278 /* Round the top 32 bits of a 64-bit value. */
279 static void gen_roundqd(TCGv a, TCGv b)
281 tcg_gen_shri_i32(a, a, 31);
282 tcg_gen_add_i32(a, a, b);
285 /* FIXME: Most targets have native widening multiplication.
286 It would be good to use that instead of a full wide multiply. */
287 /* 32x32->64 multiply. Marks inputs as dead. */
288 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
290 TCGv_i64 tmp1 = tcg_temp_new_i64();
291 TCGv_i64 tmp2 = tcg_temp_new_i64();
293 tcg_gen_extu_i32_i64(tmp1, a);
294 dead_tmp(a);
295 tcg_gen_extu_i32_i64(tmp2, b);
296 dead_tmp(b);
297 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
298 return tmp1;
301 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
303 TCGv_i64 tmp1 = tcg_temp_new_i64();
304 TCGv_i64 tmp2 = tcg_temp_new_i64();
306 tcg_gen_ext_i32_i64(tmp1, a);
307 dead_tmp(a);
308 tcg_gen_ext_i32_i64(tmp2, b);
309 dead_tmp(b);
310 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
311 return tmp1;
314 /* Unsigned 32x32->64 multiply. */
315 static void gen_mull(TCGv a, TCGv b)
317 TCGv_i64 tmp1 = tcg_temp_new_i64();
318 TCGv_i64 tmp2 = tcg_temp_new_i64();
320 tcg_gen_extu_i32_i64(tmp1, a);
321 tcg_gen_extu_i32_i64(tmp2, b);
322 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
323 tcg_gen_trunc_i64_i32(a, tmp1);
324 tcg_gen_shri_i64(tmp1, tmp1, 32);
325 tcg_gen_trunc_i64_i32(b, tmp1);
328 /* Signed 32x32->64 multiply. */
329 static void gen_imull(TCGv a, TCGv b)
331 TCGv_i64 tmp1 = tcg_temp_new_i64();
332 TCGv_i64 tmp2 = tcg_temp_new_i64();
334 tcg_gen_ext_i32_i64(tmp1, a);
335 tcg_gen_ext_i32_i64(tmp2, b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 tcg_gen_trunc_i64_i32(a, tmp1);
338 tcg_gen_shri_i64(tmp1, tmp1, 32);
339 tcg_gen_trunc_i64_i32(b, tmp1);
342 /* Swap low and high halfwords. */
343 static void gen_swap_half(TCGv var)
345 TCGv tmp = new_tmp();
346 tcg_gen_shri_i32(tmp, var, 16);
347 tcg_gen_shli_i32(var, var, 16);
348 tcg_gen_or_i32(var, var, tmp);
349 dead_tmp(tmp);
352 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
353 tmp = (t0 ^ t1) & 0x8000;
354 t0 &= ~0x8000;
355 t1 &= ~0x8000;
356 t0 = (t0 + t1) ^ tmp;
359 static void gen_add16(TCGv t0, TCGv t1)
361 TCGv tmp = new_tmp();
362 tcg_gen_xor_i32(tmp, t0, t1);
363 tcg_gen_andi_i32(tmp, tmp, 0x8000);
364 tcg_gen_andi_i32(t0, t0, ~0x8000);
365 tcg_gen_andi_i32(t1, t1, ~0x8000);
366 tcg_gen_add_i32(t0, t0, t1);
367 tcg_gen_xor_i32(t0, t0, tmp);
368 dead_tmp(tmp);
369 dead_tmp(t1);
372 #define gen_set_CF(var) tcg_gen_mov_i32(cpu_CF, var)
374 /* Set CF to the top bit of var. */
375 static void gen_set_CF_bit31(TCGv var)
377 tcg_gen_shri_i32(cpu_CF, var, 31);
380 /* Set N and Z flags from var. */
381 static inline void gen_logic_CC(TCGv var)
383 tcg_gen_mov_i32(cpu_NF, var);
384 tcg_gen_mov_i32(cpu_ZF, var);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
390 tcg_gen_add_i32(dest, t0, t1);
391 tcg_gen_add_i32(dest, dest, cpu_CF);
394 /* dest = T0 - T1 + CF - 1. */
395 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
397 tcg_gen_sub_i32(dest, t0, t1);
398 tcg_gen_add_i32(dest, dest, cpu_CF);
399 tcg_gen_subi_i32(dest, dest, 1);
402 /* T0 &= ~T1. Clobbers T1. */
403 /* FIXME: Implement bic natively. */
404 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
406 TCGv tmp = new_tmp();
407 tcg_gen_not_i32(tmp, t1);
408 tcg_gen_and_i32(dest, t0, tmp);
409 dead_tmp(tmp);
412 /* FIXME: Implement this natively. */
413 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
415 static void shifter_out_im(TCGv var, int shift)
417 TCGv tmp = new_tmp();
418 if (shift == 0) {
419 tcg_gen_andi_i32(tmp, var, 1);
420 } else {
421 tcg_gen_shri_i32(tmp, var, shift);
422 if (shift != 31)
423 tcg_gen_andi_i32(tmp, tmp, 1);
425 gen_set_CF(tmp);
426 dead_tmp(tmp);
429 /* Shift by immediate. Includes special handling for shift == 0. */
430 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
432 switch (shiftop) {
433 case 0: /* LSL */
434 if (shift != 0) {
435 if (flags)
436 shifter_out_im(var, 32 - shift);
437 tcg_gen_shli_i32(var, var, shift);
439 break;
440 case 1: /* LSR */
441 if (shift == 0) {
442 if (flags) {
443 tcg_gen_shri_i32(var, var, 31);
444 gen_set_CF(var);
446 tcg_gen_movi_i32(var, 0);
447 } else {
448 if (flags)
449 shifter_out_im(var, shift - 1);
450 tcg_gen_shri_i32(var, var, shift);
452 break;
453 case 2: /* ASR */
454 if (shift == 0)
455 shift = 32;
456 if (flags)
457 shifter_out_im(var, shift - 1);
458 if (shift == 32)
459 shift = 31;
460 tcg_gen_sari_i32(var, var, shift);
461 break;
462 case 3: /* ROR/RRX */
463 if (shift != 0) {
464 if (flags)
465 shifter_out_im(var, shift - 1);
466 tcg_gen_rotri_i32(var, var, shift); break;
467 } else {
468 TCGv tmp = new_tmp();
469 tcg_gen_mov_i32(tmp, cpu_CF);
470 if (flags)
471 shifter_out_im(var, 0);
472 tcg_gen_shri_i32(var, var, 1);
473 tcg_gen_shli_i32(tmp, tmp, 31);
474 tcg_gen_or_i32(var, var, tmp);
475 dead_tmp(tmp);
480 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
481 TCGv shift, int flags)
483 if (flags) {
484 switch (shiftop) {
485 case 0: gen_helper_shl_cc(var, var, shift); break;
486 case 1: gen_helper_shr_cc(var, var, shift); break;
487 case 2: gen_helper_sar_cc(var, var, shift); break;
488 case 3: gen_helper_ror_cc(var, var, shift); break;
490 } else {
491 switch (shiftop) {
492 case 0: gen_helper_shl(var, var, shift); break;
493 case 1: gen_helper_shr(var, var, shift); break;
494 case 2: gen_helper_sar(var, var, shift); break;
495 case 3: gen_helper_ror(var, var, shift); break;
498 dead_tmp(shift);
501 #define PAS_OP(pfx) \
502 switch (op2) { \
503 case 0: gen_pas_helper(glue(pfx,add16)); break; \
504 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
505 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
506 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
507 case 4: gen_pas_helper(glue(pfx,add8)); break; \
508 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
510 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
512 TCGv_ptr tmp;
514 switch (op1) {
515 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
516 case 1:
517 tmp = tcg_temp_new_ptr();
518 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
519 PAS_OP(s)
520 break;
521 case 5:
522 tmp = tcg_temp_new_ptr();
523 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
524 PAS_OP(u)
525 break;
526 #undef gen_pas_helper
527 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
528 case 2:
529 PAS_OP(q);
530 break;
531 case 3:
532 PAS_OP(sh);
533 break;
534 case 6:
535 PAS_OP(uq);
536 break;
537 case 7:
538 PAS_OP(uh);
539 break;
540 #undef gen_pas_helper
543 #undef PAS_OP
545 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
546 #define PAS_OP(pfx) \
547 switch (op2) { \
548 case 0: gen_pas_helper(glue(pfx,add8)); break; \
549 case 1: gen_pas_helper(glue(pfx,add16)); break; \
550 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
551 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
552 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
553 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
555 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
557 TCGv_ptr tmp;
559 switch (op1) {
560 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
561 case 0:
562 tmp = tcg_temp_new_ptr();
563 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
564 PAS_OP(s)
565 break;
566 case 4:
567 tmp = tcg_temp_new_ptr();
568 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
569 PAS_OP(u)
570 break;
571 #undef gen_pas_helper
572 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
573 case 1:
574 PAS_OP(q);
575 break;
576 case 2:
577 PAS_OP(sh);
578 break;
579 case 5:
580 PAS_OP(uq);
581 break;
582 case 6:
583 PAS_OP(uh);
584 break;
585 #undef gen_pas_helper
588 #undef PAS_OP
590 static void gen_test_cc(int cc, int label)
592 TCGv tmp;
593 int inv;
595 switch (cc) {
596 case 0: /* eq: Z */
597 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
598 break;
599 case 1: /* ne: !Z */
600 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
601 break;
602 case 2: /* cs: C */
603 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
604 break;
605 case 3: /* cc: !C */
606 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
607 break;
608 case 4: /* mi: N */
609 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
610 break;
611 case 5: /* pl: !N */
612 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
613 break;
614 case 6: /* vs: V */
615 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
616 break;
617 case 7: /* vc: !V */
618 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
619 break;
620 case 8: /* hi: C && !Z */
621 inv = gen_new_label();
622 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
623 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
624 gen_set_label(inv);
625 break;
626 case 9: /* ls: !C || Z */
627 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
628 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
629 break;
630 case 10: /* ge: N == V -> N ^ V == 0 */
631 tmp = new_tmp();
632 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
633 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
634 dead_tmp(tmp);
635 break;
636 case 11: /* lt: N != V -> N ^ V != 0 */
637 tmp = new_tmp();
638 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
639 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
640 dead_tmp(tmp);
641 break;
642 case 12: /* gt: !Z && N == V */
643 inv = gen_new_label();
644 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
645 tmp = new_tmp();
646 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
647 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
648 dead_tmp(tmp);
649 gen_set_label(inv);
650 break;
651 case 13: /* le: Z || N != V */
652 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
653 tmp = new_tmp();
654 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
655 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
656 dead_tmp(tmp);
657 break;
658 default:
659 fprintf(stderr, "Bad condition code 0x%x\n", cc);
660 abort();
664 static const uint8_t table_logic_cc[16] = {
665 1, /* and */
666 1, /* xor */
667 0, /* sub */
668 0, /* rsb */
669 0, /* add */
670 0, /* adc */
671 0, /* sbc */
672 0, /* rsc */
673 1, /* andl */
674 1, /* xorl */
675 0, /* cmp */
676 0, /* cmn */
677 1, /* orr */
678 1, /* mov */
679 1, /* bic */
680 1, /* mvn */
683 /* Set PC and Thumb state from an immediate address. */
684 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
686 TCGv tmp;
688 s->is_jmp = DISAS_UPDATE;
689 if (s->thumb != (addr & 1)) {
690 tmp = new_tmp();
691 tcg_gen_movi_i32(tmp, addr & 1);
692 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
693 dead_tmp(tmp);
695 tcg_gen_mov_i32(cpu_R[15], addr & ~1);
698 /* Set PC and Thumb state from var. var is marked as dead. */
699 static inline void gen_bx(DisasContext *s, TCGv var)
701 s->is_jmp = DISAS_UPDATE;
702 tcg_gen_andi_i32(cpu_R[15], var, ~1);
703 tcg_gen_andi_i32(var, var, 1);
704 store_cpu_field(var, thumb);
707 /* Variant of store_reg which uses branch&exchange logic when storing
708 to r15 in ARM architecture v7 and above. The source must be a temporary
709 and will be marked as dead. */
710 static inline void store_reg_bx(CPUState *env, DisasContext *s,
711 int reg, TCGv var)
713 if (reg == 15 && ENABLE_ARCH_7) {
714 gen_bx(s, var);
715 } else {
716 store_reg(s, reg, var);
720 static inline TCGv gen_ld8s(TCGv addr, int index)
722 TCGv tmp = new_tmp();
723 tcg_gen_qemu_ld8s(tmp, addr, index);
724 return tmp;
726 static inline TCGv gen_ld8u(TCGv addr, int index)
728 TCGv tmp = new_tmp();
729 tcg_gen_qemu_ld8u(tmp, addr, index);
730 return tmp;
732 static inline TCGv gen_ld16s(TCGv addr, int index)
734 TCGv tmp = new_tmp();
735 tcg_gen_qemu_ld16s(tmp, addr, index);
736 return tmp;
738 static inline TCGv gen_ld16u(TCGv addr, int index)
740 TCGv tmp = new_tmp();
741 tcg_gen_qemu_ld16u(tmp, addr, index);
742 return tmp;
744 static inline TCGv gen_ld32(TCGv addr, int index)
746 TCGv tmp = new_tmp();
747 tcg_gen_qemu_ld32u(tmp, addr, index);
748 return tmp;
750 static inline void gen_st8(TCGv val, TCGv addr, int index)
752 tcg_gen_qemu_st8(val, addr, index);
753 dead_tmp(val);
755 static inline void gen_st16(TCGv val, TCGv addr, int index)
757 tcg_gen_qemu_st16(val, addr, index);
758 dead_tmp(val);
760 static inline void gen_st32(TCGv val, TCGv addr, int index)
762 tcg_gen_qemu_st32(val, addr, index);
763 dead_tmp(val);
766 static inline void gen_set_pc_im(uint32_t val)
768 tcg_gen_movi_i32(cpu_R[15], val);
771 /* Force a TB lookup after an instruction that changes the CPU state. */
772 static inline void gen_lookup_tb(DisasContext *s)
774 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
775 s->is_jmp = DISAS_UPDATE;
778 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
779 TCGv var)
781 int val, rm, shift, shiftop;
782 TCGv offset;
784 if (!(insn & (1 << 25))) {
785 /* immediate */
786 val = insn & 0xfff;
787 if (!(insn & (1 << 23)))
788 val = -val;
789 if (val != 0)
790 tcg_gen_addi_i32(var, var, val);
791 } else {
792 /* shift/register */
793 rm = (insn) & 0xf;
794 shift = (insn >> 7) & 0x1f;
795 shiftop = (insn >> 5) & 3;
796 offset = load_reg(s, rm);
797 gen_arm_shift_im(offset, shiftop, shift, 0);
798 if (!(insn & (1 << 23)))
799 tcg_gen_sub_i32(var, var, offset);
800 else
801 tcg_gen_add_i32(var, var, offset);
802 dead_tmp(offset);
806 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
807 int extra, TCGv var)
809 int val, rm;
810 TCGv offset;
812 if (insn & (1 << 22)) {
813 /* immediate */
814 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
815 if (!(insn & (1 << 23)))
816 val = -val;
817 val += extra;
818 if (val != 0)
819 tcg_gen_addi_i32(var, var, val);
820 } else {
821 /* register */
822 if (extra)
823 tcg_gen_addi_i32(var, var, extra);
824 rm = (insn) & 0xf;
825 offset = load_reg(s, rm);
826 if (!(insn & (1 << 23)))
827 tcg_gen_sub_i32(var, var, offset);
828 else
829 tcg_gen_add_i32(var, var, offset);
830 dead_tmp(offset);
834 #define VFP_OP2(name) \
835 static inline void gen_vfp_##name(int dp) \
837 if (dp) \
838 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
839 else \
840 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
843 VFP_OP2(add)
844 VFP_OP2(sub)
845 VFP_OP2(mul)
846 VFP_OP2(div)
848 #undef VFP_OP2
850 static inline void gen_vfp_abs(int dp)
852 if (dp)
853 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
854 else
855 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
858 static inline void gen_vfp_neg(int dp)
860 if (dp)
861 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
862 else
863 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
866 static inline void gen_vfp_sqrt(int dp)
868 if (dp)
869 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
870 else
871 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
874 static inline void gen_vfp_cmp(int dp)
876 if (dp)
877 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
878 else
879 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
882 static inline void gen_vfp_cmpe(int dp)
884 if (dp)
885 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
886 else
887 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
890 static inline void gen_vfp_F1_ld0(int dp)
892 if (dp)
893 tcg_gen_movi_i64(cpu_F1d, 0);
894 else
895 tcg_gen_movi_i32(cpu_F1s, 0);
898 static inline void gen_vfp_uito(int dp)
900 if (dp)
901 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
902 else
903 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
906 static inline void gen_vfp_sito(int dp)
908 if (dp)
909 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
910 else
911 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
914 static inline void gen_vfp_toui(int dp)
916 if (dp)
917 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
918 else
919 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
922 static inline void gen_vfp_touiz(int dp)
924 if (dp)
925 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
926 else
927 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
930 static inline void gen_vfp_tosi(int dp)
932 if (dp)
933 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
934 else
935 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
938 static inline void gen_vfp_tosiz(int dp)
940 if (dp)
941 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
942 else
943 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
946 #define VFP_GEN_FIX(name) \
947 static inline void gen_vfp_##name(int dp, int shift) \
949 if (dp) \
950 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
951 else \
952 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
954 VFP_GEN_FIX(tosh)
955 VFP_GEN_FIX(tosl)
956 VFP_GEN_FIX(touh)
957 VFP_GEN_FIX(toul)
958 VFP_GEN_FIX(shto)
959 VFP_GEN_FIX(slto)
960 VFP_GEN_FIX(uhto)
961 VFP_GEN_FIX(ulto)
962 #undef VFP_GEN_FIX
964 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
966 if (dp)
967 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
968 else
969 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
972 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
974 if (dp)
975 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
976 else
977 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
980 static inline long
981 vfp_reg_offset (int dp, int reg)
983 if (dp)
984 return offsetof(CPUARMState, vfp.regs[reg]);
985 else if (reg & 1) {
986 return offsetof(CPUARMState, vfp.regs[reg >> 1])
987 + offsetof(CPU_DoubleU, l.upper);
988 } else {
989 return offsetof(CPUARMState, vfp.regs[reg >> 1])
990 + offsetof(CPU_DoubleU, l.lower);
994 /* Return the offset of a 32-bit piece of a NEON register.
995 zero is the least significant end of the register. */
996 static inline long
997 neon_reg_offset (int reg, int n)
999 int sreg;
1000 sreg = reg * 2 + n;
1001 return vfp_reg_offset(0, sreg);
1004 static TCGv neon_load_reg(int reg, int pass)
1006 TCGv tmp = new_tmp();
1007 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1008 return tmp;
1011 static void neon_store_reg(int reg, int pass, TCGv var)
1013 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1014 dead_tmp(var);
1017 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1019 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1022 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1024 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1027 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1028 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1029 #define tcg_gen_st_f32 tcg_gen_st_i32
1030 #define tcg_gen_st_f64 tcg_gen_st_i64
1032 static inline void gen_mov_F0_vreg(int dp, int reg)
1034 if (dp)
1035 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1036 else
1037 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1040 static inline void gen_mov_F1_vreg(int dp, int reg)
1042 if (dp)
1043 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1044 else
1045 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1048 static inline void gen_mov_vreg_F0(int dp, int reg)
1050 if (dp)
1051 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1052 else
1053 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1056 #define ARM_CP_RW_BIT (1 << 20)
1058 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1060 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1063 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1065 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1068 static inline TCGv iwmmxt_load_creg(int reg)
1070 TCGv var = new_tmp();
1071 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1072 return var;
1075 static inline void iwmmxt_store_creg(int reg, TCGv var)
1077 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1080 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1082 iwmmxt_store_reg(cpu_M0, rn);
1085 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1087 iwmmxt_load_reg(cpu_M0, rn);
1090 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1092 iwmmxt_load_reg(cpu_V1, rn);
1093 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1096 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1098 iwmmxt_load_reg(cpu_V1, rn);
1099 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1102 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1104 iwmmxt_load_reg(cpu_V1, rn);
1105 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1108 #define IWMMXT_OP(name) \
1109 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1111 iwmmxt_load_reg(cpu_V1, rn); \
1112 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1115 #define IWMMXT_OP_ENV(name) \
1116 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1118 iwmmxt_load_reg(cpu_V1, rn); \
1119 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1122 #define IWMMXT_OP_ENV_SIZE(name) \
1123 IWMMXT_OP_ENV(name##b) \
1124 IWMMXT_OP_ENV(name##w) \
1125 IWMMXT_OP_ENV(name##l)
1127 #define IWMMXT_OP_ENV1(name) \
1128 static inline void gen_op_iwmmxt_##name##_M0(void) \
1130 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1133 IWMMXT_OP(maddsq)
1134 IWMMXT_OP(madduq)
1135 IWMMXT_OP(sadb)
1136 IWMMXT_OP(sadw)
1137 IWMMXT_OP(mulslw)
1138 IWMMXT_OP(mulshw)
1139 IWMMXT_OP(mululw)
1140 IWMMXT_OP(muluhw)
1141 IWMMXT_OP(macsw)
1142 IWMMXT_OP(macuw)
1144 IWMMXT_OP_ENV_SIZE(unpackl)
1145 IWMMXT_OP_ENV_SIZE(unpackh)
1147 IWMMXT_OP_ENV1(unpacklub)
1148 IWMMXT_OP_ENV1(unpackluw)
1149 IWMMXT_OP_ENV1(unpacklul)
1150 IWMMXT_OP_ENV1(unpackhub)
1151 IWMMXT_OP_ENV1(unpackhuw)
1152 IWMMXT_OP_ENV1(unpackhul)
1153 IWMMXT_OP_ENV1(unpacklsb)
1154 IWMMXT_OP_ENV1(unpacklsw)
1155 IWMMXT_OP_ENV1(unpacklsl)
1156 IWMMXT_OP_ENV1(unpackhsb)
1157 IWMMXT_OP_ENV1(unpackhsw)
1158 IWMMXT_OP_ENV1(unpackhsl)
1160 IWMMXT_OP_ENV_SIZE(cmpeq)
1161 IWMMXT_OP_ENV_SIZE(cmpgtu)
1162 IWMMXT_OP_ENV_SIZE(cmpgts)
1164 IWMMXT_OP_ENV_SIZE(mins)
1165 IWMMXT_OP_ENV_SIZE(minu)
1166 IWMMXT_OP_ENV_SIZE(maxs)
1167 IWMMXT_OP_ENV_SIZE(maxu)
1169 IWMMXT_OP_ENV_SIZE(subn)
1170 IWMMXT_OP_ENV_SIZE(addn)
1171 IWMMXT_OP_ENV_SIZE(subu)
1172 IWMMXT_OP_ENV_SIZE(addu)
1173 IWMMXT_OP_ENV_SIZE(subs)
1174 IWMMXT_OP_ENV_SIZE(adds)
1176 IWMMXT_OP_ENV(avgb0)
1177 IWMMXT_OP_ENV(avgb1)
1178 IWMMXT_OP_ENV(avgw0)
1179 IWMMXT_OP_ENV(avgw1)
1181 IWMMXT_OP(msadb)
1183 IWMMXT_OP_ENV(packuw)
1184 IWMMXT_OP_ENV(packul)
1185 IWMMXT_OP_ENV(packuq)
1186 IWMMXT_OP_ENV(packsw)
1187 IWMMXT_OP_ENV(packsl)
1188 IWMMXT_OP_ENV(packsq)
1190 static void gen_op_iwmmxt_set_mup(void)
1192 TCGv tmp;
1193 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1194 tcg_gen_ori_i32(tmp, tmp, 2);
1195 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1198 static void gen_op_iwmmxt_set_cup(void)
1200 TCGv tmp;
1201 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1202 tcg_gen_ori_i32(tmp, tmp, 1);
1203 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1206 static void gen_op_iwmmxt_setpsr_nz(void)
1208 TCGv tmp = new_tmp();
1209 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1210 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1213 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1215 iwmmxt_load_reg(cpu_V1, rn);
1216 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1217 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1220 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1222 int rd;
1223 uint32_t offset;
1224 TCGv tmp;
1226 rd = (insn >> 16) & 0xf;
1227 tmp = load_reg(s, rd);
1229 offset = (insn & 0xff) << ((insn >> 7) & 2);
1230 if (insn & (1 << 24)) {
1231 /* Pre indexed */
1232 if (insn & (1 << 23))
1233 tcg_gen_addi_i32(tmp, tmp, offset);
1234 else
1235 tcg_gen_addi_i32(tmp, tmp, -offset);
1236 tcg_gen_mov_i32(dest, tmp);
1237 if (insn & (1 << 21))
1238 store_reg(s, rd, tmp);
1239 else
1240 dead_tmp(tmp);
1241 } else if (insn & (1 << 21)) {
1242 /* Post indexed */
1243 tcg_gen_mov_i32(dest, tmp);
1244 if (insn & (1 << 23))
1245 tcg_gen_addi_i32(tmp, tmp, offset);
1246 else
1247 tcg_gen_addi_i32(tmp, tmp, -offset);
1248 store_reg(s, rd, tmp);
1249 } else if (!(insn & (1 << 23)))
1250 return 1;
1251 return 0;
1254 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1256 int rd = (insn >> 0) & 0xf;
1257 TCGv tmp;
1259 if (insn & (1 << 8)) {
1260 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1261 return 1;
1262 } else {
1263 tmp = iwmmxt_load_creg(rd);
1265 } else {
1266 tmp = new_tmp();
1267 iwmmxt_load_reg(cpu_V0, rd);
1268 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1270 tcg_gen_andi_i32(tmp, tmp, mask);
1271 tcg_gen_mov_i32(dest, tmp);
1272 dead_tmp(tmp);
1273 return 0;
1276 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1277 (ie. an undefined instruction). */
1278 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1280 int rd, wrd;
1281 int rdhi, rdlo, rd0, rd1, i;
1282 TCGv addr;
1283 TCGv tmp, tmp2, tmp3;
1285 if ((insn & 0x0e000e00) == 0x0c000000) {
1286 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1287 wrd = insn & 0xf;
1288 rdlo = (insn >> 12) & 0xf;
1289 rdhi = (insn >> 16) & 0xf;
1290 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1291 iwmmxt_load_reg(cpu_V0, wrd);
1292 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1293 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1294 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1295 } else { /* TMCRR */
1296 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1297 iwmmxt_store_reg(cpu_V0, wrd);
1298 gen_op_iwmmxt_set_mup();
1300 return 0;
1303 wrd = (insn >> 12) & 0xf;
1304 addr = new_tmp();
1305 if (gen_iwmmxt_address(s, insn, addr)) {
1306 dead_tmp(addr);
1307 return 1;
1309 if (insn & ARM_CP_RW_BIT) {
1310 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1311 tmp = new_tmp();
1312 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1313 iwmmxt_store_creg(wrd, tmp);
1314 } else {
1315 i = 1;
1316 if (insn & (1 << 8)) {
1317 if (insn & (1 << 22)) { /* WLDRD */
1318 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1319 i = 0;
1320 } else { /* WLDRW wRd */
1321 tmp = gen_ld32(addr, IS_USER(s));
1323 } else {
1324 if (insn & (1 << 22)) { /* WLDRH */
1325 tmp = gen_ld16u(addr, IS_USER(s));
1326 } else { /* WLDRB */
1327 tmp = gen_ld8u(addr, IS_USER(s));
1330 if (i) {
1331 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1332 dead_tmp(tmp);
1334 gen_op_iwmmxt_movq_wRn_M0(wrd);
1336 } else {
1337 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1338 tmp = iwmmxt_load_creg(wrd);
1339 gen_st32(tmp, addr, IS_USER(s));
1340 } else {
1341 gen_op_iwmmxt_movq_M0_wRn(wrd);
1342 tmp = new_tmp();
1343 if (insn & (1 << 8)) {
1344 if (insn & (1 << 22)) { /* WSTRD */
1345 dead_tmp(tmp);
1346 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1347 } else { /* WSTRW wRd */
1348 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1349 gen_st32(tmp, addr, IS_USER(s));
1351 } else {
1352 if (insn & (1 << 22)) { /* WSTRH */
1353 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1354 gen_st16(tmp, addr, IS_USER(s));
1355 } else { /* WSTRB */
1356 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1357 gen_st8(tmp, addr, IS_USER(s));
1362 return 0;
1365 if ((insn & 0x0f000000) != 0x0e000000)
1366 return 1;
1368 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1369 case 0x000: /* WOR */
1370 wrd = (insn >> 12) & 0xf;
1371 rd0 = (insn >> 0) & 0xf;
1372 rd1 = (insn >> 16) & 0xf;
1373 gen_op_iwmmxt_movq_M0_wRn(rd0);
1374 gen_op_iwmmxt_orq_M0_wRn(rd1);
1375 gen_op_iwmmxt_setpsr_nz();
1376 gen_op_iwmmxt_movq_wRn_M0(wrd);
1377 gen_op_iwmmxt_set_mup();
1378 gen_op_iwmmxt_set_cup();
1379 break;
1380 case 0x011: /* TMCR */
1381 if (insn & 0xf)
1382 return 1;
1383 rd = (insn >> 12) & 0xf;
1384 wrd = (insn >> 16) & 0xf;
1385 switch (wrd) {
1386 case ARM_IWMMXT_wCID:
1387 case ARM_IWMMXT_wCASF:
1388 break;
1389 case ARM_IWMMXT_wCon:
1390 gen_op_iwmmxt_set_cup();
1391 /* Fall through. */
1392 case ARM_IWMMXT_wCSSF:
1393 tmp = iwmmxt_load_creg(wrd);
1394 tmp2 = load_reg(s, rd);
1395 tcg_gen_bic_i32(tmp, tmp, tmp2);
1396 dead_tmp(tmp2);
1397 iwmmxt_store_creg(wrd, tmp);
1398 break;
1399 case ARM_IWMMXT_wCGR0:
1400 case ARM_IWMMXT_wCGR1:
1401 case ARM_IWMMXT_wCGR2:
1402 case ARM_IWMMXT_wCGR3:
1403 gen_op_iwmmxt_set_cup();
1404 tmp = load_reg(s, rd);
1405 iwmmxt_store_creg(wrd, tmp);
1406 break;
1407 default:
1408 return 1;
1410 break;
1411 case 0x100: /* WXOR */
1412 wrd = (insn >> 12) & 0xf;
1413 rd0 = (insn >> 0) & 0xf;
1414 rd1 = (insn >> 16) & 0xf;
1415 gen_op_iwmmxt_movq_M0_wRn(rd0);
1416 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1417 gen_op_iwmmxt_setpsr_nz();
1418 gen_op_iwmmxt_movq_wRn_M0(wrd);
1419 gen_op_iwmmxt_set_mup();
1420 gen_op_iwmmxt_set_cup();
1421 break;
1422 case 0x111: /* TMRC */
1423 if (insn & 0xf)
1424 return 1;
1425 rd = (insn >> 12) & 0xf;
1426 wrd = (insn >> 16) & 0xf;
1427 tmp = iwmmxt_load_creg(wrd);
1428 store_reg(s, rd, tmp);
1429 break;
1430 case 0x300: /* WANDN */
1431 wrd = (insn >> 12) & 0xf;
1432 rd0 = (insn >> 0) & 0xf;
1433 rd1 = (insn >> 16) & 0xf;
1434 gen_op_iwmmxt_movq_M0_wRn(rd0);
1435 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1436 gen_op_iwmmxt_andq_M0_wRn(rd1);
1437 gen_op_iwmmxt_setpsr_nz();
1438 gen_op_iwmmxt_movq_wRn_M0(wrd);
1439 gen_op_iwmmxt_set_mup();
1440 gen_op_iwmmxt_set_cup();
1441 break;
1442 case 0x200: /* WAND */
1443 wrd = (insn >> 12) & 0xf;
1444 rd0 = (insn >> 0) & 0xf;
1445 rd1 = (insn >> 16) & 0xf;
1446 gen_op_iwmmxt_movq_M0_wRn(rd0);
1447 gen_op_iwmmxt_andq_M0_wRn(rd1);
1448 gen_op_iwmmxt_setpsr_nz();
1449 gen_op_iwmmxt_movq_wRn_M0(wrd);
1450 gen_op_iwmmxt_set_mup();
1451 gen_op_iwmmxt_set_cup();
1452 break;
1453 case 0x810: case 0xa10: /* WMADD */
1454 wrd = (insn >> 12) & 0xf;
1455 rd0 = (insn >> 0) & 0xf;
1456 rd1 = (insn >> 16) & 0xf;
1457 gen_op_iwmmxt_movq_M0_wRn(rd0);
1458 if (insn & (1 << 21))
1459 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1460 else
1461 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1462 gen_op_iwmmxt_movq_wRn_M0(wrd);
1463 gen_op_iwmmxt_set_mup();
1464 break;
1465 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1466 wrd = (insn >> 12) & 0xf;
1467 rd0 = (insn >> 16) & 0xf;
1468 rd1 = (insn >> 0) & 0xf;
1469 gen_op_iwmmxt_movq_M0_wRn(rd0);
1470 switch ((insn >> 22) & 3) {
1471 case 0:
1472 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1473 break;
1474 case 1:
1475 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1476 break;
1477 case 2:
1478 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1479 break;
1480 case 3:
1481 return 1;
1483 gen_op_iwmmxt_movq_wRn_M0(wrd);
1484 gen_op_iwmmxt_set_mup();
1485 gen_op_iwmmxt_set_cup();
1486 break;
1487 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1488 wrd = (insn >> 12) & 0xf;
1489 rd0 = (insn >> 16) & 0xf;
1490 rd1 = (insn >> 0) & 0xf;
1491 gen_op_iwmmxt_movq_M0_wRn(rd0);
1492 switch ((insn >> 22) & 3) {
1493 case 0:
1494 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1495 break;
1496 case 1:
1497 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1498 break;
1499 case 2:
1500 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1501 break;
1502 case 3:
1503 return 1;
1505 gen_op_iwmmxt_movq_wRn_M0(wrd);
1506 gen_op_iwmmxt_set_mup();
1507 gen_op_iwmmxt_set_cup();
1508 break;
1509 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1510 wrd = (insn >> 12) & 0xf;
1511 rd0 = (insn >> 16) & 0xf;
1512 rd1 = (insn >> 0) & 0xf;
1513 gen_op_iwmmxt_movq_M0_wRn(rd0);
1514 if (insn & (1 << 22))
1515 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1516 else
1517 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1518 if (!(insn & (1 << 20)))
1519 gen_op_iwmmxt_addl_M0_wRn(wrd);
1520 gen_op_iwmmxt_movq_wRn_M0(wrd);
1521 gen_op_iwmmxt_set_mup();
1522 break;
1523 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1524 wrd = (insn >> 12) & 0xf;
1525 rd0 = (insn >> 16) & 0xf;
1526 rd1 = (insn >> 0) & 0xf;
1527 gen_op_iwmmxt_movq_M0_wRn(rd0);
1528 if (insn & (1 << 21)) {
1529 if (insn & (1 << 20))
1530 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1531 else
1532 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1533 } else {
1534 if (insn & (1 << 20))
1535 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1536 else
1537 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1539 gen_op_iwmmxt_movq_wRn_M0(wrd);
1540 gen_op_iwmmxt_set_mup();
1541 break;
1542 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1543 wrd = (insn >> 12) & 0xf;
1544 rd0 = (insn >> 16) & 0xf;
1545 rd1 = (insn >> 0) & 0xf;
1546 gen_op_iwmmxt_movq_M0_wRn(rd0);
1547 if (insn & (1 << 21))
1548 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1549 else
1550 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1551 if (!(insn & (1 << 20))) {
1552 iwmmxt_load_reg(cpu_V1, wrd);
1553 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1555 gen_op_iwmmxt_movq_wRn_M0(wrd);
1556 gen_op_iwmmxt_set_mup();
1557 break;
1558 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1559 wrd = (insn >> 12) & 0xf;
1560 rd0 = (insn >> 16) & 0xf;
1561 rd1 = (insn >> 0) & 0xf;
1562 gen_op_iwmmxt_movq_M0_wRn(rd0);
1563 switch ((insn >> 22) & 3) {
1564 case 0:
1565 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1566 break;
1567 case 1:
1568 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1569 break;
1570 case 2:
1571 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1572 break;
1573 case 3:
1574 return 1;
1576 gen_op_iwmmxt_movq_wRn_M0(wrd);
1577 gen_op_iwmmxt_set_mup();
1578 gen_op_iwmmxt_set_cup();
1579 break;
1580 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1581 wrd = (insn >> 12) & 0xf;
1582 rd0 = (insn >> 16) & 0xf;
1583 rd1 = (insn >> 0) & 0xf;
1584 gen_op_iwmmxt_movq_M0_wRn(rd0);
1585 if (insn & (1 << 22)) {
1586 if (insn & (1 << 20))
1587 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1588 else
1589 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1590 } else {
1591 if (insn & (1 << 20))
1592 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1593 else
1594 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1596 gen_op_iwmmxt_movq_wRn_M0(wrd);
1597 gen_op_iwmmxt_set_mup();
1598 gen_op_iwmmxt_set_cup();
1599 break;
1600 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1601 wrd = (insn >> 12) & 0xf;
1602 rd0 = (insn >> 16) & 0xf;
1603 rd1 = (insn >> 0) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0);
1605 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1606 tcg_gen_andi_i32(tmp, tmp, 7);
1607 iwmmxt_load_reg(cpu_V1, rd1);
1608 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1609 dead_tmp(tmp);
1610 gen_op_iwmmxt_movq_wRn_M0(wrd);
1611 gen_op_iwmmxt_set_mup();
1612 break;
1613 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1614 if (((insn >> 6) & 3) == 3)
1615 return 1;
1616 rd = (insn >> 12) & 0xf;
1617 wrd = (insn >> 16) & 0xf;
1618 tmp = load_reg(s, rd);
1619 gen_op_iwmmxt_movq_M0_wRn(wrd);
1620 switch ((insn >> 6) & 3) {
1621 case 0:
1622 tmp2 = tcg_const_i32(0xff);
1623 tmp3 = tcg_const_i32((insn & 7) << 3);
1624 break;
1625 case 1:
1626 tmp2 = tcg_const_i32(0xffff);
1627 tmp3 = tcg_const_i32((insn & 3) << 4);
1628 break;
1629 case 2:
1630 tmp2 = tcg_const_i32(0xffffffff);
1631 tmp3 = tcg_const_i32((insn & 1) << 5);
1632 break;
1633 default:
1634 TCGV_UNUSED(tmp2);
1635 TCGV_UNUSED(tmp3);
1637 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1638 tcg_temp_free(tmp3);
1639 tcg_temp_free(tmp2);
1640 dead_tmp(tmp);
1641 gen_op_iwmmxt_movq_wRn_M0(wrd);
1642 gen_op_iwmmxt_set_mup();
1643 break;
1644 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1645 rd = (insn >> 12) & 0xf;
1646 wrd = (insn >> 16) & 0xf;
1647 if (rd == 15 || ((insn >> 22) & 3) == 3)
1648 return 1;
1649 gen_op_iwmmxt_movq_M0_wRn(wrd);
1650 tmp = new_tmp();
1651 switch ((insn >> 22) & 3) {
1652 case 0:
1653 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1654 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1655 if (insn & 8) {
1656 tcg_gen_ext8s_i32(tmp, tmp);
1657 } else {
1658 tcg_gen_andi_i32(tmp, tmp, 0xff);
1660 break;
1661 case 1:
1662 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1663 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1664 if (insn & 8) {
1665 tcg_gen_ext16s_i32(tmp, tmp);
1666 } else {
1667 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1669 break;
1670 case 2:
1671 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1672 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1673 break;
1675 store_reg(s, rd, tmp);
1676 break;
1677 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1678 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1679 return 1;
1680 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1681 switch ((insn >> 22) & 3) {
1682 case 0:
1683 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1684 break;
1685 case 1:
1686 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1687 break;
1688 case 2:
1689 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1690 break;
1692 tcg_gen_shli_i32(tmp, tmp, 28);
1693 gen_set_nzcv(tmp);
1694 dead_tmp(tmp);
1695 break;
1696 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1697 if (((insn >> 6) & 3) == 3)
1698 return 1;
1699 rd = (insn >> 12) & 0xf;
1700 wrd = (insn >> 16) & 0xf;
1701 tmp = load_reg(s, rd);
1702 switch ((insn >> 6) & 3) {
1703 case 0:
1704 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1705 break;
1706 case 1:
1707 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1708 break;
1709 case 2:
1710 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1711 break;
1713 dead_tmp(tmp);
1714 gen_op_iwmmxt_movq_wRn_M0(wrd);
1715 gen_op_iwmmxt_set_mup();
1716 break;
1717 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1718 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1719 return 1;
1720 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1721 tmp2 = new_tmp();
1722 tcg_gen_mov_i32(tmp2, tmp);
1723 switch ((insn >> 22) & 3) {
1724 case 0:
1725 for (i = 0; i < 7; i ++) {
1726 tcg_gen_shli_i32(tmp2, tmp2, 4);
1727 tcg_gen_and_i32(tmp, tmp, tmp2);
1729 break;
1730 case 1:
1731 for (i = 0; i < 3; i ++) {
1732 tcg_gen_shli_i32(tmp2, tmp2, 8);
1733 tcg_gen_and_i32(tmp, tmp, tmp2);
1735 break;
1736 case 2:
1737 tcg_gen_shli_i32(tmp2, tmp2, 16);
1738 tcg_gen_and_i32(tmp, tmp, tmp2);
1739 break;
1741 gen_set_nzcv(tmp);
1742 dead_tmp(tmp2);
1743 dead_tmp(tmp);
1744 break;
1745 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1746 wrd = (insn >> 12) & 0xf;
1747 rd0 = (insn >> 16) & 0xf;
1748 gen_op_iwmmxt_movq_M0_wRn(rd0);
1749 switch ((insn >> 22) & 3) {
1750 case 0:
1751 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1752 break;
1753 case 1:
1754 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1755 break;
1756 case 2:
1757 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1758 break;
1759 case 3:
1760 return 1;
1762 gen_op_iwmmxt_movq_wRn_M0(wrd);
1763 gen_op_iwmmxt_set_mup();
1764 break;
1765 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1766 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1767 return 1;
1768 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1769 tmp2 = new_tmp();
1770 tcg_gen_mov_i32(tmp2, tmp);
1771 switch ((insn >> 22) & 3) {
1772 case 0:
1773 for (i = 0; i < 7; i ++) {
1774 tcg_gen_shli_i32(tmp2, tmp2, 4);
1775 tcg_gen_or_i32(tmp, tmp, tmp2);
1777 break;
1778 case 1:
1779 for (i = 0; i < 3; i ++) {
1780 tcg_gen_shli_i32(tmp2, tmp2, 8);
1781 tcg_gen_or_i32(tmp, tmp, tmp2);
1783 break;
1784 case 2:
1785 tcg_gen_shli_i32(tmp2, tmp2, 16);
1786 tcg_gen_or_i32(tmp, tmp, tmp2);
1787 break;
1789 gen_set_nzcv(tmp);
1790 dead_tmp(tmp2);
1791 dead_tmp(tmp);
1792 break;
1793 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1794 rd = (insn >> 12) & 0xf;
1795 rd0 = (insn >> 16) & 0xf;
1796 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1797 return 1;
1798 gen_op_iwmmxt_movq_M0_wRn(rd0);
1799 tmp = new_tmp();
1800 switch ((insn >> 22) & 3) {
1801 case 0:
1802 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1803 break;
1804 case 1:
1805 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1806 break;
1807 case 2:
1808 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1809 break;
1811 store_reg(s, rd, tmp);
1812 break;
1813 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1814 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1815 wrd = (insn >> 12) & 0xf;
1816 rd0 = (insn >> 16) & 0xf;
1817 rd1 = (insn >> 0) & 0xf;
1818 gen_op_iwmmxt_movq_M0_wRn(rd0);
1819 switch ((insn >> 22) & 3) {
1820 case 0:
1821 if (insn & (1 << 21))
1822 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1823 else
1824 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1825 break;
1826 case 1:
1827 if (insn & (1 << 21))
1828 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1829 else
1830 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1831 break;
1832 case 2:
1833 if (insn & (1 << 21))
1834 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1835 else
1836 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1837 break;
1838 case 3:
1839 return 1;
1841 gen_op_iwmmxt_movq_wRn_M0(wrd);
1842 gen_op_iwmmxt_set_mup();
1843 gen_op_iwmmxt_set_cup();
1844 break;
1845 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1846 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1847 wrd = (insn >> 12) & 0xf;
1848 rd0 = (insn >> 16) & 0xf;
1849 gen_op_iwmmxt_movq_M0_wRn(rd0);
1850 switch ((insn >> 22) & 3) {
1851 case 0:
1852 if (insn & (1 << 21))
1853 gen_op_iwmmxt_unpacklsb_M0();
1854 else
1855 gen_op_iwmmxt_unpacklub_M0();
1856 break;
1857 case 1:
1858 if (insn & (1 << 21))
1859 gen_op_iwmmxt_unpacklsw_M0();
1860 else
1861 gen_op_iwmmxt_unpackluw_M0();
1862 break;
1863 case 2:
1864 if (insn & (1 << 21))
1865 gen_op_iwmmxt_unpacklsl_M0();
1866 else
1867 gen_op_iwmmxt_unpacklul_M0();
1868 break;
1869 case 3:
1870 return 1;
1872 gen_op_iwmmxt_movq_wRn_M0(wrd);
1873 gen_op_iwmmxt_set_mup();
1874 gen_op_iwmmxt_set_cup();
1875 break;
1876 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1877 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1878 wrd = (insn >> 12) & 0xf;
1879 rd0 = (insn >> 16) & 0xf;
1880 gen_op_iwmmxt_movq_M0_wRn(rd0);
1881 switch ((insn >> 22) & 3) {
1882 case 0:
1883 if (insn & (1 << 21))
1884 gen_op_iwmmxt_unpackhsb_M0();
1885 else
1886 gen_op_iwmmxt_unpackhub_M0();
1887 break;
1888 case 1:
1889 if (insn & (1 << 21))
1890 gen_op_iwmmxt_unpackhsw_M0();
1891 else
1892 gen_op_iwmmxt_unpackhuw_M0();
1893 break;
1894 case 2:
1895 if (insn & (1 << 21))
1896 gen_op_iwmmxt_unpackhsl_M0();
1897 else
1898 gen_op_iwmmxt_unpackhul_M0();
1899 break;
1900 case 3:
1901 return 1;
1903 gen_op_iwmmxt_movq_wRn_M0(wrd);
1904 gen_op_iwmmxt_set_mup();
1905 gen_op_iwmmxt_set_cup();
1906 break;
1907 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1908 case 0x214: case 0x614: case 0xa14: case 0xe14:
1909 if (((insn >> 22) & 3) == 0)
1910 return 1;
1911 wrd = (insn >> 12) & 0xf;
1912 rd0 = (insn >> 16) & 0xf;
1913 gen_op_iwmmxt_movq_M0_wRn(rd0);
1914 tmp = new_tmp();
1915 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1916 dead_tmp(tmp);
1917 return 1;
1919 switch ((insn >> 22) & 3) {
1920 case 1:
1921 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1922 break;
1923 case 2:
1924 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1925 break;
1926 case 3:
1927 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1928 break;
1930 dead_tmp(tmp);
1931 gen_op_iwmmxt_movq_wRn_M0(wrd);
1932 gen_op_iwmmxt_set_mup();
1933 gen_op_iwmmxt_set_cup();
1934 break;
1935 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1936 case 0x014: case 0x414: case 0x814: case 0xc14:
1937 if (((insn >> 22) & 3) == 0)
1938 return 1;
1939 wrd = (insn >> 12) & 0xf;
1940 rd0 = (insn >> 16) & 0xf;
1941 gen_op_iwmmxt_movq_M0_wRn(rd0);
1942 tmp = new_tmp();
1943 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1944 dead_tmp(tmp);
1945 return 1;
1947 switch ((insn >> 22) & 3) {
1948 case 1:
1949 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
1950 break;
1951 case 2:
1952 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
1953 break;
1954 case 3:
1955 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
1956 break;
1958 dead_tmp(tmp);
1959 gen_op_iwmmxt_movq_wRn_M0(wrd);
1960 gen_op_iwmmxt_set_mup();
1961 gen_op_iwmmxt_set_cup();
1962 break;
1963 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
1964 case 0x114: case 0x514: case 0x914: case 0xd14:
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_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
1978 break;
1979 case 2:
1980 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
1981 break;
1982 case 3:
1983 gen_helper_iwmmxt_sllq(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 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
1992 case 0x314: case 0x714: case 0xb14: case 0xf14:
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 switch ((insn >> 22) & 3) {
2000 case 1:
2001 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2002 dead_tmp(tmp);
2003 return 1;
2005 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2006 break;
2007 case 2:
2008 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2009 dead_tmp(tmp);
2010 return 1;
2012 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2013 break;
2014 case 3:
2015 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2016 dead_tmp(tmp);
2017 return 1;
2019 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2020 break;
2022 dead_tmp(tmp);
2023 gen_op_iwmmxt_movq_wRn_M0(wrd);
2024 gen_op_iwmmxt_set_mup();
2025 gen_op_iwmmxt_set_cup();
2026 break;
2027 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2028 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2029 wrd = (insn >> 12) & 0xf;
2030 rd0 = (insn >> 16) & 0xf;
2031 rd1 = (insn >> 0) & 0xf;
2032 gen_op_iwmmxt_movq_M0_wRn(rd0);
2033 switch ((insn >> 22) & 3) {
2034 case 0:
2035 if (insn & (1 << 21))
2036 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2037 else
2038 gen_op_iwmmxt_minub_M0_wRn(rd1);
2039 break;
2040 case 1:
2041 if (insn & (1 << 21))
2042 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2043 else
2044 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2045 break;
2046 case 2:
2047 if (insn & (1 << 21))
2048 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2049 else
2050 gen_op_iwmmxt_minul_M0_wRn(rd1);
2051 break;
2052 case 3:
2053 return 1;
2055 gen_op_iwmmxt_movq_wRn_M0(wrd);
2056 gen_op_iwmmxt_set_mup();
2057 break;
2058 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2059 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2060 wrd = (insn >> 12) & 0xf;
2061 rd0 = (insn >> 16) & 0xf;
2062 rd1 = (insn >> 0) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0);
2064 switch ((insn >> 22) & 3) {
2065 case 0:
2066 if (insn & (1 << 21))
2067 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2068 else
2069 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2070 break;
2071 case 1:
2072 if (insn & (1 << 21))
2073 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2074 else
2075 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2076 break;
2077 case 2:
2078 if (insn & (1 << 21))
2079 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2080 else
2081 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2082 break;
2083 case 3:
2084 return 1;
2086 gen_op_iwmmxt_movq_wRn_M0(wrd);
2087 gen_op_iwmmxt_set_mup();
2088 break;
2089 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2090 case 0x402: case 0x502: case 0x602: case 0x702:
2091 wrd = (insn >> 12) & 0xf;
2092 rd0 = (insn >> 16) & 0xf;
2093 rd1 = (insn >> 0) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0);
2095 tmp = tcg_const_i32((insn >> 20) & 3);
2096 iwmmxt_load_reg(cpu_V1, rd1);
2097 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2098 tcg_temp_free(tmp);
2099 gen_op_iwmmxt_movq_wRn_M0(wrd);
2100 gen_op_iwmmxt_set_mup();
2101 break;
2102 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2103 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2104 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2105 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2106 wrd = (insn >> 12) & 0xf;
2107 rd0 = (insn >> 16) & 0xf;
2108 rd1 = (insn >> 0) & 0xf;
2109 gen_op_iwmmxt_movq_M0_wRn(rd0);
2110 switch ((insn >> 20) & 0xf) {
2111 case 0x0:
2112 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2113 break;
2114 case 0x1:
2115 gen_op_iwmmxt_subub_M0_wRn(rd1);
2116 break;
2117 case 0x3:
2118 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2119 break;
2120 case 0x4:
2121 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2122 break;
2123 case 0x5:
2124 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2125 break;
2126 case 0x7:
2127 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2128 break;
2129 case 0x8:
2130 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2131 break;
2132 case 0x9:
2133 gen_op_iwmmxt_subul_M0_wRn(rd1);
2134 break;
2135 case 0xb:
2136 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2137 break;
2138 default:
2139 return 1;
2141 gen_op_iwmmxt_movq_wRn_M0(wrd);
2142 gen_op_iwmmxt_set_mup();
2143 gen_op_iwmmxt_set_cup();
2144 break;
2145 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2146 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2147 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2148 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2149 wrd = (insn >> 12) & 0xf;
2150 rd0 = (insn >> 16) & 0xf;
2151 gen_op_iwmmxt_movq_M0_wRn(rd0);
2152 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2153 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2154 tcg_temp_free(tmp);
2155 gen_op_iwmmxt_movq_wRn_M0(wrd);
2156 gen_op_iwmmxt_set_mup();
2157 gen_op_iwmmxt_set_cup();
2158 break;
2159 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2160 case 0x418: case 0x518: case 0x618: case 0x718:
2161 case 0x818: case 0x918: case 0xa18: case 0xb18:
2162 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2163 wrd = (insn >> 12) & 0xf;
2164 rd0 = (insn >> 16) & 0xf;
2165 rd1 = (insn >> 0) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0);
2167 switch ((insn >> 20) & 0xf) {
2168 case 0x0:
2169 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2170 break;
2171 case 0x1:
2172 gen_op_iwmmxt_addub_M0_wRn(rd1);
2173 break;
2174 case 0x3:
2175 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2176 break;
2177 case 0x4:
2178 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2179 break;
2180 case 0x5:
2181 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2182 break;
2183 case 0x7:
2184 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2185 break;
2186 case 0x8:
2187 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2188 break;
2189 case 0x9:
2190 gen_op_iwmmxt_addul_M0_wRn(rd1);
2191 break;
2192 case 0xb:
2193 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2194 break;
2195 default:
2196 return 1;
2198 gen_op_iwmmxt_movq_wRn_M0(wrd);
2199 gen_op_iwmmxt_set_mup();
2200 gen_op_iwmmxt_set_cup();
2201 break;
2202 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2203 case 0x408: case 0x508: case 0x608: case 0x708:
2204 case 0x808: case 0x908: case 0xa08: case 0xb08:
2205 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2206 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2207 return 1;
2208 wrd = (insn >> 12) & 0xf;
2209 rd0 = (insn >> 16) & 0xf;
2210 rd1 = (insn >> 0) & 0xf;
2211 gen_op_iwmmxt_movq_M0_wRn(rd0);
2212 switch ((insn >> 22) & 3) {
2213 case 1:
2214 if (insn & (1 << 21))
2215 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2216 else
2217 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2218 break;
2219 case 2:
2220 if (insn & (1 << 21))
2221 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2222 else
2223 gen_op_iwmmxt_packul_M0_wRn(rd1);
2224 break;
2225 case 3:
2226 if (insn & (1 << 21))
2227 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2228 else
2229 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2230 break;
2232 gen_op_iwmmxt_movq_wRn_M0(wrd);
2233 gen_op_iwmmxt_set_mup();
2234 gen_op_iwmmxt_set_cup();
2235 break;
2236 case 0x201: case 0x203: case 0x205: case 0x207:
2237 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2238 case 0x211: case 0x213: case 0x215: case 0x217:
2239 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2240 wrd = (insn >> 5) & 0xf;
2241 rd0 = (insn >> 12) & 0xf;
2242 rd1 = (insn >> 0) & 0xf;
2243 if (rd0 == 0xf || rd1 == 0xf)
2244 return 1;
2245 gen_op_iwmmxt_movq_M0_wRn(wrd);
2246 tmp = load_reg(s, rd0);
2247 tmp2 = load_reg(s, rd1);
2248 switch ((insn >> 16) & 0xf) {
2249 case 0x0: /* TMIA */
2250 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2251 break;
2252 case 0x8: /* TMIAPH */
2253 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2254 break;
2255 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2256 if (insn & (1 << 16))
2257 tcg_gen_shri_i32(tmp, tmp, 16);
2258 if (insn & (1 << 17))
2259 tcg_gen_shri_i32(tmp2, tmp2, 16);
2260 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2261 break;
2262 default:
2263 dead_tmp(tmp2);
2264 dead_tmp(tmp);
2265 return 1;
2267 dead_tmp(tmp2);
2268 dead_tmp(tmp);
2269 gen_op_iwmmxt_movq_wRn_M0(wrd);
2270 gen_op_iwmmxt_set_mup();
2271 break;
2272 default:
2273 return 1;
2276 return 0;
2279 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2280 (ie. an undefined instruction). */
2281 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2283 int acc, rd0, rd1, rdhi, rdlo;
2284 TCGv tmp, tmp2;
2286 if ((insn & 0x0ff00f10) == 0x0e200010) {
2287 /* Multiply with Internal Accumulate Format */
2288 rd0 = (insn >> 12) & 0xf;
2289 rd1 = insn & 0xf;
2290 acc = (insn >> 5) & 7;
2292 if (acc != 0)
2293 return 1;
2295 tmp = load_reg(s, rd0);
2296 tmp2 = load_reg(s, rd1);
2297 switch ((insn >> 16) & 0xf) {
2298 case 0x0: /* MIA */
2299 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2300 break;
2301 case 0x8: /* MIAPH */
2302 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2303 break;
2304 case 0xc: /* MIABB */
2305 case 0xd: /* MIABT */
2306 case 0xe: /* MIATB */
2307 case 0xf: /* MIATT */
2308 if (insn & (1 << 16))
2309 tcg_gen_shri_i32(tmp, tmp, 16);
2310 if (insn & (1 << 17))
2311 tcg_gen_shri_i32(tmp2, tmp2, 16);
2312 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2313 break;
2314 default:
2315 return 1;
2317 dead_tmp(tmp2);
2318 dead_tmp(tmp);
2320 gen_op_iwmmxt_movq_wRn_M0(acc);
2321 return 0;
2324 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2325 /* Internal Accumulator Access Format */
2326 rdhi = (insn >> 16) & 0xf;
2327 rdlo = (insn >> 12) & 0xf;
2328 acc = insn & 7;
2330 if (acc != 0)
2331 return 1;
2333 if (insn & ARM_CP_RW_BIT) { /* MRA */
2334 iwmmxt_load_reg(cpu_V0, acc);
2335 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2336 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2337 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2338 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2339 } else { /* MAR */
2340 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2341 iwmmxt_store_reg(cpu_V0, acc);
2343 return 0;
2346 return 1;
2349 /* Disassemble system coprocessor instruction. Return nonzero if
2350 instruction is not defined. */
2351 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2353 TCGv tmp;
2354 uint32_t rd = (insn >> 12) & 0xf;
2355 uint32_t cp = (insn >> 8) & 0xf;
2356 if (IS_USER(s)) {
2357 return 1;
2360 if (insn & ARM_CP_RW_BIT) {
2361 if (!env->cp[cp].cp_read)
2362 return 1;
2363 gen_set_pc_im(s->pc);
2364 tmp = new_tmp();
2365 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2366 store_reg(s, rd, tmp);
2367 } else {
2368 if (!env->cp[cp].cp_write)
2369 return 1;
2370 gen_set_pc_im(s->pc);
2371 tmp = load_reg(s, rd);
2372 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2373 dead_tmp(tmp);
2375 return 0;
2378 static int cp15_user_ok(uint32_t insn)
2380 int cpn = (insn >> 16) & 0xf;
2381 int cpm = insn & 0xf;
2382 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2384 if (cpn == 13 && cpm == 0) {
2385 /* TLS register. */
2386 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2387 return 1;
2389 if (cpn == 7) {
2390 /* ISB, DSB, DMB. */
2391 if ((cpm == 5 && op == 4)
2392 || (cpm == 10 && (op == 4 || op == 5)))
2393 return 1;
2395 return 0;
2398 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2399 instruction is not defined. */
2400 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2402 uint32_t rd;
2403 TCGv tmp;
2405 /* M profile cores use memory mapped registers instead of cp15. */
2406 if (arm_feature(env, ARM_FEATURE_M) ||
2407 !arm_feature(env, ARM_FEATURE_CP15)) {
2408 return 1;
2411 if ((insn & (1 << 25)) == 0) {
2412 if (insn & (1 << 20)) {
2413 /* mrrc */
2414 return 1;
2416 /* mcrr. Used for block cache operations, so implement as no-op. */
2417 return 0;
2419 if ((insn & (1 << 4)) == 0) {
2420 /* cdp */
2421 return 1;
2423 if (IS_USER(s) && !cp15_user_ok(insn)) {
2424 return 1;
2426 if ((insn & 0x0fff0fff) == 0x0e070f90
2427 || (insn & 0x0fff0fff) == 0x0e070f58) {
2428 /* Wait for interrupt. */
2429 gen_set_pc_im(s->pc);
2430 s->is_jmp = DISAS_WFI;
2431 return 0;
2433 rd = (insn >> 12) & 0xf;
2434 if (insn & ARM_CP_RW_BIT) {
2435 tmp = new_tmp();
2436 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2437 /* If the destination register is r15 then sets condition codes. */
2438 if (rd != 15)
2439 store_reg(s, rd, tmp);
2440 else
2441 dead_tmp(tmp);
2442 } else {
2443 tmp = load_reg(s, rd);
2444 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2445 dead_tmp(tmp);
2446 /* Normally we would always end the TB here, but Linux
2447 * arch/arm/mach-pxa/sleep.S expects two instructions following
2448 * an MMU enable to execute from cache. Imitate this behaviour. */
2449 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2450 (insn & 0x0fff0fff) != 0x0e010f10)
2451 gen_lookup_tb(s);
2453 return 0;
2456 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2457 #define VFP_SREG(insn, bigbit, smallbit) \
2458 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2459 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2460 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2461 reg = (((insn) >> (bigbit)) & 0x0f) \
2462 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2463 } else { \
2464 if (insn & (1 << (smallbit))) \
2465 return 1; \
2466 reg = ((insn) >> (bigbit)) & 0x0f; \
2467 }} while (0)
2469 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2470 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2471 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2472 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2473 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2474 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2476 /* Move between integer and VFP cores. */
2477 static TCGv gen_vfp_mrs(void)
2479 TCGv tmp = new_tmp();
2480 tcg_gen_mov_i32(tmp, cpu_F0s);
2481 return tmp;
2484 static void gen_vfp_msr(TCGv tmp)
2486 tcg_gen_mov_i32(cpu_F0s, tmp);
2487 dead_tmp(tmp);
2490 static inline int
2491 vfp_enabled(CPUState * env)
2493 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2496 static void gen_neon_dup_u8(TCGv var, int shift)
2498 TCGv tmp = new_tmp();
2499 if (shift)
2500 tcg_gen_shri_i32(var, var, shift);
2501 tcg_gen_ext8u_i32(var, var);
2502 tcg_gen_shli_i32(tmp, var, 8);
2503 tcg_gen_or_i32(var, var, tmp);
2504 tcg_gen_shli_i32(tmp, var, 16);
2505 tcg_gen_or_i32(var, var, tmp);
2506 dead_tmp(tmp);
2509 static void gen_neon_dup_low16(TCGv var)
2511 TCGv tmp = new_tmp();
2512 tcg_gen_ext16u_i32(var, var);
2513 tcg_gen_shli_i32(tmp, var, 16);
2514 tcg_gen_or_i32(var, var, tmp);
2515 dead_tmp(tmp);
2518 static void gen_neon_dup_high16(TCGv var)
2520 TCGv tmp = new_tmp();
2521 tcg_gen_andi_i32(var, var, 0xffff0000);
2522 tcg_gen_shri_i32(tmp, var, 16);
2523 tcg_gen_or_i32(var, var, tmp);
2524 dead_tmp(tmp);
2527 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2528 (ie. an undefined instruction). */
2529 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2531 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2532 int dp, veclen;
2533 TCGv addr;
2534 TCGv tmp;
2535 TCGv tmp2;
2537 if (!arm_feature(env, ARM_FEATURE_VFP))
2538 return 1;
2540 if (!vfp_enabled(env)) {
2541 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2542 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2543 return 1;
2544 rn = (insn >> 16) & 0xf;
2545 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2546 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2547 return 1;
2549 dp = ((insn & 0xf00) == 0xb00);
2550 switch ((insn >> 24) & 0xf) {
2551 case 0xe:
2552 if (insn & (1 << 4)) {
2553 /* single register transfer */
2554 rd = (insn >> 12) & 0xf;
2555 if (dp) {
2556 int size;
2557 int pass;
2559 VFP_DREG_N(rn, insn);
2560 if (insn & 0xf)
2561 return 1;
2562 if (insn & 0x00c00060
2563 && !arm_feature(env, ARM_FEATURE_NEON))
2564 return 1;
2566 pass = (insn >> 21) & 1;
2567 if (insn & (1 << 22)) {
2568 size = 0;
2569 offset = ((insn >> 5) & 3) * 8;
2570 } else if (insn & (1 << 5)) {
2571 size = 1;
2572 offset = (insn & (1 << 6)) ? 16 : 0;
2573 } else {
2574 size = 2;
2575 offset = 0;
2577 if (insn & ARM_CP_RW_BIT) {
2578 /* vfp->arm */
2579 tmp = neon_load_reg(rn, pass);
2580 switch (size) {
2581 case 0:
2582 if (offset)
2583 tcg_gen_shri_i32(tmp, tmp, offset);
2584 if (insn & (1 << 23))
2585 gen_uxtb(tmp);
2586 else
2587 gen_sxtb(tmp);
2588 break;
2589 case 1:
2590 if (insn & (1 << 23)) {
2591 if (offset) {
2592 tcg_gen_shri_i32(tmp, tmp, 16);
2593 } else {
2594 gen_uxth(tmp);
2596 } else {
2597 if (offset) {
2598 tcg_gen_sari_i32(tmp, tmp, 16);
2599 } else {
2600 gen_sxth(tmp);
2603 break;
2604 case 2:
2605 break;
2607 store_reg(s, rd, tmp);
2608 } else {
2609 /* arm->vfp */
2610 tmp = load_reg(s, rd);
2611 if (insn & (1 << 23)) {
2612 /* VDUP */
2613 if (size == 0) {
2614 gen_neon_dup_u8(tmp, 0);
2615 } else if (size == 1) {
2616 gen_neon_dup_low16(tmp);
2618 for (n = 0; n <= pass * 2; n++) {
2619 tmp2 = new_tmp();
2620 tcg_gen_mov_i32(tmp2, tmp);
2621 neon_store_reg(rn, n, tmp2);
2623 neon_store_reg(rn, n, tmp);
2624 } else {
2625 /* VMOV */
2626 switch (size) {
2627 case 0:
2628 tmp2 = neon_load_reg(rn, pass);
2629 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2630 dead_tmp(tmp2);
2631 break;
2632 case 1:
2633 tmp2 = neon_load_reg(rn, pass);
2634 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2635 dead_tmp(tmp2);
2636 break;
2637 case 2:
2638 break;
2640 neon_store_reg(rn, pass, tmp);
2643 } else { /* !dp */
2644 if ((insn & 0x6f) != 0x00)
2645 return 1;
2646 rn = VFP_SREG_N(insn);
2647 if (insn & ARM_CP_RW_BIT) {
2648 /* vfp->arm */
2649 if (insn & (1 << 21)) {
2650 /* system register */
2651 rn >>= 1;
2653 switch (rn) {
2654 case ARM_VFP_FPSID:
2655 /* VFP2 allows access to FSID from userspace.
2656 VFP3 restricts all id registers to privileged
2657 accesses. */
2658 if (IS_USER(s)
2659 && arm_feature(env, ARM_FEATURE_VFP3))
2660 return 1;
2661 tmp = load_cpu_field(vfp.xregs[rn]);
2662 break;
2663 case ARM_VFP_FPEXC:
2664 if (IS_USER(s))
2665 return 1;
2666 tmp = load_cpu_field(vfp.xregs[rn]);
2667 break;
2668 case ARM_VFP_FPINST:
2669 case ARM_VFP_FPINST2:
2670 /* Not present in VFP3. */
2671 if (IS_USER(s)
2672 || arm_feature(env, ARM_FEATURE_VFP3))
2673 return 1;
2674 tmp = load_cpu_field(vfp.xregs[rn]);
2675 break;
2676 case ARM_VFP_FPSCR:
2677 if (rd == 15) {
2678 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2679 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2680 } else {
2681 tmp = new_tmp();
2682 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2684 break;
2685 case ARM_VFP_MVFR0:
2686 case ARM_VFP_MVFR1:
2687 if (IS_USER(s)
2688 || !arm_feature(env, ARM_FEATURE_VFP3))
2689 return 1;
2690 tmp = load_cpu_field(vfp.xregs[rn]);
2691 break;
2692 default:
2693 return 1;
2695 } else {
2696 gen_mov_F0_vreg(0, rn);
2697 tmp = gen_vfp_mrs();
2699 if (rd == 15) {
2700 /* Set the 4 flag bits in the CPSR. */
2701 gen_set_nzcv(tmp);
2702 dead_tmp(tmp);
2703 } else {
2704 store_reg(s, rd, tmp);
2706 } else {
2707 /* arm->vfp */
2708 tmp = load_reg(s, rd);
2709 if (insn & (1 << 21)) {
2710 rn >>= 1;
2711 /* system register */
2712 switch (rn) {
2713 case ARM_VFP_FPSID:
2714 case ARM_VFP_MVFR0:
2715 case ARM_VFP_MVFR1:
2716 /* Writes are ignored. */
2717 break;
2718 case ARM_VFP_FPSCR:
2719 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2720 dead_tmp(tmp);
2721 gen_lookup_tb(s);
2722 break;
2723 case ARM_VFP_FPEXC:
2724 if (IS_USER(s))
2725 return 1;
2726 store_cpu_field(tmp, vfp.xregs[rn]);
2727 gen_lookup_tb(s);
2728 break;
2729 case ARM_VFP_FPINST:
2730 case ARM_VFP_FPINST2:
2731 store_cpu_field(tmp, vfp.xregs[rn]);
2732 break;
2733 default:
2734 return 1;
2736 } else {
2737 gen_vfp_msr(tmp);
2738 gen_mov_vreg_F0(0, rn);
2742 } else {
2743 /* data processing */
2744 /* The opcode is in bits 23, 21, 20 and 6. */
2745 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2746 if (dp) {
2747 if (op == 15) {
2748 /* rn is opcode */
2749 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2750 } else {
2751 /* rn is register number */
2752 VFP_DREG_N(rn, insn);
2755 if (op == 15 && (rn == 15 || rn > 17)) {
2756 /* Integer or single precision destination. */
2757 rd = VFP_SREG_D(insn);
2758 } else {
2759 VFP_DREG_D(rd, insn);
2762 if (op == 15 && (rn == 16 || rn == 17)) {
2763 /* Integer source. */
2764 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2765 } else {
2766 VFP_DREG_M(rm, insn);
2768 } else {
2769 rn = VFP_SREG_N(insn);
2770 if (op == 15 && rn == 15) {
2771 /* Double precision destination. */
2772 VFP_DREG_D(rd, insn);
2773 } else {
2774 rd = VFP_SREG_D(insn);
2776 rm = VFP_SREG_M(insn);
2779 veclen = env->vfp.vec_len;
2780 if (op == 15 && rn > 3)
2781 veclen = 0;
2783 /* Shut up compiler warnings. */
2784 delta_m = 0;
2785 delta_d = 0;
2786 bank_mask = 0;
2788 if (veclen > 0) {
2789 if (dp)
2790 bank_mask = 0xc;
2791 else
2792 bank_mask = 0x18;
2794 /* Figure out what type of vector operation this is. */
2795 if ((rd & bank_mask) == 0) {
2796 /* scalar */
2797 veclen = 0;
2798 } else {
2799 if (dp)
2800 delta_d = (env->vfp.vec_stride >> 1) + 1;
2801 else
2802 delta_d = env->vfp.vec_stride + 1;
2804 if ((rm & bank_mask) == 0) {
2805 /* mixed scalar/vector */
2806 delta_m = 0;
2807 } else {
2808 /* vector */
2809 delta_m = delta_d;
2814 /* Load the initial operands. */
2815 if (op == 15) {
2816 switch (rn) {
2817 case 16:
2818 case 17:
2819 /* Integer source */
2820 gen_mov_F0_vreg(0, rm);
2821 break;
2822 case 8:
2823 case 9:
2824 /* Compare */
2825 gen_mov_F0_vreg(dp, rd);
2826 gen_mov_F1_vreg(dp, rm);
2827 break;
2828 case 10:
2829 case 11:
2830 /* Compare with zero */
2831 gen_mov_F0_vreg(dp, rd);
2832 gen_vfp_F1_ld0(dp);
2833 break;
2834 case 20:
2835 case 21:
2836 case 22:
2837 case 23:
2838 case 28:
2839 case 29:
2840 case 30:
2841 case 31:
2842 /* Source and destination the same. */
2843 gen_mov_F0_vreg(dp, rd);
2844 break;
2845 default:
2846 /* One source operand. */
2847 gen_mov_F0_vreg(dp, rm);
2848 break;
2850 } else {
2851 /* Two source operands. */
2852 gen_mov_F0_vreg(dp, rn);
2853 gen_mov_F1_vreg(dp, rm);
2856 for (;;) {
2857 /* Perform the calculation. */
2858 switch (op) {
2859 case 0: /* mac: fd + (fn * fm) */
2860 gen_vfp_mul(dp);
2861 gen_mov_F1_vreg(dp, rd);
2862 gen_vfp_add(dp);
2863 break;
2864 case 1: /* nmac: fd - (fn * fm) */
2865 gen_vfp_mul(dp);
2866 gen_vfp_neg(dp);
2867 gen_mov_F1_vreg(dp, rd);
2868 gen_vfp_add(dp);
2869 break;
2870 case 2: /* msc: -fd + (fn * fm) */
2871 gen_vfp_mul(dp);
2872 gen_mov_F1_vreg(dp, rd);
2873 gen_vfp_sub(dp);
2874 break;
2875 case 3: /* nmsc: -fd - (fn * fm) */
2876 gen_vfp_mul(dp);
2877 gen_vfp_neg(dp);
2878 gen_mov_F1_vreg(dp, rd);
2879 gen_vfp_sub(dp);
2880 break;
2881 case 4: /* mul: fn * fm */
2882 gen_vfp_mul(dp);
2883 break;
2884 case 5: /* nmul: -(fn * fm) */
2885 gen_vfp_mul(dp);
2886 gen_vfp_neg(dp);
2887 break;
2888 case 6: /* add: fn + fm */
2889 gen_vfp_add(dp);
2890 break;
2891 case 7: /* sub: fn - fm */
2892 gen_vfp_sub(dp);
2893 break;
2894 case 8: /* div: fn / fm */
2895 gen_vfp_div(dp);
2896 break;
2897 case 14: /* fconst */
2898 if (!arm_feature(env, ARM_FEATURE_VFP3))
2899 return 1;
2901 n = (insn << 12) & 0x80000000;
2902 i = ((insn >> 12) & 0x70) | (insn & 0xf);
2903 if (dp) {
2904 if (i & 0x40)
2905 i |= 0x3f80;
2906 else
2907 i |= 0x4000;
2908 n |= i << 16;
2909 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2910 } else {
2911 if (i & 0x40)
2912 i |= 0x780;
2913 else
2914 i |= 0x800;
2915 n |= i << 19;
2916 tcg_gen_movi_i32(cpu_F0s, n);
2918 break;
2919 case 15: /* extension space */
2920 switch (rn) {
2921 case 0: /* cpy */
2922 /* no-op */
2923 break;
2924 case 1: /* abs */
2925 gen_vfp_abs(dp);
2926 break;
2927 case 2: /* neg */
2928 gen_vfp_neg(dp);
2929 break;
2930 case 3: /* sqrt */
2931 gen_vfp_sqrt(dp);
2932 break;
2933 case 8: /* cmp */
2934 gen_vfp_cmp(dp);
2935 break;
2936 case 9: /* cmpe */
2937 gen_vfp_cmpe(dp);
2938 break;
2939 case 10: /* cmpz */
2940 gen_vfp_cmp(dp);
2941 break;
2942 case 11: /* cmpez */
2943 gen_vfp_F1_ld0(dp);
2944 gen_vfp_cmpe(dp);
2945 break;
2946 case 15: /* single<->double conversion */
2947 if (dp)
2948 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
2949 else
2950 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
2951 break;
2952 case 16: /* fuito */
2953 gen_vfp_uito(dp);
2954 break;
2955 case 17: /* fsito */
2956 gen_vfp_sito(dp);
2957 break;
2958 case 20: /* fshto */
2959 if (!arm_feature(env, ARM_FEATURE_VFP3))
2960 return 1;
2961 gen_vfp_shto(dp, 16 - rm);
2962 break;
2963 case 21: /* fslto */
2964 if (!arm_feature(env, ARM_FEATURE_VFP3))
2965 return 1;
2966 gen_vfp_slto(dp, 32 - rm);
2967 break;
2968 case 22: /* fuhto */
2969 if (!arm_feature(env, ARM_FEATURE_VFP3))
2970 return 1;
2971 gen_vfp_uhto(dp, 16 - rm);
2972 break;
2973 case 23: /* fulto */
2974 if (!arm_feature(env, ARM_FEATURE_VFP3))
2975 return 1;
2976 gen_vfp_ulto(dp, 32 - rm);
2977 break;
2978 case 24: /* ftoui */
2979 gen_vfp_toui(dp);
2980 break;
2981 case 25: /* ftouiz */
2982 gen_vfp_touiz(dp);
2983 break;
2984 case 26: /* ftosi */
2985 gen_vfp_tosi(dp);
2986 break;
2987 case 27: /* ftosiz */
2988 gen_vfp_tosiz(dp);
2989 break;
2990 case 28: /* ftosh */
2991 if (!arm_feature(env, ARM_FEATURE_VFP3))
2992 return 1;
2993 gen_vfp_tosh(dp, 16 - rm);
2994 break;
2995 case 29: /* ftosl */
2996 if (!arm_feature(env, ARM_FEATURE_VFP3))
2997 return 1;
2998 gen_vfp_tosl(dp, 32 - rm);
2999 break;
3000 case 30: /* ftouh */
3001 if (!arm_feature(env, ARM_FEATURE_VFP3))
3002 return 1;
3003 gen_vfp_touh(dp, 16 - rm);
3004 break;
3005 case 31: /* ftoul */
3006 if (!arm_feature(env, ARM_FEATURE_VFP3))
3007 return 1;
3008 gen_vfp_toul(dp, 32 - rm);
3009 break;
3010 default: /* undefined */
3011 printf ("rn:%d\n", rn);
3012 return 1;
3014 break;
3015 default: /* undefined */
3016 printf ("op:%d\n", op);
3017 return 1;
3020 /* Write back the result. */
3021 if (op == 15 && (rn >= 8 && rn <= 11))
3022 ; /* Comparison, do nothing. */
3023 else if (op == 15 && rn > 17)
3024 /* Integer result. */
3025 gen_mov_vreg_F0(0, rd);
3026 else if (op == 15 && rn == 15)
3027 /* conversion */
3028 gen_mov_vreg_F0(!dp, rd);
3029 else
3030 gen_mov_vreg_F0(dp, rd);
3032 /* break out of the loop if we have finished */
3033 if (veclen == 0)
3034 break;
3036 if (op == 15 && delta_m == 0) {
3037 /* single source one-many */
3038 while (veclen--) {
3039 rd = ((rd + delta_d) & (bank_mask - 1))
3040 | (rd & bank_mask);
3041 gen_mov_vreg_F0(dp, rd);
3043 break;
3045 /* Setup the next operands. */
3046 veclen--;
3047 rd = ((rd + delta_d) & (bank_mask - 1))
3048 | (rd & bank_mask);
3050 if (op == 15) {
3051 /* One source operand. */
3052 rm = ((rm + delta_m) & (bank_mask - 1))
3053 | (rm & bank_mask);
3054 gen_mov_F0_vreg(dp, rm);
3055 } else {
3056 /* Two source operands. */
3057 rn = ((rn + delta_d) & (bank_mask - 1))
3058 | (rn & bank_mask);
3059 gen_mov_F0_vreg(dp, rn);
3060 if (delta_m) {
3061 rm = ((rm + delta_m) & (bank_mask - 1))
3062 | (rm & bank_mask);
3063 gen_mov_F1_vreg(dp, rm);
3068 break;
3069 case 0xc:
3070 case 0xd:
3071 if (dp && (insn & 0x03e00000) == 0x00400000) {
3072 /* two-register transfer */
3073 rn = (insn >> 16) & 0xf;
3074 rd = (insn >> 12) & 0xf;
3075 if (dp) {
3076 VFP_DREG_M(rm, insn);
3077 } else {
3078 rm = VFP_SREG_M(insn);
3081 if (insn & ARM_CP_RW_BIT) {
3082 /* vfp->arm */
3083 if (dp) {
3084 gen_mov_F0_vreg(0, rm * 2);
3085 tmp = gen_vfp_mrs();
3086 store_reg(s, rd, tmp);
3087 gen_mov_F0_vreg(0, rm * 2 + 1);
3088 tmp = gen_vfp_mrs();
3089 store_reg(s, rn, tmp);
3090 } else {
3091 gen_mov_F0_vreg(0, rm);
3092 tmp = gen_vfp_mrs();
3093 store_reg(s, rn, tmp);
3094 gen_mov_F0_vreg(0, rm + 1);
3095 tmp = gen_vfp_mrs();
3096 store_reg(s, rd, tmp);
3098 } else {
3099 /* arm->vfp */
3100 if (dp) {
3101 tmp = load_reg(s, rd);
3102 gen_vfp_msr(tmp);
3103 gen_mov_vreg_F0(0, rm * 2);
3104 tmp = load_reg(s, rn);
3105 gen_vfp_msr(tmp);
3106 gen_mov_vreg_F0(0, rm * 2 + 1);
3107 } else {
3108 tmp = load_reg(s, rn);
3109 gen_vfp_msr(tmp);
3110 gen_mov_vreg_F0(0, rm);
3111 tmp = load_reg(s, rd);
3112 gen_vfp_msr(tmp);
3113 gen_mov_vreg_F0(0, rm + 1);
3116 } else {
3117 /* Load/store */
3118 rn = (insn >> 16) & 0xf;
3119 if (dp)
3120 VFP_DREG_D(rd, insn);
3121 else
3122 rd = VFP_SREG_D(insn);
3123 if (s->thumb && rn == 15) {
3124 addr = new_tmp();
3125 tcg_gen_movi_i32(addr, s->pc & ~2);
3126 } else {
3127 addr = load_reg(s, rn);
3129 if ((insn & 0x01200000) == 0x01000000) {
3130 /* Single load/store */
3131 offset = (insn & 0xff) << 2;
3132 if ((insn & (1 << 23)) == 0)
3133 offset = -offset;
3134 tcg_gen_addi_i32(addr, addr, offset);
3135 if (insn & (1 << 20)) {
3136 gen_vfp_ld(s, dp, addr);
3137 gen_mov_vreg_F0(dp, rd);
3138 } else {
3139 gen_mov_F0_vreg(dp, rd);
3140 gen_vfp_st(s, dp, addr);
3142 } else {
3143 /* load/store multiple */
3144 if (dp)
3145 n = (insn >> 1) & 0x7f;
3146 else
3147 n = insn & 0xff;
3149 if (insn & (1 << 24)) /* pre-decrement */
3150 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3152 if (dp)
3153 offset = 8;
3154 else
3155 offset = 4;
3156 for (i = 0; i < n; i++) {
3157 if (insn & ARM_CP_RW_BIT) {
3158 /* load */
3159 gen_vfp_ld(s, dp, addr);
3160 gen_mov_vreg_F0(dp, rd + i);
3161 } else {
3162 /* store */
3163 gen_mov_F0_vreg(dp, rd + i);
3164 gen_vfp_st(s, dp, addr);
3166 tcg_gen_addi_i32(addr, addr, offset);
3168 if (insn & (1 << 21)) {
3169 /* writeback */
3170 if (insn & (1 << 24))
3171 offset = -offset * n;
3172 else if (dp && (insn & 1))
3173 offset = 4;
3174 else
3175 offset = 0;
3177 if (offset != 0)
3178 tcg_gen_addi_i32(addr, addr, offset);
3179 store_reg(s, rn, addr);
3180 } else {
3181 dead_tmp(addr);
3185 break;
3186 default:
3187 /* Should never happen. */
3188 return 1;
3190 return 0;
3193 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3195 TranslationBlock *tb;
3197 tb = s->tb;
3198 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3199 tcg_gen_goto_tb(n);
3200 gen_set_pc_im(dest);
3201 tcg_gen_exit_tb((long)tb + n);
3202 } else {
3203 gen_set_pc_im(dest);
3204 tcg_gen_exit_tb(0);
3208 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3210 if (unlikely(s->singlestep_enabled)) {
3211 /* An indirect jump so that we still trigger the debug exception. */
3212 if (s->thumb)
3213 dest |= 1;
3214 gen_bx_im(s, dest);
3215 } else {
3216 gen_goto_tb(s, 0, dest);
3217 s->is_jmp = DISAS_TB_JUMP;
3221 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3223 if (x)
3224 tcg_gen_sari_i32(t0, t0, 16);
3225 else
3226 gen_sxth(t0);
3227 if (y)
3228 tcg_gen_sari_i32(t1, t1, 16);
3229 else
3230 gen_sxth(t1);
3231 tcg_gen_mul_i32(t0, t0, t1);
3234 /* Return the mask of PSR bits set by a MSR instruction. */
3235 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3236 uint32_t mask;
3238 mask = 0;
3239 if (flags & (1 << 0))
3240 mask |= 0xff;
3241 if (flags & (1 << 1))
3242 mask |= 0xff00;
3243 if (flags & (1 << 2))
3244 mask |= 0xff0000;
3245 if (flags & (1 << 3))
3246 mask |= 0xff000000;
3248 /* Mask out undefined bits. */
3249 mask &= ~CPSR_RESERVED;
3250 if (!arm_feature(env, ARM_FEATURE_V6))
3251 mask &= ~(CPSR_E | CPSR_GE);
3252 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3253 mask &= ~CPSR_IT;
3254 /* Mask out execution state bits. */
3255 if (!spsr)
3256 mask &= ~CPSR_EXEC;
3257 /* Mask out privileged bits. */
3258 if (IS_USER(s))
3259 mask &= CPSR_USER;
3260 return mask;
3263 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3264 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3266 TCGv tmp;
3267 if (spsr) {
3268 /* ??? This is also undefined in system mode. */
3269 if (IS_USER(s))
3270 return 1;
3272 tmp = load_cpu_field(spsr);
3273 tcg_gen_andi_i32(tmp, tmp, ~mask);
3274 tcg_gen_andi_i32(t0, t0, mask);
3275 tcg_gen_or_i32(tmp, tmp, t0);
3276 store_cpu_field(tmp, spsr);
3277 } else {
3278 gen_set_cpsr(t0, mask);
3280 dead_tmp(t0);
3281 gen_lookup_tb(s);
3282 return 0;
3285 /* Returns nonzero if access to the PSR is not permitted. */
3286 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3288 TCGv tmp;
3289 tmp = new_tmp();
3290 tcg_gen_movi_i32(tmp, val);
3291 return gen_set_psr(s, mask, spsr, tmp);
3294 /* Generate an old-style exception return. Marks pc as dead. */
3295 static void gen_exception_return(DisasContext *s, TCGv pc)
3297 TCGv tmp;
3298 store_reg(s, 15, pc);
3299 tmp = load_cpu_field(spsr);
3300 gen_set_cpsr(tmp, 0xffffffff);
3301 dead_tmp(tmp);
3302 s->is_jmp = DISAS_UPDATE;
3305 /* Generate a v6 exception return. Marks both values as dead. */
3306 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3308 gen_set_cpsr(cpsr, 0xffffffff);
3309 dead_tmp(cpsr);
3310 store_reg(s, 15, pc);
3311 s->is_jmp = DISAS_UPDATE;
3314 static inline void
3315 gen_set_condexec (DisasContext *s)
3317 if (s->condexec_mask) {
3318 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3319 TCGv tmp = new_tmp();
3320 tcg_gen_movi_i32(tmp, val);
3321 store_cpu_field(tmp, condexec_bits);
3325 static void gen_nop_hint(DisasContext *s, int val)
3327 switch (val) {
3328 case 3: /* wfi */
3329 gen_set_pc_im(s->pc);
3330 s->is_jmp = DISAS_WFI;
3331 break;
3332 case 2: /* wfe */
3333 case 4: /* sev */
3334 /* TODO: Implement SEV and WFE. May help SMP performance. */
3335 default: /* nop */
3336 break;
3340 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3342 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3344 switch (size) {
3345 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3346 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3347 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3348 default: return 1;
3350 return 0;
3353 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3355 switch (size) {
3356 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3357 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3358 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3359 default: return;
3363 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3364 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3365 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3366 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3367 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3369 /* FIXME: This is wrong. They set the wrong overflow bit. */
3370 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3371 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3372 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3373 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3375 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3376 switch ((size << 1) | u) { \
3377 case 0: \
3378 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3379 break; \
3380 case 1: \
3381 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3382 break; \
3383 case 2: \
3384 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3385 break; \
3386 case 3: \
3387 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3388 break; \
3389 case 4: \
3390 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3391 break; \
3392 case 5: \
3393 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3394 break; \
3395 default: return 1; \
3396 }} while (0)
3398 #define GEN_NEON_INTEGER_OP(name) do { \
3399 switch ((size << 1) | u) { \
3400 case 0: \
3401 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3402 break; \
3403 case 1: \
3404 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3405 break; \
3406 case 2: \
3407 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3408 break; \
3409 case 3: \
3410 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3411 break; \
3412 case 4: \
3413 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3414 break; \
3415 case 5: \
3416 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3417 break; \
3418 default: return 1; \
3419 }} while (0)
3421 static TCGv neon_load_scratch(int scratch)
3423 TCGv tmp = new_tmp();
3424 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3425 return tmp;
3428 static void neon_store_scratch(int scratch, TCGv var)
3430 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3431 dead_tmp(var);
3434 static inline TCGv neon_get_scalar(int size, int reg)
3436 TCGv tmp;
3437 if (size == 1) {
3438 tmp = neon_load_reg(reg >> 1, reg & 1);
3439 } else {
3440 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3441 if (reg & 1) {
3442 gen_neon_dup_low16(tmp);
3443 } else {
3444 gen_neon_dup_high16(tmp);
3447 return tmp;
3450 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3452 TCGv rd, rm, tmp;
3454 rd = new_tmp();
3455 rm = new_tmp();
3456 tmp = new_tmp();
3458 tcg_gen_andi_i32(rd, t0, 0xff);
3459 tcg_gen_shri_i32(tmp, t0, 8);
3460 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3461 tcg_gen_or_i32(rd, rd, tmp);
3462 tcg_gen_shli_i32(tmp, t1, 16);
3463 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3464 tcg_gen_or_i32(rd, rd, tmp);
3465 tcg_gen_shli_i32(tmp, t1, 8);
3466 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3467 tcg_gen_or_i32(rd, rd, tmp);
3469 tcg_gen_shri_i32(rm, t0, 8);
3470 tcg_gen_andi_i32(rm, rm, 0xff);
3471 tcg_gen_shri_i32(tmp, t0, 16);
3472 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3473 tcg_gen_or_i32(rm, rm, tmp);
3474 tcg_gen_shli_i32(tmp, t1, 8);
3475 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3476 tcg_gen_or_i32(rm, rm, tmp);
3477 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3478 tcg_gen_or_i32(t1, rm, tmp);
3479 tcg_gen_mov_i32(t0, rd);
3481 dead_tmp(tmp);
3482 dead_tmp(rm);
3483 dead_tmp(rd);
3486 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3488 TCGv rd, rm, tmp;
3490 rd = new_tmp();
3491 rm = new_tmp();
3492 tmp = new_tmp();
3494 tcg_gen_andi_i32(rd, t0, 0xff);
3495 tcg_gen_shli_i32(tmp, t1, 8);
3496 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3497 tcg_gen_or_i32(rd, rd, tmp);
3498 tcg_gen_shli_i32(tmp, t0, 16);
3499 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3500 tcg_gen_or_i32(rd, rd, tmp);
3501 tcg_gen_shli_i32(tmp, t1, 24);
3502 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3503 tcg_gen_or_i32(rd, rd, tmp);
3505 tcg_gen_andi_i32(rm, t1, 0xff000000);
3506 tcg_gen_shri_i32(tmp, t0, 8);
3507 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3508 tcg_gen_or_i32(rm, rm, tmp);
3509 tcg_gen_shri_i32(tmp, t1, 8);
3510 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3511 tcg_gen_or_i32(rm, rm, tmp);
3512 tcg_gen_shri_i32(tmp, t0, 16);
3513 tcg_gen_andi_i32(tmp, tmp, 0xff);
3514 tcg_gen_or_i32(t1, rm, tmp);
3515 tcg_gen_mov_i32(t0, rd);
3517 dead_tmp(tmp);
3518 dead_tmp(rm);
3519 dead_tmp(rd);
3522 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3524 TCGv tmp, tmp2;
3526 tmp = new_tmp();
3527 tmp2 = new_tmp();
3529 tcg_gen_andi_i32(tmp, t0, 0xffff);
3530 tcg_gen_shli_i32(tmp2, t1, 16);
3531 tcg_gen_or_i32(tmp, tmp, tmp2);
3532 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3533 tcg_gen_shri_i32(tmp2, t0, 16);
3534 tcg_gen_or_i32(t1, t1, tmp2);
3535 tcg_gen_mov_i32(t0, tmp);
3537 dead_tmp(tmp2);
3538 dead_tmp(tmp);
3541 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3543 int n;
3544 TCGv t0, t1;
3546 for (n = 0; n < q + 1; n += 2) {
3547 t0 = neon_load_reg(reg, n);
3548 t1 = neon_load_reg(reg, n + 1);
3549 switch (size) {
3550 case 0: gen_neon_unzip_u8(t0, t1); break;
3551 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3552 case 2: /* no-op */; break;
3553 default: abort();
3555 neon_store_scratch(tmp + n, t0);
3556 neon_store_scratch(tmp + n + 1, t1);
3560 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3562 TCGv rd, tmp;
3564 rd = new_tmp();
3565 tmp = new_tmp();
3567 tcg_gen_shli_i32(rd, t0, 8);
3568 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3569 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3570 tcg_gen_or_i32(rd, rd, tmp);
3572 tcg_gen_shri_i32(t1, t1, 8);
3573 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3574 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3575 tcg_gen_or_i32(t1, t1, tmp);
3576 tcg_gen_mov_i32(t0, rd);
3578 dead_tmp(tmp);
3579 dead_tmp(rd);
3582 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3584 TCGv rd, tmp;
3586 rd = new_tmp();
3587 tmp = new_tmp();
3589 tcg_gen_shli_i32(rd, t0, 16);
3590 tcg_gen_andi_i32(tmp, t1, 0xffff);
3591 tcg_gen_or_i32(rd, rd, tmp);
3592 tcg_gen_shri_i32(t1, t1, 16);
3593 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3594 tcg_gen_or_i32(t1, t1, tmp);
3595 tcg_gen_mov_i32(t0, rd);
3597 dead_tmp(tmp);
3598 dead_tmp(rd);
3602 static struct {
3603 int nregs;
3604 int interleave;
3605 int spacing;
3606 } neon_ls_element_type[11] = {
3607 {4, 4, 1},
3608 {4, 4, 2},
3609 {4, 1, 1},
3610 {4, 2, 1},
3611 {3, 3, 1},
3612 {3, 3, 2},
3613 {3, 1, 1},
3614 {1, 1, 1},
3615 {2, 2, 1},
3616 {2, 2, 2},
3617 {2, 1, 1}
3620 /* Translate a NEON load/store element instruction. Return nonzero if the
3621 instruction is invalid. */
3622 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3624 int rd, rn, rm;
3625 int op;
3626 int nregs;
3627 int interleave;
3628 int stride;
3629 int size;
3630 int reg;
3631 int pass;
3632 int load;
3633 int shift;
3634 int n;
3635 TCGv addr;
3636 TCGv tmp;
3637 TCGv tmp2;
3639 if (!vfp_enabled(env))
3640 return 1;
3641 VFP_DREG_D(rd, insn);
3642 rn = (insn >> 16) & 0xf;
3643 rm = insn & 0xf;
3644 load = (insn & (1 << 21)) != 0;
3645 addr = new_tmp();
3646 if ((insn & (1 << 23)) == 0) {
3647 /* Load store all elements. */
3648 op = (insn >> 8) & 0xf;
3649 size = (insn >> 6) & 3;
3650 if (op > 10 || size == 3)
3651 return 1;
3652 nregs = neon_ls_element_type[op].nregs;
3653 interleave = neon_ls_element_type[op].interleave;
3654 tcg_gen_mov_i32(addr, cpu_R[rn]);
3655 stride = (1 << size) * interleave;
3656 for (reg = 0; reg < nregs; reg++) {
3657 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3658 tcg_gen_add_i32(addr, cpu_R[rn], (1 << size) * reg);
3659 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3660 tcg_gen_add_i32(addr, cpu_R[rn], 1 << size);
3662 for (pass = 0; pass < 2; pass++) {
3663 if (size == 2) {
3664 if (load) {
3665 tmp = gen_ld32(addr, IS_USER(s));
3666 neon_store_reg(rd, pass, tmp);
3667 } else {
3668 tmp = neon_load_reg(rd, pass);
3669 gen_st32(tmp, addr, IS_USER(s));
3671 tcg_gen_addi_i32(addr, addr, stride);
3672 } else if (size == 1) {
3673 if (load) {
3674 tmp = gen_ld16u(addr, IS_USER(s));
3675 tcg_gen_addi_i32(addr, addr, stride);
3676 tmp2 = gen_ld16u(addr, IS_USER(s));
3677 tcg_gen_addi_i32(addr, addr, stride);
3678 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3679 dead_tmp(tmp2);
3680 neon_store_reg(rd, pass, tmp);
3681 } else {
3682 tmp = neon_load_reg(rd, pass);
3683 tmp2 = new_tmp();
3684 tcg_gen_shri_i32(tmp2, tmp, 16);
3685 gen_st16(tmp, addr, IS_USER(s));
3686 tcg_gen_addi_i32(addr, addr, stride);
3687 gen_st16(tmp2, addr, IS_USER(s));
3688 tcg_gen_addi_i32(addr, addr, stride);
3690 } else /* size == 0 */ {
3691 if (load) {
3692 TCGV_UNUSED(tmp2);
3693 for (n = 0; n < 4; n++) {
3694 tmp = gen_ld8u(addr, IS_USER(s));
3695 tcg_gen_addi_i32(addr, addr, stride);
3696 if (n == 0) {
3697 tmp2 = tmp;
3698 } else {
3699 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3700 dead_tmp(tmp);
3703 neon_store_reg(rd, pass, tmp2);
3704 } else {
3705 tmp2 = neon_load_reg(rd, pass);
3706 for (n = 0; n < 4; n++) {
3707 tmp = new_tmp();
3708 if (n == 0) {
3709 tcg_gen_mov_i32(tmp, tmp2);
3710 } else {
3711 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3713 gen_st8(tmp, addr, IS_USER(s));
3714 tcg_gen_addi_i32(addr, addr, stride);
3716 dead_tmp(tmp2);
3720 rd += neon_ls_element_type[op].spacing;
3722 stride = nregs * 8;
3723 } else {
3724 size = (insn >> 10) & 3;
3725 if (size == 3) {
3726 /* Load single element to all lanes. */
3727 if (!load)
3728 return 1;
3729 size = (insn >> 6) & 3;
3730 nregs = ((insn >> 8) & 3) + 1;
3731 stride = (insn & (1 << 5)) ? 2 : 1;
3732 tcg_gen_mov_i32(addr, cpu_R[rn]);
3733 for (reg = 0; reg < nregs; reg++) {
3734 switch (size) {
3735 case 0:
3736 tmp = gen_ld8u(addr, IS_USER(s));
3737 gen_neon_dup_u8(tmp, 0);
3738 break;
3739 case 1:
3740 tmp = gen_ld16u(addr, IS_USER(s));
3741 gen_neon_dup_low16(tmp);
3742 break;
3743 case 2:
3744 tmp = gen_ld32(addr, IS_USER(s));
3745 break;
3746 case 3:
3747 return 1;
3748 default: /* Avoid compiler warnings. */
3749 abort();
3751 tcg_gen_addi_i32(addr, addr, 1 << size);
3752 tmp2 = new_tmp();
3753 tcg_gen_mov_i32(tmp2, tmp);
3754 neon_store_reg(rd, 0, tmp2);
3755 neon_store_reg(rd, 1, tmp);
3756 rd += stride;
3758 stride = (1 << size) * nregs;
3759 } else {
3760 /* Single element. */
3761 pass = (insn >> 7) & 1;
3762 switch (size) {
3763 case 0:
3764 shift = ((insn >> 5) & 3) * 8;
3765 stride = 1;
3766 break;
3767 case 1:
3768 shift = ((insn >> 6) & 1) * 16;
3769 stride = (insn & (1 << 5)) ? 2 : 1;
3770 break;
3771 case 2:
3772 shift = 0;
3773 stride = (insn & (1 << 6)) ? 2 : 1;
3774 break;
3775 default:
3776 abort();
3778 nregs = ((insn >> 8) & 3) + 1;
3779 tcg_gen_mov_i32(addr, cpu_R[rn]);
3780 for (reg = 0; reg < nregs; reg++) {
3781 if (load) {
3782 switch (size) {
3783 case 0:
3784 tmp = gen_ld8u(addr, IS_USER(s));
3785 break;
3786 case 1:
3787 tmp = gen_ld16u(addr, IS_USER(s));
3788 break;
3789 case 2:
3790 tmp = gen_ld32(addr, IS_USER(s));
3791 break;
3792 default: /* Avoid compiler warnings. */
3793 abort();
3795 if (size != 2) {
3796 tmp2 = neon_load_reg(rd, pass);
3797 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3798 dead_tmp(tmp2);
3800 neon_store_reg(rd, pass, tmp);
3801 } else { /* Store */
3802 tmp = neon_load_reg(rd, pass);
3803 if (shift)
3804 tcg_gen_shri_i32(tmp, tmp, shift);
3805 switch (size) {
3806 case 0:
3807 gen_st8(tmp, addr, IS_USER(s));
3808 break;
3809 case 1:
3810 gen_st16(tmp, addr, IS_USER(s));
3811 break;
3812 case 2:
3813 gen_st32(tmp, addr, IS_USER(s));
3814 break;
3817 rd += stride;
3818 tcg_gen_addi_i32(addr, addr, 1 << size);
3820 stride = nregs * (1 << size);
3823 dead_tmp(addr);
3824 if (rm != 15) {
3825 TCGv base;
3827 base = load_reg(s, rn);
3828 if (rm == 13) {
3829 tcg_gen_addi_i32(base, base, stride);
3830 } else {
3831 TCGv index;
3832 index = load_reg(s, rm);
3833 tcg_gen_add_i32(base, base, index);
3834 dead_tmp(index);
3836 store_reg(s, rn, base);
3838 return 0;
3841 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3842 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3844 tcg_gen_and_i32(t, t, c);
3845 tcg_gen_bic_i32(f, f, c);
3846 tcg_gen_or_i32(dest, t, f);
3849 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3851 switch (size) {
3852 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3853 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3854 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3855 default: abort();
3859 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3861 switch (size) {
3862 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3863 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3864 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3865 default: abort();
3869 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3871 switch (size) {
3872 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3873 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3874 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3875 default: abort();
3879 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3880 int q, int u)
3882 if (q) {
3883 if (u) {
3884 switch (size) {
3885 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3886 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3887 default: abort();
3889 } else {
3890 switch (size) {
3891 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3892 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3893 default: abort();
3896 } else {
3897 if (u) {
3898 switch (size) {
3899 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3900 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3901 default: abort();
3903 } else {
3904 switch (size) {
3905 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3906 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3907 default: abort();
3913 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3915 if (u) {
3916 switch (size) {
3917 case 0: gen_helper_neon_widen_u8(dest, src); break;
3918 case 1: gen_helper_neon_widen_u16(dest, src); break;
3919 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3920 default: abort();
3922 } else {
3923 switch (size) {
3924 case 0: gen_helper_neon_widen_s8(dest, src); break;
3925 case 1: gen_helper_neon_widen_s16(dest, src); break;
3926 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3927 default: abort();
3930 dead_tmp(src);
3933 static inline void gen_neon_addl(int size)
3935 switch (size) {
3936 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3937 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3938 case 2: tcg_gen_add_i64(CPU_V001); break;
3939 default: abort();
3943 static inline void gen_neon_subl(int size)
3945 switch (size) {
3946 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3947 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3948 case 2: tcg_gen_sub_i64(CPU_V001); break;
3949 default: abort();
3953 static inline void gen_neon_negl(TCGv_i64 var, int size)
3955 switch (size) {
3956 case 0: gen_helper_neon_negl_u16(var, var); break;
3957 case 1: gen_helper_neon_negl_u32(var, var); break;
3958 case 2: gen_helper_neon_negl_u64(var, var); break;
3959 default: abort();
3963 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
3965 switch (size) {
3966 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3967 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
3968 default: abort();
3972 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
3974 TCGv_i64 tmp;
3976 switch ((size << 1) | u) {
3977 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3978 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3979 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3980 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3981 case 4:
3982 tmp = gen_muls_i64_i32(a, b);
3983 tcg_gen_mov_i64(dest, tmp);
3984 break;
3985 case 5:
3986 tmp = gen_mulu_i64_i32(a, b);
3987 tcg_gen_mov_i64(dest, tmp);
3988 break;
3989 default: abort();
3993 /* Translate a NEON data processing instruction. Return nonzero if the
3994 instruction is invalid.
3995 We process data in a mixture of 32-bit and 64-bit chunks.
3996 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
3998 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4000 int op;
4001 int q;
4002 int rd, rn, rm;
4003 int size;
4004 int shift;
4005 int pass;
4006 int count;
4007 int pairwise;
4008 int u;
4009 int n;
4010 uint32_t imm;
4011 TCGv tmp;
4012 TCGv tmp2;
4013 TCGv tmp3;
4014 TCGv_i64 tmp64;
4016 if (!vfp_enabled(env))
4017 return 1;
4018 q = (insn & (1 << 6)) != 0;
4019 u = (insn >> 24) & 1;
4020 VFP_DREG_D(rd, insn);
4021 VFP_DREG_N(rn, insn);
4022 VFP_DREG_M(rm, insn);
4023 size = (insn >> 20) & 3;
4024 if ((insn & (1 << 23)) == 0) {
4025 /* Three register same length. */
4026 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4027 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4028 || op == 10 || op == 11 || op == 16)) {
4029 /* 64-bit element instructions. */
4030 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4031 neon_load_reg64(cpu_V0, rn + pass);
4032 neon_load_reg64(cpu_V1, rm + pass);
4033 switch (op) {
4034 case 1: /* VQADD */
4035 if (u) {
4036 gen_helper_neon_add_saturate_u64(CPU_V001);
4037 } else {
4038 gen_helper_neon_add_saturate_s64(CPU_V001);
4040 break;
4041 case 5: /* VQSUB */
4042 if (u) {
4043 gen_helper_neon_sub_saturate_u64(CPU_V001);
4044 } else {
4045 gen_helper_neon_sub_saturate_s64(CPU_V001);
4047 break;
4048 case 8: /* VSHL */
4049 if (u) {
4050 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4051 } else {
4052 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4054 break;
4055 case 9: /* VQSHL */
4056 if (u) {
4057 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4058 cpu_V0, cpu_V0);
4059 } else {
4060 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4061 cpu_V1, cpu_V0);
4063 break;
4064 case 10: /* VRSHL */
4065 if (u) {
4066 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4067 } else {
4068 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4070 break;
4071 case 11: /* VQRSHL */
4072 if (u) {
4073 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4074 cpu_V1, cpu_V0);
4075 } else {
4076 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4077 cpu_V1, cpu_V0);
4079 break;
4080 case 16:
4081 if (u) {
4082 tcg_gen_sub_i64(CPU_V001);
4083 } else {
4084 tcg_gen_add_i64(CPU_V001);
4086 break;
4087 default:
4088 abort();
4090 neon_store_reg64(cpu_V0, rd + pass);
4092 return 0;
4094 switch (op) {
4095 case 8: /* VSHL */
4096 case 9: /* VQSHL */
4097 case 10: /* VRSHL */
4098 case 11: /* VQRSHL */
4100 int rtmp;
4101 /* Shift instruction operands are reversed. */
4102 rtmp = rn;
4103 rn = rm;
4104 rm = rtmp;
4105 pairwise = 0;
4107 break;
4108 case 20: /* VPMAX */
4109 case 21: /* VPMIN */
4110 case 23: /* VPADD */
4111 pairwise = 1;
4112 break;
4113 case 26: /* VPADD (float) */
4114 pairwise = (u && size < 2);
4115 break;
4116 case 30: /* VPMIN/VPMAX (float) */
4117 pairwise = u;
4118 break;
4119 default:
4120 pairwise = 0;
4121 break;
4124 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4126 if (pairwise) {
4127 /* Pairwise. */
4128 if (q)
4129 n = (pass & 1) * 2;
4130 else
4131 n = 0;
4132 if (pass < q + 1) {
4133 tmp = neon_load_reg(rn, n);
4134 tmp2 = neon_load_reg(rn, n + 1);
4135 } else {
4136 tmp = neon_load_reg(rm, n);
4137 tmp2 = neon_load_reg(rm, n + 1);
4139 } else {
4140 /* Elementwise. */
4141 tmp = neon_load_reg(rn, pass);
4142 tmp2 = neon_load_reg(rm, pass);
4144 switch (op) {
4145 case 0: /* VHADD */
4146 GEN_NEON_INTEGER_OP(hadd);
4147 break;
4148 case 1: /* VQADD */
4149 GEN_NEON_INTEGER_OP_ENV(qadd);
4150 break;
4151 case 2: /* VRHADD */
4152 GEN_NEON_INTEGER_OP(rhadd);
4153 break;
4154 case 3: /* Logic ops. */
4155 switch ((u << 2) | size) {
4156 case 0: /* VAND */
4157 tcg_gen_and_i32(tmp, tmp, tmp2);
4158 break;
4159 case 1: /* BIC */
4160 tcg_gen_bic_i32(tmp, tmp, tmp2);
4161 break;
4162 case 2: /* VORR */
4163 tcg_gen_or_i32(tmp, tmp, tmp2);
4164 break;
4165 case 3: /* VORN */
4166 tcg_gen_not_i32(tmp2, tmp2);
4167 tcg_gen_or_i32(tmp, tmp, tmp2);
4168 break;
4169 case 4: /* VEOR */
4170 tcg_gen_xor_i32(tmp, tmp, tmp2);
4171 break;
4172 case 5: /* VBSL */
4173 tmp3 = neon_load_reg(rd, pass);
4174 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4175 dead_tmp(tmp3);
4176 break;
4177 case 6: /* VBIT */
4178 tmp3 = neon_load_reg(rd, pass);
4179 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4180 dead_tmp(tmp3);
4181 break;
4182 case 7: /* VBIF */
4183 tmp3 = neon_load_reg(rd, pass);
4184 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4185 dead_tmp(tmp3);
4186 break;
4188 break;
4189 case 4: /* VHSUB */
4190 GEN_NEON_INTEGER_OP(hsub);
4191 break;
4192 case 5: /* VQSUB */
4193 GEN_NEON_INTEGER_OP_ENV(qsub);
4194 break;
4195 case 6: /* VCGT */
4196 GEN_NEON_INTEGER_OP(cgt);
4197 break;
4198 case 7: /* VCGE */
4199 GEN_NEON_INTEGER_OP(cge);
4200 break;
4201 case 8: /* VSHL */
4202 GEN_NEON_INTEGER_OP(shl);
4203 break;
4204 case 9: /* VQSHL */
4205 GEN_NEON_INTEGER_OP_ENV(qshl);
4206 break;
4207 case 10: /* VRSHL */
4208 GEN_NEON_INTEGER_OP(rshl);
4209 break;
4210 case 11: /* VQRSHL */
4211 GEN_NEON_INTEGER_OP_ENV(qrshl);
4212 break;
4213 case 12: /* VMAX */
4214 GEN_NEON_INTEGER_OP(max);
4215 break;
4216 case 13: /* VMIN */
4217 GEN_NEON_INTEGER_OP(min);
4218 break;
4219 case 14: /* VABD */
4220 GEN_NEON_INTEGER_OP(abd);
4221 break;
4222 case 15: /* VABA */
4223 GEN_NEON_INTEGER_OP(abd);
4224 dead_tmp(tmp2);
4225 tmp2 = neon_load_reg(rd, pass);
4226 gen_neon_add(size, tmp, tmp2);
4227 break;
4228 case 16:
4229 if (!u) { /* VADD */
4230 if (gen_neon_add(size, tmp, tmp2))
4231 return 1;
4232 } else { /* VSUB */
4233 switch (size) {
4234 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4235 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4236 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4237 default: return 1;
4240 break;
4241 case 17:
4242 if (!u) { /* VTST */
4243 switch (size) {
4244 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4245 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4246 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4247 default: return 1;
4249 } else { /* VCEQ */
4250 switch (size) {
4251 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4252 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4253 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4254 default: return 1;
4257 break;
4258 case 18: /* Multiply. */
4259 switch (size) {
4260 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4261 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4262 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4263 default: return 1;
4265 dead_tmp(tmp2);
4266 tmp2 = neon_load_reg(rd, pass);
4267 if (u) { /* VMLS */
4268 gen_neon_rsb(size, tmp, tmp2);
4269 } else { /* VMLA */
4270 gen_neon_add(size, tmp, tmp2);
4272 break;
4273 case 19: /* VMUL */
4274 if (u) { /* polynomial */
4275 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4276 } else { /* Integer */
4277 switch (size) {
4278 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4279 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4280 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4281 default: return 1;
4284 break;
4285 case 20: /* VPMAX */
4286 GEN_NEON_INTEGER_OP(pmax);
4287 break;
4288 case 21: /* VPMIN */
4289 GEN_NEON_INTEGER_OP(pmin);
4290 break;
4291 case 22: /* Hultiply high. */
4292 if (!u) { /* VQDMULH */
4293 switch (size) {
4294 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4295 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4296 default: return 1;
4298 } else { /* VQRDHMUL */
4299 switch (size) {
4300 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4301 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4302 default: return 1;
4305 break;
4306 case 23: /* VPADD */
4307 if (u)
4308 return 1;
4309 switch (size) {
4310 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4311 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4312 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4313 default: return 1;
4315 break;
4316 case 26: /* Floating point arithnetic. */
4317 switch ((u << 2) | size) {
4318 case 0: /* VADD */
4319 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4320 break;
4321 case 2: /* VSUB */
4322 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4323 break;
4324 case 4: /* VPADD */
4325 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4326 break;
4327 case 6: /* VABD */
4328 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4329 break;
4330 default:
4331 return 1;
4333 break;
4334 case 27: /* Float multiply. */
4335 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4336 if (!u) {
4337 dead_tmp(tmp2);
4338 tmp2 = neon_load_reg(rd, pass);
4339 if (size == 0) {
4340 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4341 } else {
4342 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4345 break;
4346 case 28: /* Float compare. */
4347 if (!u) {
4348 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4349 } else {
4350 if (size == 0)
4351 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4352 else
4353 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4355 break;
4356 case 29: /* Float compare absolute. */
4357 if (!u)
4358 return 1;
4359 if (size == 0)
4360 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4361 else
4362 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4363 break;
4364 case 30: /* Float min/max. */
4365 if (size == 0)
4366 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4367 else
4368 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4369 break;
4370 case 31:
4371 if (size == 0)
4372 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4373 else
4374 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4375 break;
4376 default:
4377 abort();
4379 dead_tmp(tmp2);
4381 /* Save the result. For elementwise operations we can put it
4382 straight into the destination register. For pairwise operations
4383 we have to be careful to avoid clobbering the source operands. */
4384 if (pairwise && rd == rm) {
4385 neon_store_scratch(pass, tmp);
4386 } else {
4387 neon_store_reg(rd, pass, tmp);
4390 } /* for pass */
4391 if (pairwise && rd == rm) {
4392 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4393 tmp = neon_load_scratch(pass);
4394 neon_store_reg(rd, pass, tmp);
4397 /* End of 3 register same size operations. */
4398 } else if (insn & (1 << 4)) {
4399 if ((insn & 0x00380080) != 0) {
4400 /* Two registers and shift. */
4401 op = (insn >> 8) & 0xf;
4402 if (insn & (1 << 7)) {
4403 /* 64-bit shift. */
4404 size = 3;
4405 } else {
4406 size = 2;
4407 while ((insn & (1 << (size + 19))) == 0)
4408 size--;
4410 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4411 /* To avoid excessive dumplication of ops we implement shift
4412 by immediate using the variable shift operations. */
4413 if (op < 8) {
4414 /* Shift by immediate:
4415 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4416 /* Right shifts are encoded as N - shift, where N is the
4417 element size in bits. */
4418 if (op <= 4)
4419 shift = shift - (1 << (size + 3));
4420 if (size == 3) {
4421 count = q + 1;
4422 } else {
4423 count = q ? 4: 2;
4425 switch (size) {
4426 case 0:
4427 imm = (uint8_t) shift;
4428 imm |= imm << 8;
4429 imm |= imm << 16;
4430 break;
4431 case 1:
4432 imm = (uint16_t) shift;
4433 imm |= imm << 16;
4434 break;
4435 case 2:
4436 case 3:
4437 imm = shift;
4438 break;
4439 default:
4440 abort();
4443 for (pass = 0; pass < count; pass++) {
4444 if (size == 3) {
4445 neon_load_reg64(cpu_V0, rm + pass);
4446 tcg_gen_movi_i64(cpu_V1, imm);
4447 switch (op) {
4448 case 0: /* VSHR */
4449 case 1: /* VSRA */
4450 if (u)
4451 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4452 else
4453 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4454 break;
4455 case 2: /* VRSHR */
4456 case 3: /* VRSRA */
4457 if (u)
4458 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4459 else
4460 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4461 break;
4462 case 4: /* VSRI */
4463 if (!u)
4464 return 1;
4465 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4466 break;
4467 case 5: /* VSHL, VSLI */
4468 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4469 break;
4470 case 6: /* VQSHL */
4471 if (u)
4472 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4473 else
4474 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4475 break;
4476 case 7: /* VQSHLU */
4477 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4478 break;
4480 if (op == 1 || op == 3) {
4481 /* Accumulate. */
4482 neon_load_reg64(cpu_V0, rd + pass);
4483 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4484 } else if (op == 4 || (op == 5 && u)) {
4485 /* Insert */
4486 cpu_abort(env, "VS[LR]I.64 not implemented");
4488 neon_store_reg64(cpu_V0, rd + pass);
4489 } else { /* size < 3 */
4490 /* Operands in T0 and T1. */
4491 tmp = neon_load_reg(rm, pass);
4492 tmp2 = new_tmp();
4493 tcg_gen_movi_i32(tmp2, imm);
4494 switch (op) {
4495 case 0: /* VSHR */
4496 case 1: /* VSRA */
4497 GEN_NEON_INTEGER_OP(shl);
4498 break;
4499 case 2: /* VRSHR */
4500 case 3: /* VRSRA */
4501 GEN_NEON_INTEGER_OP(rshl);
4502 break;
4503 case 4: /* VSRI */
4504 if (!u)
4505 return 1;
4506 GEN_NEON_INTEGER_OP(shl);
4507 break;
4508 case 5: /* VSHL, VSLI */
4509 switch (size) {
4510 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4511 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4512 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4513 default: return 1;
4515 break;
4516 case 6: /* VQSHL */
4517 GEN_NEON_INTEGER_OP_ENV(qshl);
4518 break;
4519 case 7: /* VQSHLU */
4520 switch (size) {
4521 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4522 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4523 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4524 default: return 1;
4526 break;
4528 dead_tmp(tmp2);
4530 if (op == 1 || op == 3) {
4531 /* Accumulate. */
4532 tmp2 = neon_load_reg(rd, pass);
4533 gen_neon_add(size, tmp2, tmp);
4534 dead_tmp(tmp2);
4535 } else if (op == 4 || (op == 5 && u)) {
4536 /* Insert */
4537 switch (size) {
4538 case 0:
4539 if (op == 4)
4540 imm = 0xff >> -shift;
4541 else
4542 imm = (uint8_t)(0xff << shift);
4543 imm |= imm << 8;
4544 imm |= imm << 16;
4545 break;
4546 case 1:
4547 if (op == 4)
4548 imm = 0xffff >> -shift;
4549 else
4550 imm = (uint16_t)(0xffff << shift);
4551 imm |= imm << 16;
4552 break;
4553 case 2:
4554 if (op == 4)
4555 imm = 0xffffffffu >> -shift;
4556 else
4557 imm = 0xffffffffu << shift;
4558 break;
4559 default:
4560 abort();
4562 tmp2 = neon_load_reg(rd, pass);
4563 tcg_gen_andi_i32(tmp, tmp, imm);
4564 tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4565 tcg_gen_or_i32(tmp, tmp, tmp2);
4566 dead_tmp(tmp2);
4568 neon_store_reg(rd, pass, tmp);
4570 } /* for pass */
4571 } else if (op < 10) {
4572 /* Shift by immediate and narrow:
4573 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4574 shift = shift - (1 << (size + 3));
4575 size++;
4576 switch (size) {
4577 case 1:
4578 imm = (uint16_t)shift;
4579 imm |= imm << 16;
4580 tmp2 = tcg_const_i32(imm);
4581 TCGV_UNUSED_I64(tmp64);
4582 break;
4583 case 2:
4584 imm = (uint32_t)shift;
4585 tmp2 = tcg_const_i32(imm);
4586 TCGV_UNUSED_I64(tmp64);
4587 break;
4588 case 3:
4589 tmp64 = tcg_const_i64(shift);
4590 TCGV_UNUSED(tmp2);
4591 break;
4592 default:
4593 abort();
4596 for (pass = 0; pass < 2; pass++) {
4597 if (size == 3) {
4598 neon_load_reg64(cpu_V0, rm + pass);
4599 if (q) {
4600 if (u)
4601 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4602 else
4603 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4604 } else {
4605 if (u)
4606 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4607 else
4608 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4610 } else {
4611 tmp = neon_load_reg(rm + pass, 0);
4612 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4613 tmp3 = neon_load_reg(rm + pass, 1);
4614 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4615 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4616 dead_tmp(tmp);
4617 dead_tmp(tmp3);
4619 tmp = new_tmp();
4620 if (op == 8 && !u) {
4621 gen_neon_narrow(size - 1, tmp, cpu_V0);
4622 } else {
4623 if (op == 8)
4624 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4625 else
4626 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4628 if (pass == 0) {
4629 tmp2 = tmp;
4630 } else {
4631 neon_store_reg(rd, 0, tmp2);
4632 neon_store_reg(rd, 1, tmp);
4634 } /* for pass */
4635 } else if (op == 10) {
4636 /* VSHLL */
4637 if (q || size == 3)
4638 return 1;
4639 tmp = neon_load_reg(rm, 0);
4640 tmp2 = neon_load_reg(rm, 1);
4641 for (pass = 0; pass < 2; pass++) {
4642 if (pass == 1)
4643 tmp = tmp2;
4645 gen_neon_widen(cpu_V0, tmp, size, u);
4647 if (shift != 0) {
4648 /* The shift is less than the width of the source
4649 type, so we can just shift the whole register. */
4650 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4651 if (size < 2 || !u) {
4652 uint64_t imm64;
4653 if (size == 0) {
4654 imm = (0xffu >> (8 - shift));
4655 imm |= imm << 16;
4656 } else {
4657 imm = 0xffff >> (16 - shift);
4659 imm64 = imm | (((uint64_t)imm) << 32);
4660 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4663 neon_store_reg64(cpu_V0, rd + pass);
4665 } else if (op == 15 || op == 16) {
4666 /* VCVT fixed-point. */
4667 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4668 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4669 if (op & 1) {
4670 if (u)
4671 gen_vfp_ulto(0, shift);
4672 else
4673 gen_vfp_slto(0, shift);
4674 } else {
4675 if (u)
4676 gen_vfp_toul(0, shift);
4677 else
4678 gen_vfp_tosl(0, shift);
4680 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4682 } else {
4683 return 1;
4685 } else { /* (insn & 0x00380080) == 0 */
4686 int invert;
4688 op = (insn >> 8) & 0xf;
4689 /* One register and immediate. */
4690 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4691 invert = (insn & (1 << 5)) != 0;
4692 switch (op) {
4693 case 0: case 1:
4694 /* no-op */
4695 break;
4696 case 2: case 3:
4697 imm <<= 8;
4698 break;
4699 case 4: case 5:
4700 imm <<= 16;
4701 break;
4702 case 6: case 7:
4703 imm <<= 24;
4704 break;
4705 case 8: case 9:
4706 imm |= imm << 16;
4707 break;
4708 case 10: case 11:
4709 imm = (imm << 8) | (imm << 24);
4710 break;
4711 case 12:
4712 imm = (imm < 8) | 0xff;
4713 break;
4714 case 13:
4715 imm = (imm << 16) | 0xffff;
4716 break;
4717 case 14:
4718 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4719 if (invert)
4720 imm = ~imm;
4721 break;
4722 case 15:
4723 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4724 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4725 break;
4727 if (invert)
4728 imm = ~imm;
4730 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4731 if (op & 1 && op < 12) {
4732 tmp = neon_load_reg(rd, pass);
4733 if (invert) {
4734 /* The immediate value has already been inverted, so
4735 BIC becomes AND. */
4736 tcg_gen_andi_i32(tmp, tmp, imm);
4737 } else {
4738 tcg_gen_ori_i32(tmp, tmp, imm);
4740 } else {
4741 /* VMOV, VMVN. */
4742 tmp = new_tmp();
4743 if (op == 14 && invert) {
4744 uint32_t val;
4745 val = 0;
4746 for (n = 0; n < 4; n++) {
4747 if (imm & (1 << (n + (pass & 1) * 4)))
4748 val |= 0xff << (n * 8);
4750 tcg_gen_movi_i32(tmp, val);
4751 } else {
4752 tcg_gen_movi_i32(tmp, imm);
4755 neon_store_reg(rd, pass, tmp);
4758 } else { /* (insn & 0x00800010 == 0x00800000) */
4759 if (size != 3) {
4760 op = (insn >> 8) & 0xf;
4761 if ((insn & (1 << 6)) == 0) {
4762 /* Three registers of different lengths. */
4763 int src1_wide;
4764 int src2_wide;
4765 int prewiden;
4766 /* prewiden, src1_wide, src2_wide */
4767 static const int neon_3reg_wide[16][3] = {
4768 {1, 0, 0}, /* VADDL */
4769 {1, 1, 0}, /* VADDW */
4770 {1, 0, 0}, /* VSUBL */
4771 {1, 1, 0}, /* VSUBW */
4772 {0, 1, 1}, /* VADDHN */
4773 {0, 0, 0}, /* VABAL */
4774 {0, 1, 1}, /* VSUBHN */
4775 {0, 0, 0}, /* VABDL */
4776 {0, 0, 0}, /* VMLAL */
4777 {0, 0, 0}, /* VQDMLAL */
4778 {0, 0, 0}, /* VMLSL */
4779 {0, 0, 0}, /* VQDMLSL */
4780 {0, 0, 0}, /* Integer VMULL */
4781 {0, 0, 0}, /* VQDMULL */
4782 {0, 0, 0} /* Polynomial VMULL */
4785 prewiden = neon_3reg_wide[op][0];
4786 src1_wide = neon_3reg_wide[op][1];
4787 src2_wide = neon_3reg_wide[op][2];
4789 if (size == 0 && (op == 9 || op == 11 || op == 13))
4790 return 1;
4792 /* Avoid overlapping operands. Wide source operands are
4793 always aligned so will never overlap with wide
4794 destinations in problematic ways. */
4795 if (rd == rm && !src2_wide) {
4796 tmp = neon_load_reg(rm, 1);
4797 neon_store_scratch(2, tmp);
4798 } else if (rd == rn && !src1_wide) {
4799 tmp = neon_load_reg(rn, 1);
4800 neon_store_scratch(2, tmp);
4802 TCGV_UNUSED(tmp3);
4803 for (pass = 0; pass < 2; pass++) {
4804 if (src1_wide) {
4805 neon_load_reg64(cpu_V0, rn + pass);
4806 TCGV_UNUSED(tmp);
4807 } else {
4808 if (pass == 1 && rd == rn) {
4809 tmp = neon_load_scratch(2);
4810 } else {
4811 tmp = neon_load_reg(rn, pass);
4813 if (prewiden) {
4814 gen_neon_widen(cpu_V0, tmp, size, u);
4817 if (src2_wide) {
4818 neon_load_reg64(cpu_V1, rm + pass);
4819 TCGV_UNUSED(tmp2);
4820 } else {
4821 if (pass == 1 && rd == rm) {
4822 tmp2 = neon_load_scratch(2);
4823 } else {
4824 tmp2 = neon_load_reg(rm, pass);
4826 if (prewiden) {
4827 gen_neon_widen(cpu_V1, tmp2, size, u);
4830 switch (op) {
4831 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4832 gen_neon_addl(size);
4833 break;
4834 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4835 gen_neon_subl(size);
4836 break;
4837 case 5: case 7: /* VABAL, VABDL */
4838 switch ((size << 1) | u) {
4839 case 0:
4840 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4841 break;
4842 case 1:
4843 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4844 break;
4845 case 2:
4846 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4847 break;
4848 case 3:
4849 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4850 break;
4851 case 4:
4852 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4853 break;
4854 case 5:
4855 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4856 break;
4857 default: abort();
4859 dead_tmp(tmp2);
4860 dead_tmp(tmp);
4861 break;
4862 case 8: case 9: case 10: case 11: case 12: case 13:
4863 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4864 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4865 dead_tmp(tmp2);
4866 dead_tmp(tmp);
4867 break;
4868 case 14: /* Polynomial VMULL */
4869 cpu_abort(env, "Polynomial VMULL not implemented");
4871 default: /* 15 is RESERVED. */
4872 return 1;
4874 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4875 /* Accumulate. */
4876 if (op == 10 || op == 11) {
4877 gen_neon_negl(cpu_V0, size);
4880 if (op != 13) {
4881 neon_load_reg64(cpu_V1, rd + pass);
4884 switch (op) {
4885 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4886 gen_neon_addl(size);
4887 break;
4888 case 9: case 11: /* VQDMLAL, VQDMLSL */
4889 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4890 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4891 break;
4892 /* Fall through. */
4893 case 13: /* VQDMULL */
4894 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4895 break;
4896 default:
4897 abort();
4899 neon_store_reg64(cpu_V0, rd + pass);
4900 } else if (op == 4 || op == 6) {
4901 /* Narrowing operation. */
4902 tmp = new_tmp();
4903 if (u) {
4904 switch (size) {
4905 case 0:
4906 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4907 break;
4908 case 1:
4909 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4910 break;
4911 case 2:
4912 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4913 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4914 break;
4915 default: abort();
4917 } else {
4918 switch (size) {
4919 case 0:
4920 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4921 break;
4922 case 1:
4923 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4924 break;
4925 case 2:
4926 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4927 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4928 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4929 break;
4930 default: abort();
4933 if (pass == 0) {
4934 tmp3 = tmp;
4935 } else {
4936 neon_store_reg(rd, 0, tmp3);
4937 neon_store_reg(rd, 1, tmp);
4939 } else {
4940 /* Write back the result. */
4941 neon_store_reg64(cpu_V0, rd + pass);
4944 } else {
4945 /* Two registers and a scalar. */
4946 switch (op) {
4947 case 0: /* Integer VMLA scalar */
4948 case 1: /* Float VMLA scalar */
4949 case 4: /* Integer VMLS scalar */
4950 case 5: /* Floating point VMLS scalar */
4951 case 8: /* Integer VMUL scalar */
4952 case 9: /* Floating point VMUL scalar */
4953 case 12: /* VQDMULH scalar */
4954 case 13: /* VQRDMULH scalar */
4955 tmp = neon_get_scalar(size, rm);
4956 neon_store_scratch(0, tmp);
4957 for (pass = 0; pass < (u ? 4 : 2); pass++) {
4958 tmp = neon_load_scratch(0);
4959 tmp2 = neon_load_reg(rn, pass);
4960 if (op == 12) {
4961 if (size == 1) {
4962 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4963 } else {
4964 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4966 } else if (op == 13) {
4967 if (size == 1) {
4968 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4969 } else {
4970 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4972 } else if (op & 1) {
4973 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4974 } else {
4975 switch (size) {
4976 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4977 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4978 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4979 default: return 1;
4982 dead_tmp(tmp2);
4983 if (op < 8) {
4984 /* Accumulate. */
4985 tmp2 = neon_load_reg(rd, pass);
4986 switch (op) {
4987 case 0:
4988 gen_neon_add(size, tmp, tmp2);
4989 break;
4990 case 1:
4991 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4992 break;
4993 case 4:
4994 gen_neon_rsb(size, tmp, tmp2);
4995 break;
4996 case 5:
4997 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4998 break;
4999 default:
5000 abort();
5002 dead_tmp(tmp2);
5004 neon_store_reg(rd, pass, tmp);
5006 break;
5007 case 2: /* VMLAL sclar */
5008 case 3: /* VQDMLAL scalar */
5009 case 6: /* VMLSL scalar */
5010 case 7: /* VQDMLSL scalar */
5011 case 10: /* VMULL scalar */
5012 case 11: /* VQDMULL scalar */
5013 if (size == 0 && (op == 3 || op == 7 || op == 11))
5014 return 1;
5016 tmp2 = neon_get_scalar(size, rm);
5017 tmp3 = neon_load_reg(rn, 1);
5019 for (pass = 0; pass < 2; pass++) {
5020 if (pass == 0) {
5021 tmp = neon_load_reg(rn, 0);
5022 } else {
5023 tmp = tmp3;
5025 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5026 dead_tmp(tmp);
5027 if (op == 6 || op == 7) {
5028 gen_neon_negl(cpu_V0, size);
5030 if (op != 11) {
5031 neon_load_reg64(cpu_V1, rd + pass);
5033 switch (op) {
5034 case 2: case 6:
5035 gen_neon_addl(size);
5036 break;
5037 case 3: case 7:
5038 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5039 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5040 break;
5041 case 10:
5042 /* no-op */
5043 break;
5044 case 11:
5045 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5046 break;
5047 default:
5048 abort();
5050 neon_store_reg64(cpu_V0, rd + pass);
5053 dead_tmp(tmp2);
5055 break;
5056 default: /* 14 and 15 are RESERVED */
5057 return 1;
5060 } else { /* size == 3 */
5061 if (!u) {
5062 /* Extract. */
5063 imm = (insn >> 8) & 0xf;
5064 count = q + 1;
5066 if (imm > 7 && !q)
5067 return 1;
5069 if (imm == 0) {
5070 neon_load_reg64(cpu_V0, rn);
5071 if (q) {
5072 neon_load_reg64(cpu_V1, rn + 1);
5074 } else if (imm == 8) {
5075 neon_load_reg64(cpu_V0, rn + 1);
5076 if (q) {
5077 neon_load_reg64(cpu_V1, rm);
5079 } else if (q) {
5080 tmp64 = tcg_temp_new_i64();
5081 if (imm < 8) {
5082 neon_load_reg64(cpu_V0, rn);
5083 neon_load_reg64(tmp64, rn + 1);
5084 } else {
5085 neon_load_reg64(cpu_V0, rn + 1);
5086 neon_load_reg64(tmp64, rm);
5088 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5089 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5090 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5091 if (imm < 8) {
5092 neon_load_reg64(cpu_V1, rm);
5093 } else {
5094 neon_load_reg64(cpu_V1, rm + 1);
5095 imm -= 8;
5097 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5098 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5099 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5100 } else {
5101 /* BUGFIX */
5102 neon_load_reg64(cpu_V0, rn);
5103 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5104 neon_load_reg64(cpu_V1, rm);
5105 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5106 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5108 neon_store_reg64(cpu_V0, rd);
5109 if (q) {
5110 neon_store_reg64(cpu_V1, rd + 1);
5112 } else if ((insn & (1 << 11)) == 0) {
5113 /* Two register misc. */
5114 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5115 size = (insn >> 18) & 3;
5116 switch (op) {
5117 case 0: /* VREV64 */
5118 if (size == 3)
5119 return 1;
5120 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5121 tmp = neon_load_reg(rm, pass * 2);
5122 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5123 switch (size) {
5124 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5125 case 1: gen_swap_half(tmp); break;
5126 case 2: /* no-op */ break;
5127 default: abort();
5129 neon_store_reg(rd, pass * 2 + 1, tmp);
5130 if (size == 2) {
5131 neon_store_reg(rd, pass * 2, tmp2);
5132 } else {
5133 switch (size) {
5134 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5135 case 1: gen_swap_half(tmp2); break;
5136 default: abort();
5138 neon_store_reg(rd, pass * 2, tmp2);
5141 break;
5142 case 4: case 5: /* VPADDL */
5143 case 12: case 13: /* VPADAL */
5144 if (size == 3)
5145 return 1;
5146 for (pass = 0; pass < q + 1; pass++) {
5147 tmp = neon_load_reg(rm, pass * 2);
5148 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5149 tmp = neon_load_reg(rm, pass * 2 + 1);
5150 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5151 switch (size) {
5152 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5153 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5154 case 2: tcg_gen_add_i64(CPU_V001); break;
5155 default: abort();
5157 if (op >= 12) {
5158 /* Accumulate. */
5159 neon_load_reg64(cpu_V1, rd + pass);
5160 gen_neon_addl(size);
5162 neon_store_reg64(cpu_V0, rd + pass);
5164 break;
5165 case 33: /* VTRN */
5166 if (size == 2) {
5167 for (n = 0; n < (q ? 4 : 2); n += 2) {
5168 tmp = neon_load_reg(rm, n);
5169 tmp2 = neon_load_reg(rd, n + 1);
5170 neon_store_reg(rm, n, tmp2);
5171 neon_store_reg(rd, n + 1, tmp);
5173 } else {
5174 goto elementwise;
5176 break;
5177 case 34: /* VUZP */
5178 /* Reg Before After
5179 Rd A3 A2 A1 A0 B2 B0 A2 A0
5180 Rm B3 B2 B1 B0 B3 B1 A3 A1
5182 if (size == 3)
5183 return 1;
5184 gen_neon_unzip(rd, q, 0, size);
5185 gen_neon_unzip(rm, q, 4, size);
5186 if (q) {
5187 static int unzip_order_q[8] =
5188 {0, 2, 4, 6, 1, 3, 5, 7};
5189 for (n = 0; n < 8; n++) {
5190 int reg = (n < 4) ? rd : rm;
5191 tmp = neon_load_scratch(unzip_order_q[n]);
5192 neon_store_reg(reg, n % 4, tmp);
5194 } else {
5195 static int unzip_order[4] =
5196 {0, 4, 1, 5};
5197 for (n = 0; n < 4; n++) {
5198 int reg = (n < 2) ? rd : rm;
5199 tmp = neon_load_scratch(unzip_order[n]);
5200 neon_store_reg(reg, n % 2, tmp);
5203 break;
5204 case 35: /* VZIP */
5205 /* Reg Before After
5206 Rd A3 A2 A1 A0 B1 A1 B0 A0
5207 Rm B3 B2 B1 B0 B3 A3 B2 A2
5209 if (size == 3)
5210 return 1;
5211 count = (q ? 4 : 2);
5212 for (n = 0; n < count; n++) {
5213 tmp = neon_load_reg(rd, n);
5214 tmp2 = neon_load_reg(rd, n);
5215 switch (size) {
5216 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5217 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5218 case 2: /* no-op */; break;
5219 default: abort();
5221 neon_store_scratch(n * 2, tmp);
5222 neon_store_scratch(n * 2 + 1, tmp2);
5224 for (n = 0; n < count * 2; n++) {
5225 int reg = (n < count) ? rd : rm;
5226 tmp = neon_load_scratch(n);
5227 neon_store_reg(reg, n % count, tmp);
5229 break;
5230 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5231 if (size == 3)
5232 return 1;
5233 TCGV_UNUSED(tmp2);
5234 for (pass = 0; pass < 2; pass++) {
5235 neon_load_reg64(cpu_V0, rm + pass);
5236 tmp = new_tmp();
5237 if (op == 36 && q == 0) {
5238 gen_neon_narrow(size, tmp, cpu_V0);
5239 } else if (q) {
5240 gen_neon_narrow_satu(size, tmp, cpu_V0);
5241 } else {
5242 gen_neon_narrow_sats(size, tmp, cpu_V0);
5244 if (pass == 0) {
5245 tmp2 = tmp;
5246 } else {
5247 neon_store_reg(rd, 0, tmp2);
5248 neon_store_reg(rd, 1, tmp);
5251 break;
5252 case 38: /* VSHLL */
5253 if (q || size == 3)
5254 return 1;
5255 tmp = neon_load_reg(rm, 0);
5256 tmp2 = neon_load_reg(rm, 1);
5257 for (pass = 0; pass < 2; pass++) {
5258 if (pass == 1)
5259 tmp = tmp2;
5260 gen_neon_widen(cpu_V0, tmp, size, 1);
5261 neon_store_reg64(cpu_V0, rd + pass);
5263 break;
5264 default:
5265 elementwise:
5266 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5267 if (op == 30 || op == 31 || op >= 58) {
5268 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5269 neon_reg_offset(rm, pass));
5270 TCGV_UNUSED(tmp);
5271 } else {
5272 tmp = neon_load_reg(rm, pass);
5274 switch (op) {
5275 case 1: /* VREV32 */
5276 switch (size) {
5277 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5278 case 1: gen_swap_half(tmp); break;
5279 default: return 1;
5281 break;
5282 case 2: /* VREV16 */
5283 if (size != 0)
5284 return 1;
5285 gen_rev16(tmp);
5286 break;
5287 case 8: /* CLS */
5288 switch (size) {
5289 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5290 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5291 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5292 default: return 1;
5294 break;
5295 case 9: /* CLZ */
5296 switch (size) {
5297 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5298 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5299 case 2: gen_helper_clz(tmp, tmp); break;
5300 default: return 1;
5302 break;
5303 case 10: /* CNT */
5304 if (size != 0)
5305 return 1;
5306 gen_helper_neon_cnt_u8(tmp, tmp);
5307 break;
5308 case 11: /* VNOT */
5309 if (size != 0)
5310 return 1;
5311 tcg_gen_not_i32(tmp, tmp);
5312 break;
5313 case 14: /* VQABS */
5314 switch (size) {
5315 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5316 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5317 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5318 default: return 1;
5320 break;
5321 case 15: /* VQNEG */
5322 switch (size) {
5323 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5324 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5325 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5326 default: return 1;
5328 break;
5329 case 16: case 19: /* VCGT #0, VCLE #0 */
5330 tmp2 = tcg_const_i32(0);
5331 switch(size) {
5332 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5333 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5334 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5335 default: return 1;
5337 tcg_temp_free(tmp2);
5338 if (op == 19)
5339 tcg_gen_not_i32(tmp, tmp);
5340 break;
5341 case 17: case 20: /* VCGE #0, VCLT #0 */
5342 tmp2 = tcg_const_i32(0);
5343 switch(size) {
5344 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5345 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5346 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5347 default: return 1;
5349 tcg_temp_free(tmp2);
5350 if (op == 20)
5351 tcg_gen_not_i32(tmp, tmp);
5352 break;
5353 case 18: /* VCEQ #0 */
5354 tmp2 = tcg_const_i32(0);
5355 switch(size) {
5356 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5357 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5358 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5359 default: return 1;
5361 tcg_temp_free(tmp2);
5362 break;
5363 case 22: /* VABS */
5364 switch(size) {
5365 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5366 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5367 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5368 default: return 1;
5370 break;
5371 case 23: /* VNEG */
5372 if (size == 3)
5373 return 1;
5374 tmp2 = tcg_const_i32(0);
5375 gen_neon_rsb(size, tmp, tmp2);
5376 tcg_temp_free(tmp2);
5377 break;
5378 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5379 tmp2 = tcg_const_i32(0);
5380 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5381 tcg_temp_free(tmp2);
5382 if (op == 27)
5383 tcg_gen_not_i32(tmp, tmp);
5384 break;
5385 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5386 tmp2 = tcg_const_i32(0);
5387 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5388 tcg_temp_free(tmp2);
5389 if (op == 28)
5390 tcg_gen_not_i32(tmp, tmp);
5391 break;
5392 case 26: /* Float VCEQ #0 */
5393 tmp2 = tcg_const_i32(0);
5394 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5395 tcg_temp_free(tmp2);
5396 break;
5397 case 30: /* Float VABS */
5398 gen_vfp_abs(0);
5399 break;
5400 case 31: /* Float VNEG */
5401 gen_vfp_neg(0);
5402 break;
5403 case 32: /* VSWP */
5404 tmp2 = neon_load_reg(rd, pass);
5405 neon_store_reg(rm, pass, tmp2);
5406 break;
5407 case 33: /* VTRN */
5408 tmp2 = neon_load_reg(rd, pass);
5409 switch (size) {
5410 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5411 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5412 case 2: abort();
5413 default: return 1;
5415 neon_store_reg(rm, pass, tmp2);
5416 break;
5417 case 56: /* Integer VRECPE */
5418 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5419 break;
5420 case 57: /* Integer VRSQRTE */
5421 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5422 break;
5423 case 58: /* Float VRECPE */
5424 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5425 break;
5426 case 59: /* Float VRSQRTE */
5427 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5428 break;
5429 case 60: /* VCVT.F32.S32 */
5430 gen_vfp_tosiz(0);
5431 break;
5432 case 61: /* VCVT.F32.U32 */
5433 gen_vfp_touiz(0);
5434 break;
5435 case 62: /* VCVT.S32.F32 */
5436 gen_vfp_sito(0);
5437 break;
5438 case 63: /* VCVT.U32.F32 */
5439 gen_vfp_uito(0);
5440 break;
5441 default:
5442 /* Reserved: 21, 29, 39-56 */
5443 return 1;
5445 if (op == 30 || op == 31 || op >= 58) {
5446 tcg_gen_st_f32(cpu_F0s, cpu_env,
5447 neon_reg_offset(rd, pass));
5448 } else {
5449 neon_store_reg(rd, pass, tmp);
5452 break;
5454 } else if ((insn & (1 << 10)) == 0) {
5455 /* VTBL, VTBX. */
5456 n = ((insn >> 5) & 0x18) + 8;
5457 if (insn & (1 << 6)) {
5458 tmp = neon_load_reg(rd, 0);
5459 } else {
5460 tmp = new_tmp();
5461 tcg_gen_movi_i32(tmp, 0);
5463 tmp2 = neon_load_reg(rm, 0);
5464 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5465 tcg_const_i32(n));
5466 dead_tmp(tmp);
5467 if (insn & (1 << 6)) {
5468 tmp = neon_load_reg(rd, 1);
5469 } else {
5470 tmp = new_tmp();
5471 tcg_gen_movi_i32(tmp, 0);
5473 tmp3 = neon_load_reg(rm, 1);
5474 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5475 tcg_const_i32(n));
5476 neon_store_reg(rd, 0, tmp2);
5477 neon_store_reg(rd, 1, tmp3);
5478 dead_tmp(tmp);
5479 } else if ((insn & 0x380) == 0) {
5480 /* VDUP */
5481 if (insn & (1 << 19)) {
5482 tmp = neon_load_reg(rm, 1);
5483 } else {
5484 tmp = neon_load_reg(rm, 0);
5486 if (insn & (1 << 16)) {
5487 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5488 } else if (insn & (1 << 17)) {
5489 if ((insn >> 18) & 1)
5490 gen_neon_dup_high16(tmp);
5491 else
5492 gen_neon_dup_low16(tmp);
5494 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5495 tmp2 = new_tmp();
5496 tcg_gen_mov_i32(tmp2, tmp);
5497 neon_store_reg(rd, pass, tmp2);
5499 dead_tmp(tmp);
5500 } else {
5501 return 1;
5505 return 0;
5508 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5510 int crn = (insn >> 16) & 0xf;
5511 int crm = insn & 0xf;
5512 int op1 = (insn >> 21) & 7;
5513 int op2 = (insn >> 5) & 7;
5514 int rt = (insn >> 12) & 0xf;
5515 TCGv tmp;
5517 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5518 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5519 /* TEECR */
5520 if (IS_USER(s))
5521 return 1;
5522 tmp = load_cpu_field(teecr);
5523 store_reg(s, rt, tmp);
5524 return 0;
5526 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5527 /* TEEHBR */
5528 if (IS_USER(s) && (env->teecr & 1))
5529 return 1;
5530 tmp = load_cpu_field(teehbr);
5531 store_reg(s, rt, tmp);
5532 return 0;
5535 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5536 op1, crn, crm, op2);
5537 return 1;
5540 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5542 int crn = (insn >> 16) & 0xf;
5543 int crm = insn & 0xf;
5544 int op1 = (insn >> 21) & 7;
5545 int op2 = (insn >> 5) & 7;
5546 int rt = (insn >> 12) & 0xf;
5547 TCGv tmp;
5549 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5550 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5551 /* TEECR */
5552 if (IS_USER(s))
5553 return 1;
5554 tmp = load_reg(s, rt);
5555 gen_helper_set_teecr(cpu_env, tmp);
5556 dead_tmp(tmp);
5557 return 0;
5559 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5560 /* TEEHBR */
5561 if (IS_USER(s) && (env->teecr & 1))
5562 return 1;
5563 tmp = load_reg(s, rt);
5564 store_cpu_field(tmp, teehbr);
5565 return 0;
5568 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5569 op1, crn, crm, op2);
5570 return 1;
5573 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5575 int cpnum;
5577 cpnum = (insn >> 8) & 0xf;
5578 if (arm_feature(env, ARM_FEATURE_XSCALE)
5579 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5580 return 1;
5582 switch (cpnum) {
5583 case 0:
5584 case 1:
5585 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5586 return disas_iwmmxt_insn(env, s, insn);
5587 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5588 return disas_dsp_insn(env, s, insn);
5590 return 1;
5591 case 10:
5592 case 11:
5593 return disas_vfp_insn (env, s, insn);
5594 case 14:
5595 /* Coprocessors 7-15 are architecturally reserved by ARM.
5596 Unfortunately Intel decided to ignore this. */
5597 if (arm_feature(env, ARM_FEATURE_XSCALE))
5598 goto board;
5599 if (insn & (1 << 20))
5600 return disas_cp14_read(env, s, insn);
5601 else
5602 return disas_cp14_write(env, s, insn);
5603 case 15:
5604 return disas_cp15_insn (env, s, insn);
5605 default:
5606 board:
5607 /* Unknown coprocessor. See if the board has hooked it. */
5608 return disas_cp_insn (env, s, insn);
5613 /* Store a 64-bit value to a register pair. Clobbers val. */
5614 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5616 TCGv tmp;
5617 tmp = new_tmp();
5618 tcg_gen_trunc_i64_i32(tmp, val);
5619 store_reg(s, rlow, tmp);
5620 tmp = new_tmp();
5621 tcg_gen_shri_i64(val, val, 32);
5622 tcg_gen_trunc_i64_i32(tmp, val);
5623 store_reg(s, rhigh, tmp);
5626 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5627 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5629 TCGv_i64 tmp;
5630 TCGv tmp2;
5632 /* Load value and extend to 64 bits. */
5633 tmp = tcg_temp_new_i64();
5634 tmp2 = load_reg(s, rlow);
5635 tcg_gen_extu_i32_i64(tmp, tmp2);
5636 dead_tmp(tmp2);
5637 tcg_gen_add_i64(val, val, tmp);
5640 /* load and add a 64-bit value from a register pair. */
5641 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5643 TCGv_i64 tmp;
5644 TCGv tmpl;
5645 TCGv tmph;
5647 /* Load 64-bit value rd:rn. */
5648 tmpl = load_reg(s, rlow);
5649 tmph = load_reg(s, rhigh);
5650 tmp = tcg_temp_new_i64();
5651 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5652 dead_tmp(tmpl);
5653 dead_tmp(tmph);
5654 tcg_gen_add_i64(val, val, tmp);
5657 /* Set N and Z flags from a 64-bit value. */
5658 static void gen_logicq_cc(TCGv_i64 val)
5660 TCGv tmp = new_tmp();
5661 gen_helper_logicq_cc(tmp, val);
5662 gen_logic_CC(tmp);
5663 dead_tmp(tmp);
5666 static void disas_arm_insn(CPUState * env, DisasContext *s)
5668 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5669 TCGv tmp;
5670 TCGv tmp2;
5671 TCGv tmp3;
5672 TCGv addr;
5673 TCGv_i64 tmp64;
5675 insn = ldl_code(s->pc);
5676 s->pc += 4;
5678 /* M variants do not implement ARM mode. */
5679 if (IS_M(env))
5680 goto illegal_op;
5681 cond = insn >> 28;
5682 if (cond == 0xf){
5683 /* Unconditional instructions. */
5684 if (((insn >> 25) & 7) == 1) {
5685 /* NEON Data processing. */
5686 if (!arm_feature(env, ARM_FEATURE_NEON))
5687 goto illegal_op;
5689 if (disas_neon_data_insn(env, s, insn))
5690 goto illegal_op;
5691 return;
5693 if ((insn & 0x0f100000) == 0x04000000) {
5694 /* NEON load/store. */
5695 if (!arm_feature(env, ARM_FEATURE_NEON))
5696 goto illegal_op;
5698 if (disas_neon_ls_insn(env, s, insn))
5699 goto illegal_op;
5700 return;
5702 if ((insn & 0x0d70f000) == 0x0550f000) {
5703 ARCH(5);
5704 return; /* PLD */
5705 } else if ((insn & 0x0ffffdff) == 0x01010000) {
5706 ARCH(6);
5707 /* setend */
5708 if (insn & (1 << 9)) {
5709 /* BE8 mode not implemented. */
5710 goto illegal_op;
5712 return;
5713 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5714 switch ((insn >> 4) & 0xf) {
5715 case 1: /* clrex */
5716 ARCH(6K);
5717 gen_helper_clrex(cpu_env);
5718 return;
5719 case 4: /* dsb */
5720 case 5: /* dmb */
5721 case 6: /* isb */
5722 ARCH(7);
5723 /* We don't emulate caches so these are a no-op. */
5724 return;
5725 default:
5726 goto illegal_op;
5728 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5729 /* srs */
5730 int32_t offset;
5731 if (IS_USER(s))
5732 goto illegal_op;
5733 ARCH(6);
5734 op1 = (insn & 0x1f);
5735 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5736 addr = load_reg(s, 13);
5737 } else {
5738 addr = new_tmp();
5739 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5741 i = (insn >> 23) & 3;
5742 switch (i) {
5743 case 0: offset = -4; break; /* DA */
5744 case 1: offset = 0; break; /* IA */
5745 case 2: offset = -8; break; /* DB */
5746 case 3: offset = 4; break; /* IB */
5747 default: abort();
5749 if (offset)
5750 tcg_gen_addi_i32(addr, addr, offset);
5751 tmp = load_reg(s, 14);
5752 gen_st32(tmp, addr, 0);
5753 tmp = load_cpu_field(spsr);
5754 tcg_gen_addi_i32(addr, addr, 4);
5755 gen_st32(tmp, addr, 0);
5756 if (insn & (1 << 21)) {
5757 /* Base writeback. */
5758 switch (i) {
5759 case 0: offset = -8; break;
5760 case 1: offset = 4; break;
5761 case 2: offset = -4; break;
5762 case 3: offset = 0; break;
5763 default: abort();
5765 if (offset)
5766 tcg_gen_addi_i32(addr, addr, offset);
5767 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5768 store_reg(s, 13, addr);
5769 } else {
5770 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5771 dead_tmp(addr);
5773 } else {
5774 dead_tmp(addr);
5776 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5777 /* rfe */
5778 int32_t offset;
5779 if (IS_USER(s))
5780 goto illegal_op;
5781 ARCH(6);
5782 rn = (insn >> 16) & 0xf;
5783 addr = load_reg(s, rn);
5784 i = (insn >> 23) & 3;
5785 switch (i) {
5786 case 0: offset = -4; break; /* DA */
5787 case 1: offset = 0; break; /* IA */
5788 case 2: offset = -8; break; /* DB */
5789 case 3: offset = 4; break; /* IB */
5790 default: abort();
5792 if (offset)
5793 tcg_gen_addi_i32(addr, addr, offset);
5794 /* Load PC into tmp and CPSR into tmp2. */
5795 tmp = gen_ld32(addr, 0);
5796 tcg_gen_addi_i32(addr, addr, 4);
5797 tmp2 = gen_ld32(addr, 0);
5798 if (insn & (1 << 21)) {
5799 /* Base writeback. */
5800 switch (i) {
5801 case 0: offset = -8; break;
5802 case 1: offset = 4; break;
5803 case 2: offset = -4; break;
5804 case 3: offset = 0; break;
5805 default: abort();
5807 if (offset)
5808 tcg_gen_addi_i32(addr, addr, offset);
5809 store_reg(s, rn, addr);
5810 } else {
5811 dead_tmp(addr);
5813 gen_rfe(s, tmp, tmp2);
5814 return;
5815 } else if ((insn & 0x0e000000) == 0x0a000000) {
5816 /* branch link and change to thumb (blx <offset>) */
5817 int32_t offset;
5818 ARCH(5);
5819 val = (uint32_t)s->pc;
5820 tmp = new_tmp();
5821 tcg_gen_movi_i32(tmp, val);
5822 store_reg(s, 14, tmp);
5823 /* Sign-extend the 24-bit offset */
5824 offset = (((int32_t)insn) << 8) >> 8;
5825 /* offset * 4 + bit24 * 2 + (thumb bit) */
5826 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5827 /* pipeline offset */
5828 val += 4;
5829 gen_bx_im(s, val);
5830 return;
5831 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5832 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5833 /* iWMMXt register transfer. */
5834 if (env->cp15.c15_cpar & (1 << 1))
5835 if (!disas_iwmmxt_insn(env, s, insn))
5836 return;
5838 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5839 /* Coprocessor double register transfer. */
5840 ARCH(5);
5841 } else if ((insn & 0x0f000010) == 0x0e000010) {
5842 /* Additional coprocessor register transfer. */
5843 ARCH(5);
5844 } else if ((insn & 0x0ff10020) == 0x01000000) {
5845 uint32_t mask;
5846 uint32_t val;
5847 /* cps (privileged) */
5848 if (IS_USER(s))
5849 return;
5850 mask = val = 0;
5851 if (insn & (1 << 19)) {
5852 if (insn & (1 << 8))
5853 mask |= CPSR_A;
5854 if (insn & (1 << 7))
5855 mask |= CPSR_I;
5856 if (insn & (1 << 6))
5857 mask |= CPSR_F;
5858 if (insn & (1 << 18))
5859 val |= mask;
5861 if (insn & (1 << 17)) {
5862 mask |= CPSR_M;
5863 val |= (insn & 0x1f);
5865 if (mask) {
5866 gen_set_psr_im(s, mask, 0, val);
5868 return;
5870 goto illegal_op;
5872 if (cond != 0xe) {
5873 /* if not always execute, we generate a conditional jump to
5874 next instruction */
5875 s->condlabel = gen_new_label();
5876 gen_test_cc(cond ^ 1, s->condlabel);
5877 s->condjmp = 1;
5879 if ((insn & 0x0f900000) == 0x03000000) {
5880 if ((insn & (1 << 21)) == 0) {
5881 ARCH(6T2);
5882 rd = (insn >> 12) & 0xf;
5883 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5884 if ((insn & (1 << 22)) == 0) {
5885 /* MOVW */
5886 tmp = new_tmp();
5887 tcg_gen_movi_i32(tmp, val);
5888 } else {
5889 /* MOVT */
5890 tmp = load_reg(s, rd);
5891 tcg_gen_ext16u_i32(tmp, tmp);
5892 tcg_gen_ori_i32(tmp, tmp, val << 16);
5894 store_reg(s, rd, tmp);
5895 } else {
5896 if (((insn >> 12) & 0xf) != 0xf)
5897 goto illegal_op;
5898 if (((insn >> 16) & 0xf) == 0) {
5899 gen_nop_hint(s, insn & 0xff);
5900 } else {
5901 /* CPSR = immediate */
5902 val = insn & 0xff;
5903 shift = ((insn >> 8) & 0xf) * 2;
5904 if (shift)
5905 val = (val >> shift) | (val << (32 - shift));
5906 i = ((insn & (1 << 22)) != 0);
5907 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
5908 goto illegal_op;
5911 } else if ((insn & 0x0f900000) == 0x01000000
5912 && (insn & 0x00000090) != 0x00000090) {
5913 /* miscellaneous instructions */
5914 op1 = (insn >> 21) & 3;
5915 sh = (insn >> 4) & 0xf;
5916 rm = insn & 0xf;
5917 switch (sh) {
5918 case 0x0: /* move program status register */
5919 if (op1 & 1) {
5920 /* PSR = reg */
5921 tmp = load_reg(s, rm);
5922 i = ((op1 & 2) != 0);
5923 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
5924 goto illegal_op;
5925 } else {
5926 /* reg = PSR */
5927 rd = (insn >> 12) & 0xf;
5928 if (op1 & 2) {
5929 if (IS_USER(s))
5930 goto illegal_op;
5931 tmp = load_cpu_field(spsr);
5932 } else {
5933 tmp = new_tmp();
5934 gen_helper_cpsr_read(tmp);
5936 store_reg(s, rd, tmp);
5938 break;
5939 case 0x1:
5940 if (op1 == 1) {
5941 /* branch/exchange thumb (bx). */
5942 tmp = load_reg(s, rm);
5943 gen_bx(s, tmp);
5944 } else if (op1 == 3) {
5945 /* clz */
5946 rd = (insn >> 12) & 0xf;
5947 tmp = load_reg(s, rm);
5948 gen_helper_clz(tmp, tmp);
5949 store_reg(s, rd, tmp);
5950 } else {
5951 goto illegal_op;
5953 break;
5954 case 0x2:
5955 if (op1 == 1) {
5956 ARCH(5J); /* bxj */
5957 /* Trivial implementation equivalent to bx. */
5958 tmp = load_reg(s, rm);
5959 gen_bx(s, tmp);
5960 } else {
5961 goto illegal_op;
5963 break;
5964 case 0x3:
5965 if (op1 != 1)
5966 goto illegal_op;
5967 ARCH(5);
5968 /* branch link/exchange thumb (blx) */
5969 tmp = load_reg(s, rm);
5970 tmp2 = new_tmp();
5971 tcg_gen_movi_i32(tmp2, s->pc);
5972 store_reg(s, 14, tmp2);
5973 gen_bx(s, tmp);
5974 break;
5975 case 0x5: /* saturating add/subtract */
5976 rd = (insn >> 12) & 0xf;
5977 rn = (insn >> 16) & 0xf;
5978 tmp = load_reg(s, rm);
5979 tmp2 = load_reg(s, rn);
5980 if (op1 & 2)
5981 gen_helper_double_saturate(tmp2, tmp2);
5982 if (op1 & 1)
5983 gen_helper_sub_saturate(tmp, tmp, tmp2);
5984 else
5985 gen_helper_add_saturate(tmp, tmp, tmp2);
5986 dead_tmp(tmp2);
5987 store_reg(s, rd, tmp);
5988 break;
5989 case 7: /* bkpt */
5990 ARCH(5);
5991 gen_set_condexec(s);
5992 gen_set_pc_im(s->pc - 4);
5993 gen_exception(EXCP_BKPT);
5994 s->is_jmp = DISAS_JUMP;
5995 break;
5996 case 0x8: /* signed multiply */
5997 case 0xa:
5998 case 0xc:
5999 case 0xe:
6000 rs = (insn >> 8) & 0xf;
6001 rn = (insn >> 12) & 0xf;
6002 rd = (insn >> 16) & 0xf;
6003 if (op1 == 1) {
6004 /* (32 * 16) >> 16 */
6005 tmp = load_reg(s, rm);
6006 tmp2 = load_reg(s, rs);
6007 if (sh & 4)
6008 tcg_gen_sari_i32(tmp2, tmp2, 16);
6009 else
6010 gen_sxth(tmp2);
6011 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6012 tcg_gen_shri_i64(tmp64, tmp64, 16);
6013 tmp = new_tmp();
6014 tcg_gen_trunc_i64_i32(tmp, tmp64);
6015 if ((sh & 2) == 0) {
6016 tmp2 = load_reg(s, rn);
6017 gen_helper_add_setq(tmp, tmp, tmp2);
6018 dead_tmp(tmp2);
6020 store_reg(s, rd, tmp);
6021 } else {
6022 /* 16 * 16 */
6023 tmp = load_reg(s, rm);
6024 tmp2 = load_reg(s, rs);
6025 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6026 dead_tmp(tmp2);
6027 if (op1 == 2) {
6028 tmp64 = tcg_temp_new_i64();
6029 tcg_gen_ext_i32_i64(tmp64, tmp);
6030 dead_tmp(tmp);
6031 gen_addq(s, tmp64, rn, rd);
6032 gen_storeq_reg(s, rn, rd, tmp64);
6033 } else {
6034 if (op1 == 0) {
6035 tmp2 = load_reg(s, rn);
6036 gen_helper_add_setq(tmp, tmp, tmp2);
6037 dead_tmp(tmp2);
6039 store_reg(s, rd, tmp);
6042 break;
6043 default:
6044 goto illegal_op;
6046 } else if (((insn & 0x0e000000) == 0 &&
6047 (insn & 0x00000090) != 0x90) ||
6048 ((insn & 0x0e000000) == (1 << 25))) {
6049 int set_cc, logic_cc, shiftop;
6051 op1 = (insn >> 21) & 0xf;
6052 set_cc = (insn >> 20) & 1;
6053 logic_cc = table_logic_cc[op1] & set_cc;
6055 /* data processing instruction */
6056 if (insn & (1 << 25)) {
6057 /* immediate operand */
6058 val = insn & 0xff;
6059 shift = ((insn >> 8) & 0xf) * 2;
6060 if (shift) {
6061 val = (val >> shift) | (val << (32 - shift));
6063 tmp2 = new_tmp();
6064 tcg_gen_movi_i32(tmp2, val);
6065 if (logic_cc && shift) {
6066 gen_set_CF_bit31(tmp2);
6068 } else {
6069 /* register */
6070 rm = (insn) & 0xf;
6071 tmp2 = load_reg(s, rm);
6072 shiftop = (insn >> 5) & 3;
6073 if (!(insn & (1 << 4))) {
6074 shift = (insn >> 7) & 0x1f;
6075 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6076 } else {
6077 rs = (insn >> 8) & 0xf;
6078 tmp = load_reg(s, rs);
6079 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6082 if (op1 != 0x0f && op1 != 0x0d) {
6083 rn = (insn >> 16) & 0xf;
6084 tmp = load_reg(s, rn);
6085 } else {
6086 TCGV_UNUSED(tmp);
6088 rd = (insn >> 12) & 0xf;
6089 switch(op1) {
6090 case 0x00:
6091 tcg_gen_and_i32(tmp, tmp, tmp2);
6092 if (logic_cc) {
6093 gen_logic_CC(tmp);
6095 store_reg_bx(env, s, rd, tmp);
6096 break;
6097 case 0x01:
6098 tcg_gen_xor_i32(tmp, tmp, tmp2);
6099 if (logic_cc) {
6100 gen_logic_CC(tmp);
6102 store_reg_bx(env, s, rd, tmp);
6103 break;
6104 case 0x02:
6105 if (set_cc && rd == 15) {
6106 /* SUBS r15, ... is used for exception return. */
6107 if (IS_USER(s)) {
6108 goto illegal_op;
6110 gen_helper_sub_cc(tmp, tmp, tmp2);
6111 gen_exception_return(s, tmp);
6112 } else {
6113 if (set_cc) {
6114 gen_helper_sub_cc(tmp, tmp, tmp2);
6115 } else {
6116 tcg_gen_sub_i32(tmp, tmp, tmp2);
6118 store_reg_bx(env, s, rd, tmp);
6120 break;
6121 case 0x03:
6122 if (set_cc) {
6123 gen_helper_sub_cc(tmp, tmp2, tmp);
6124 } else {
6125 tcg_gen_sub_i32(tmp, tmp2, tmp);
6127 store_reg_bx(env, s, rd, tmp);
6128 break;
6129 case 0x04:
6130 if (set_cc) {
6131 gen_helper_add_cc(tmp, tmp, tmp2);
6132 } else {
6133 tcg_gen_add_i32(tmp, tmp, tmp2);
6135 store_reg_bx(env, s, rd, tmp);
6136 break;
6137 case 0x05:
6138 if (set_cc) {
6139 gen_helper_adc_cc(tmp, tmp, tmp2);
6140 } else {
6141 gen_add_carry(tmp, tmp, tmp2);
6143 store_reg_bx(env, s, rd, tmp);
6144 break;
6145 case 0x06:
6146 if (set_cc) {
6147 gen_helper_sbc_cc(tmp, tmp, tmp2);
6148 } else {
6149 gen_sub_carry(tmp, tmp, tmp2);
6151 store_reg_bx(env, s, rd, tmp);
6152 break;
6153 case 0x07:
6154 if (set_cc) {
6155 gen_helper_sbc_cc(tmp, tmp2, tmp);
6156 } else {
6157 gen_sub_carry(tmp, tmp2, tmp);
6159 store_reg_bx(env, s, rd, tmp);
6160 break;
6161 case 0x08:
6162 if (set_cc) {
6163 tcg_gen_and_i32(tmp, tmp, tmp2);
6164 gen_logic_CC(tmp);
6166 dead_tmp(tmp);
6167 break;
6168 case 0x09:
6169 if (set_cc) {
6170 tcg_gen_xor_i32(tmp, tmp, tmp2);
6171 gen_logic_CC(tmp);
6173 dead_tmp(tmp);
6174 break;
6175 case 0x0a:
6176 if (set_cc) {
6177 gen_helper_sub_cc(tmp, tmp, tmp2);
6179 dead_tmp(tmp);
6180 break;
6181 case 0x0b:
6182 if (set_cc) {
6183 gen_helper_add_cc(tmp, tmp, tmp2);
6185 dead_tmp(tmp);
6186 break;
6187 case 0x0c:
6188 tcg_gen_or_i32(tmp, tmp, tmp2);
6189 if (logic_cc) {
6190 gen_logic_CC(tmp);
6192 store_reg_bx(env, s, rd, tmp);
6193 break;
6194 case 0x0d:
6195 if (logic_cc && rd == 15) {
6196 /* MOVS r15, ... is used for exception return. */
6197 if (IS_USER(s)) {
6198 goto illegal_op;
6200 gen_exception_return(s, tmp2);
6201 } else {
6202 if (logic_cc) {
6203 gen_logic_CC(tmp2);
6205 store_reg_bx(env, s, rd, tmp2);
6207 break;
6208 case 0x0e:
6209 tcg_gen_bic_i32(tmp, tmp, tmp2);
6210 if (logic_cc) {
6211 gen_logic_CC(tmp);
6213 store_reg_bx(env, s, rd, tmp);
6214 break;
6215 default:
6216 case 0x0f:
6217 tcg_gen_not_i32(tmp2, tmp2);
6218 if (logic_cc) {
6219 gen_logic_CC(tmp2);
6221 store_reg_bx(env, s, rd, tmp2);
6222 break;
6224 if (op1 != 0x0f && op1 != 0x0d) {
6225 dead_tmp(tmp2);
6227 } else {
6228 /* other instructions */
6229 op1 = (insn >> 24) & 0xf;
6230 switch(op1) {
6231 case 0x0:
6232 case 0x1:
6233 /* multiplies, extra load/stores */
6234 sh = (insn >> 5) & 3;
6235 if (sh == 0) {
6236 if (op1 == 0x0) {
6237 rd = (insn >> 16) & 0xf;
6238 rn = (insn >> 12) & 0xf;
6239 rs = (insn >> 8) & 0xf;
6240 rm = (insn) & 0xf;
6241 op1 = (insn >> 20) & 0xf;
6242 switch (op1) {
6243 case 0: case 1: case 2: case 3: case 6:
6244 /* 32 bit mul */
6245 tmp = load_reg(s, rs);
6246 tmp2 = load_reg(s, rm);
6247 tcg_gen_mul_i32(tmp, tmp, tmp2);
6248 dead_tmp(tmp2);
6249 if (insn & (1 << 22)) {
6250 /* Subtract (mls) */
6251 ARCH(6T2);
6252 tmp2 = load_reg(s, rn);
6253 tcg_gen_sub_i32(tmp, tmp2, tmp);
6254 dead_tmp(tmp2);
6255 } else if (insn & (1 << 21)) {
6256 /* Add */
6257 tmp2 = load_reg(s, rn);
6258 tcg_gen_add_i32(tmp, tmp, tmp2);
6259 dead_tmp(tmp2);
6261 if (insn & (1 << 20))
6262 gen_logic_CC(tmp);
6263 store_reg(s, rd, tmp);
6264 break;
6265 default:
6266 /* 64 bit mul */
6267 tmp = load_reg(s, rs);
6268 tmp2 = load_reg(s, rm);
6269 if (insn & (1 << 22))
6270 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6271 else
6272 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6273 if (insn & (1 << 21)) /* mult accumulate */
6274 gen_addq(s, tmp64, rn, rd);
6275 if (!(insn & (1 << 23))) { /* double accumulate */
6276 ARCH(6);
6277 gen_addq_lo(s, tmp64, rn);
6278 gen_addq_lo(s, tmp64, rd);
6280 if (insn & (1 << 20))
6281 gen_logicq_cc(tmp64);
6282 gen_storeq_reg(s, rn, rd, tmp64);
6283 break;
6285 } else {
6286 rn = (insn >> 16) & 0xf;
6287 rd = (insn >> 12) & 0xf;
6288 if (insn & (1 << 23)) {
6289 /* load/store exclusive */
6290 op1 = (insn >> 21) & 0x3;
6291 if (op1)
6292 ARCH(6K);
6293 else
6294 ARCH(6);
6295 addr = tcg_temp_local_new_i32();
6296 tcg_gen_mov_i32(addr, cpu_R[rn]);
6297 if (insn & (1 << 20)) {
6298 gen_helper_mark_exclusive(cpu_env, addr);
6299 switch (op1) {
6300 case 0: /* ldrex */
6301 tmp = gen_ld32(addr, IS_USER(s));
6302 break;
6303 case 1: /* ldrexd */
6304 tmp = gen_ld32(addr, IS_USER(s));
6305 store_reg(s, rd, tmp);
6306 tcg_gen_addi_i32(addr, addr, 4);
6307 tmp = gen_ld32(addr, IS_USER(s));
6308 rd++;
6309 break;
6310 case 2: /* ldrexb */
6311 tmp = gen_ld8u(addr, IS_USER(s));
6312 break;
6313 case 3: /* ldrexh */
6314 tmp = gen_ld16u(addr, IS_USER(s));
6315 break;
6316 default:
6317 abort();
6319 store_reg(s, rd, tmp);
6320 } else {
6321 int label = gen_new_label();
6322 rm = insn & 0xf;
6323 tmp2 = tcg_temp_local_new_i32();
6324 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6325 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6326 tmp = load_reg(s,rm);
6327 switch (op1) {
6328 case 0: /* strex */
6329 gen_st32(tmp, addr, IS_USER(s));
6330 break;
6331 case 1: /* strexd */
6332 gen_st32(tmp, addr, IS_USER(s));
6333 tcg_gen_addi_i32(addr, addr, 4);
6334 tmp = load_reg(s, rm + 1);
6335 gen_st32(tmp, addr, IS_USER(s));
6336 break;
6337 case 2: /* strexb */
6338 gen_st8(tmp, addr, IS_USER(s));
6339 break;
6340 case 3: /* strexh */
6341 gen_st16(tmp, addr, IS_USER(s));
6342 break;
6343 default:
6344 abort();
6346 gen_set_label(label);
6347 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6348 tcg_temp_free(tmp2);
6350 tcg_temp_free(addr);
6351 } else {
6352 /* SWP instruction */
6353 rm = (insn) & 0xf;
6355 /* ??? This is not really atomic. However we know
6356 we never have multiple CPUs running in parallel,
6357 so it is good enough. */
6358 addr = load_reg(s, rn);
6359 tmp = load_reg(s, rm);
6360 if (insn & (1 << 22)) {
6361 tmp2 = gen_ld8u(addr, IS_USER(s));
6362 gen_st8(tmp, addr, IS_USER(s));
6363 } else {
6364 tmp2 = gen_ld32(addr, IS_USER(s));
6365 gen_st32(tmp, addr, IS_USER(s));
6367 dead_tmp(addr);
6368 store_reg(s, rd, tmp2);
6371 } else {
6372 int address_offset;
6373 int load;
6374 /* Misc load/store */
6375 rn = (insn >> 16) & 0xf;
6376 rd = (insn >> 12) & 0xf;
6377 addr = load_reg(s, rn);
6378 if (insn & (1 << 24))
6379 gen_add_datah_offset(s, insn, 0, addr);
6380 address_offset = 0;
6381 if (insn & (1 << 20)) {
6382 /* load */
6383 switch(sh) {
6384 case 1:
6385 tmp = gen_ld16u(addr, IS_USER(s));
6386 break;
6387 case 2:
6388 tmp = gen_ld8s(addr, IS_USER(s));
6389 break;
6390 default:
6391 case 3:
6392 tmp = gen_ld16s(addr, IS_USER(s));
6393 break;
6395 load = 1;
6396 } else if (sh & 2) {
6397 /* doubleword */
6398 if (sh & 1) {
6399 /* store */
6400 tmp = load_reg(s, rd);
6401 gen_st32(tmp, addr, IS_USER(s));
6402 tcg_gen_addi_i32(addr, addr, 4);
6403 tmp = load_reg(s, rd + 1);
6404 gen_st32(tmp, addr, IS_USER(s));
6405 load = 0;
6406 } else {
6407 /* load */
6408 tmp = gen_ld32(addr, IS_USER(s));
6409 store_reg(s, rd, tmp);
6410 tcg_gen_addi_i32(addr, addr, 4);
6411 tmp = gen_ld32(addr, IS_USER(s));
6412 rd++;
6413 load = 1;
6415 address_offset = -4;
6416 } else {
6417 /* store */
6418 tmp = load_reg(s, rd);
6419 gen_st16(tmp, addr, IS_USER(s));
6420 load = 0;
6422 /* Perform base writeback before the loaded value to
6423 ensure correct behavior with overlapping index registers.
6424 ldrd with base writeback is is undefined if the
6425 destination and index registers overlap. */
6426 if (!(insn & (1 << 24))) {
6427 gen_add_datah_offset(s, insn, address_offset, addr);
6428 store_reg(s, rn, addr);
6429 } else if (insn & (1 << 21)) {
6430 if (address_offset)
6431 tcg_gen_addi_i32(addr, addr, address_offset);
6432 store_reg(s, rn, addr);
6433 } else {
6434 dead_tmp(addr);
6436 if (load) {
6437 /* Complete the load. */
6438 store_reg(s, rd, tmp);
6441 break;
6442 case 0x4:
6443 case 0x5:
6444 goto do_ldst;
6445 case 0x6:
6446 case 0x7:
6447 if (insn & (1 << 4)) {
6448 ARCH(6);
6449 /* Armv6 Media instructions. */
6450 rm = insn & 0xf;
6451 rn = (insn >> 16) & 0xf;
6452 rd = (insn >> 12) & 0xf;
6453 rs = (insn >> 8) & 0xf;
6454 switch ((insn >> 23) & 3) {
6455 case 0: /* Parallel add/subtract. */
6456 op1 = (insn >> 20) & 7;
6457 tmp = load_reg(s, rn);
6458 tmp2 = load_reg(s, rm);
6459 sh = (insn >> 5) & 7;
6460 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6461 goto illegal_op;
6462 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6463 dead_tmp(tmp2);
6464 store_reg(s, rd, tmp);
6465 break;
6466 case 1:
6467 if ((insn & 0x00700020) == 0) {
6468 /* Halfword pack. */
6469 tmp = load_reg(s, rn);
6470 tmp2 = load_reg(s, rm);
6471 shift = (insn >> 7) & 0x1f;
6472 if (insn & (1 << 6)) {
6473 /* pkhtb */
6474 if (shift == 0)
6475 shift = 31;
6476 tcg_gen_sari_i32(tmp2, tmp2, shift);
6477 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6478 tcg_gen_ext16u_i32(tmp2, tmp2);
6479 } else {
6480 /* pkhbt */
6481 if (shift)
6482 tcg_gen_shli_i32(tmp2, tmp2, shift);
6483 tcg_gen_ext16u_i32(tmp, tmp);
6484 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6486 tcg_gen_or_i32(tmp, tmp, tmp2);
6487 dead_tmp(tmp2);
6488 store_reg(s, rd, tmp);
6489 } else if ((insn & 0x00200020) == 0x00200000) {
6490 /* [us]sat */
6491 tmp = load_reg(s, rm);
6492 shift = (insn >> 7) & 0x1f;
6493 if (insn & (1 << 6)) {
6494 if (shift == 0)
6495 shift = 31;
6496 tcg_gen_sari_i32(tmp, tmp, shift);
6497 } else {
6498 tcg_gen_shli_i32(tmp, tmp, shift);
6500 sh = (insn >> 16) & 0x1f;
6501 if (sh != 0) {
6502 if (insn & (1 << 22))
6503 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6504 else
6505 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6507 store_reg(s, rd, tmp);
6508 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6509 /* [us]sat16 */
6510 tmp = load_reg(s, rm);
6511 sh = (insn >> 16) & 0x1f;
6512 if (sh != 0) {
6513 if (insn & (1 << 22))
6514 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6515 else
6516 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6518 store_reg(s, rd, tmp);
6519 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6520 /* Select bytes. */
6521 tmp = load_reg(s, rn);
6522 tmp2 = load_reg(s, rm);
6523 tmp3 = new_tmp();
6524 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6525 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6526 dead_tmp(tmp3);
6527 dead_tmp(tmp2);
6528 store_reg(s, rd, tmp);
6529 } else if ((insn & 0x000003e0) == 0x00000060) {
6530 tmp = load_reg(s, rm);
6531 shift = (insn >> 10) & 3;
6532 /* ??? In many cases it's not neccessary to do a
6533 rotate, a shift is sufficient. */
6534 if (shift != 0)
6535 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6536 op1 = (insn >> 20) & 7;
6537 switch (op1) {
6538 case 0: gen_sxtb16(tmp); break;
6539 case 2: gen_sxtb(tmp); break;
6540 case 3: gen_sxth(tmp); break;
6541 case 4: gen_uxtb16(tmp); break;
6542 case 6: gen_uxtb(tmp); break;
6543 case 7: gen_uxth(tmp); break;
6544 default: goto illegal_op;
6546 if (rn != 15) {
6547 tmp2 = load_reg(s, rn);
6548 if ((op1 & 3) == 0) {
6549 gen_add16(tmp, tmp2);
6550 } else {
6551 tcg_gen_add_i32(tmp, tmp, tmp2);
6552 dead_tmp(tmp2);
6555 store_reg(s, rd, tmp);
6556 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6557 /* rev */
6558 tmp = load_reg(s, rm);
6559 if (insn & (1 << 22)) {
6560 if (insn & (1 << 7)) {
6561 gen_revsh(tmp);
6562 } else {
6563 ARCH(6T2);
6564 gen_helper_rbit(tmp, tmp);
6566 } else {
6567 if (insn & (1 << 7))
6568 gen_rev16(tmp);
6569 else
6570 tcg_gen_bswap32_i32(tmp, tmp);
6572 store_reg(s, rd, tmp);
6573 } else {
6574 goto illegal_op;
6576 break;
6577 case 2: /* Multiplies (Type 3). */
6578 tmp = load_reg(s, rm);
6579 tmp2 = load_reg(s, rs);
6580 if (insn & (1 << 20)) {
6581 /* Signed multiply most significant [accumulate]. */
6582 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6583 if (insn & (1 << 5))
6584 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6585 tcg_gen_shri_i64(tmp64, tmp64, 32);
6586 tmp = new_tmp();
6587 tcg_gen_trunc_i64_i32(tmp, tmp64);
6588 if (rd != 15) {
6589 tmp2 = load_reg(s, rd);
6590 if (insn & (1 << 6)) {
6591 tcg_gen_sub_i32(tmp, tmp, tmp2);
6592 } else {
6593 tcg_gen_add_i32(tmp, tmp, tmp2);
6595 dead_tmp(tmp2);
6597 store_reg(s, rn, tmp);
6598 } else {
6599 if (insn & (1 << 5))
6600 gen_swap_half(tmp2);
6601 gen_smul_dual(tmp, tmp2);
6602 /* This addition cannot overflow. */
6603 if (insn & (1 << 6)) {
6604 tcg_gen_sub_i32(tmp, tmp, tmp2);
6605 } else {
6606 tcg_gen_add_i32(tmp, tmp, tmp2);
6608 dead_tmp(tmp2);
6609 if (insn & (1 << 22)) {
6610 /* smlald, smlsld */
6611 tmp64 = tcg_temp_new_i64();
6612 tcg_gen_ext_i32_i64(tmp64, tmp);
6613 dead_tmp(tmp);
6614 gen_addq(s, tmp64, rd, rn);
6615 gen_storeq_reg(s, rd, rn, tmp64);
6616 } else {
6617 /* smuad, smusd, smlad, smlsd */
6618 if (rd != 15)
6620 tmp2 = load_reg(s, rd);
6621 gen_helper_add_setq(tmp, tmp, tmp2);
6622 dead_tmp(tmp2);
6624 store_reg(s, rn, tmp);
6627 break;
6628 case 3:
6629 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6630 switch (op1) {
6631 case 0: /* Unsigned sum of absolute differences. */
6632 ARCH(6);
6633 tmp = load_reg(s, rm);
6634 tmp2 = load_reg(s, rs);
6635 gen_helper_usad8(tmp, tmp, tmp2);
6636 dead_tmp(tmp2);
6637 if (rd != 15) {
6638 tmp2 = load_reg(s, rd);
6639 tcg_gen_add_i32(tmp, tmp, tmp2);
6640 dead_tmp(tmp2);
6642 store_reg(s, rn, tmp);
6643 break;
6644 case 0x20: case 0x24: case 0x28: case 0x2c:
6645 /* Bitfield insert/clear. */
6646 ARCH(6T2);
6647 shift = (insn >> 7) & 0x1f;
6648 i = (insn >> 16) & 0x1f;
6649 i = i + 1 - shift;
6650 if (rm == 15) {
6651 tmp = new_tmp();
6652 tcg_gen_movi_i32(tmp, 0);
6653 } else {
6654 tmp = load_reg(s, rm);
6656 if (i != 32) {
6657 tmp2 = load_reg(s, rd);
6658 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6659 dead_tmp(tmp2);
6661 store_reg(s, rd, tmp);
6662 break;
6663 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6664 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6665 ARCH(6T2);
6666 tmp = load_reg(s, rm);
6667 shift = (insn >> 7) & 0x1f;
6668 i = ((insn >> 16) & 0x1f) + 1;
6669 if (shift + i > 32)
6670 goto illegal_op;
6671 if (i < 32) {
6672 if (op1 & 0x20) {
6673 gen_ubfx(tmp, shift, (1u << i) - 1);
6674 } else {
6675 gen_sbfx(tmp, shift, i);
6678 store_reg(s, rd, tmp);
6679 break;
6680 default:
6681 goto illegal_op;
6683 break;
6685 break;
6687 do_ldst:
6688 /* Check for undefined extension instructions
6689 * per the ARM Bible IE:
6690 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6692 sh = (0xf << 20) | (0xf << 4);
6693 if (op1 == 0x7 && ((insn & sh) == sh))
6695 goto illegal_op;
6697 /* load/store byte/word */
6698 rn = (insn >> 16) & 0xf;
6699 rd = (insn >> 12) & 0xf;
6700 tmp2 = load_reg(s, rn);
6701 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6702 if (insn & (1 << 24))
6703 gen_add_data_offset(s, insn, tmp2);
6704 if (insn & (1 << 20)) {
6705 /* load */
6706 if (insn & (1 << 22)) {
6707 tmp = gen_ld8u(tmp2, i);
6708 } else {
6709 tmp = gen_ld32(tmp2, i);
6711 } else {
6712 /* store */
6713 tmp = load_reg(s, rd);
6714 if (insn & (1 << 22))
6715 gen_st8(tmp, tmp2, i);
6716 else
6717 gen_st32(tmp, tmp2, i);
6719 if (!(insn & (1 << 24))) {
6720 gen_add_data_offset(s, insn, tmp2);
6721 store_reg(s, rn, tmp2);
6722 } else if (insn & (1 << 21)) {
6723 store_reg(s, rn, tmp2);
6724 } else {
6725 dead_tmp(tmp2);
6727 if (insn & (1 << 20)) {
6728 /* Complete the load. */
6729 if (rd == 15 && ENABLE_ARCH_5)
6730 gen_bx(s, tmp);
6731 else
6732 store_reg(s, rd, tmp);
6734 break;
6735 case 0x08:
6736 case 0x09:
6738 int j, n, user, loaded_base;
6739 int crement = 0;
6740 TCGv loaded_var;
6741 /* load/store multiple words */
6742 /* XXX: store correct base if write back */
6743 user = 0;
6744 if (insn & (1 << 22)) {
6745 if (IS_USER(s))
6746 goto illegal_op; /* only usable in supervisor mode */
6748 if ((insn & (1 << 15)) == 0)
6749 user = 1;
6751 rn = (insn >> 16) & 0xf;
6752 addr = load_reg(s, rn);
6754 /* compute total size */
6755 loaded_base = 0;
6756 TCGV_UNUSED(loaded_var);
6757 n = 0;
6758 for(i=0;i<16;i++) {
6759 if (insn & (1 << i))
6760 n++;
6762 /* XXX: test invalid n == 0 case ? */
6763 if (insn & (1 << 23)) {
6764 if (insn & (1 << 24)) {
6765 /* pre increment */
6766 tcg_gen_addi_i32(addr, addr, 4);
6767 } else {
6768 /* post increment */
6770 } else {
6771 if (insn & (1 << 24)) {
6772 /* pre decrement */
6773 tcg_gen_addi_i32(addr, addr, -(n * 4));
6774 } else {
6775 /* post decrement */
6776 if (n != 1)
6777 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6781 if (insn & (1 << 21)) {
6782 /* write back */
6783 if (insn & (1 << 23)) {
6784 if (insn & (1 << 24)) {
6785 /* pre increment */
6786 } else {
6787 /* post increment */
6788 crement = 4;
6790 } else {
6791 if (insn & (1 << 24)) {
6792 /* pre decrement */
6793 if (n != 1) {
6794 crement = -((n - 1) * 4);
6796 } else {
6797 /* post decrement */
6798 crement = -(n * 4);
6801 if (arm_feature(env, ARM_FEATURE_ABORT_BU)) {
6802 /* base-updated abort model: update base register
6803 before an abort can happen */
6804 crement += (n - 1) * 4;
6805 tmp = new_tmp();
6806 tcg_gen_addi_i32(tmp, addr, crement);
6807 store_reg(s, rn, tmp);
6812 j = 0;
6813 for(i=0;i<16;i++) {
6814 if (insn & (1 << i)) {
6815 if (insn & (1 << 20)) {
6816 /* load */
6817 tmp = gen_ld32(addr, IS_USER(s));
6818 if (i == 15) {
6819 if (ENABLE_ARCH_5) {
6820 gen_bx(s, tmp);
6821 } else {
6822 store_reg(s, i, tmp);
6824 } else if (user) {
6825 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6826 dead_tmp(tmp);
6827 } else if (i == rn) {
6828 loaded_var = tmp;
6829 loaded_base = 1;
6830 } else {
6831 store_reg(s, i, tmp);
6833 } else {
6834 /* store */
6835 if (i == 15) {
6836 /* special case: r15 = PC + 8 */
6837 val = (long)s->pc + 4;
6838 tmp = new_tmp();
6839 tcg_gen_movi_i32(tmp, val);
6840 } else if (user) {
6841 tmp = new_tmp();
6842 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6843 } else {
6844 tmp = load_reg(s, i);
6846 gen_st32(tmp, addr, IS_USER(s));
6848 j++;
6849 /* no need to add after the last transfer */
6850 if (j != n)
6851 tcg_gen_addi_i32(addr, addr, 4);
6854 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << 21))) {
6855 tcg_gen_addi_i32(addr, addr, crement);
6856 store_reg(s, rn, addr);
6857 } else {
6858 dead_tmp(addr);
6860 if (loaded_base) {
6861 store_reg(s, rn, loaded_var);
6863 if ((insn & (1 << 22)) && !user) {
6864 /* Restore CPSR from SPSR. */
6865 tmp = load_cpu_field(spsr);
6866 gen_set_cpsr(tmp, 0xffffffff);
6867 dead_tmp(tmp);
6868 s->is_jmp = DISAS_UPDATE;
6871 break;
6872 case 0xa:
6873 case 0xb:
6875 int32_t offset;
6877 /* branch (and link) */
6878 val = (int32_t)s->pc;
6879 if (insn & (1 << 24)) {
6880 tmp = new_tmp();
6881 tcg_gen_movi_i32(tmp, val);
6882 store_reg(s, 14, tmp);
6884 offset = (((int32_t)insn << 8) >> 8);
6885 val += (offset << 2) + 4;
6886 gen_jmp(s, val);
6888 break;
6889 case 0xc:
6890 case 0xd:
6891 case 0xe:
6892 /* Coprocessor. */
6893 if (disas_coproc_insn(env, s, insn))
6894 goto illegal_op;
6895 break;
6896 case 0xf:
6897 /* swi */
6898 gen_set_pc_im(s->pc);
6899 s->is_jmp = DISAS_SWI;
6900 break;
6901 default:
6902 illegal_op:
6903 gen_set_condexec(s);
6904 gen_set_pc_im(s->pc - 4);
6905 gen_exception(EXCP_UDEF);
6906 s->is_jmp = DISAS_JUMP;
6907 break;
6912 /* Return true if this is a Thumb-2 logical op. */
6913 static int
6914 thumb2_logic_op(int op)
6916 return (op < 8);
6919 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6920 then set condition code flags based on the result of the operation.
6921 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6922 to the high bit of T1.
6923 Returns zero if the opcode is valid. */
6925 static int
6926 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
6928 int logic_cc;
6930 logic_cc = 0;
6931 switch (op) {
6932 case 0: /* and */
6933 tcg_gen_and_i32(t0, t0, t1);
6934 logic_cc = conds;
6935 break;
6936 case 1: /* bic */
6937 tcg_gen_bic_i32(t0, t0, t1);
6938 logic_cc = conds;
6939 break;
6940 case 2: /* orr */
6941 tcg_gen_or_i32(t0, t0, t1);
6942 logic_cc = conds;
6943 break;
6944 case 3: /* orn */
6945 tcg_gen_not_i32(t1, t1);
6946 tcg_gen_or_i32(t0, t0, t1);
6947 logic_cc = conds;
6948 break;
6949 case 4: /* eor */
6950 tcg_gen_xor_i32(t0, t0, t1);
6951 logic_cc = conds;
6952 break;
6953 case 8: /* add */
6954 if (conds)
6955 gen_helper_add_cc(t0, t0, t1);
6956 else
6957 tcg_gen_add_i32(t0, t0, t1);
6958 break;
6959 case 10: /* adc */
6960 if (conds)
6961 gen_helper_adc_cc(t0, t0, t1);
6962 else
6963 gen_add_carry(t0, t0, t1);
6964 break;
6965 case 11: /* sbc */
6966 if (conds)
6967 gen_helper_sbc_cc(t0, t0, t1);
6968 else
6969 gen_sub_carry(t0, t0, t1);
6970 break;
6971 case 13: /* sub */
6972 if (conds)
6973 gen_helper_sub_cc(t0, t0, t1);
6974 else
6975 tcg_gen_sub_i32(t0, t0, t1);
6976 break;
6977 case 14: /* rsb */
6978 if (conds)
6979 gen_helper_sub_cc(t0, t1, t0);
6980 else
6981 tcg_gen_sub_i32(t0, t1, t0);
6982 break;
6983 default: /* 5, 6, 7, 9, 12, 15. */
6984 return 1;
6986 if (logic_cc) {
6987 gen_logic_CC(t0);
6988 if (shifter_out)
6989 gen_set_CF_bit31(t1);
6991 return 0;
6994 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6995 is not legal. */
6996 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6998 uint32_t insn, imm, shift, offset;
6999 uint32_t rd, rn, rm, rs;
7000 TCGv tmp;
7001 TCGv tmp2;
7002 TCGv tmp3;
7003 TCGv addr;
7004 TCGv_i64 tmp64;
7005 int op;
7006 int shiftop;
7007 int conds;
7008 int logic_cc;
7010 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7011 || arm_feature (env, ARM_FEATURE_M))) {
7012 /* Thumb-1 cores may need to treat bl and blx as a pair of
7013 16-bit instructions to get correct prefetch abort behavior. */
7014 insn = insn_hw1;
7015 if ((insn & (1 << 12)) == 0) {
7016 ARCH(5);
7017 /* Second half of blx. */
7018 offset = ((insn & 0x7ff) << 1);
7019 tmp = load_reg(s, 14);
7020 tcg_gen_addi_i32(tmp, tmp, offset);
7021 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7023 tmp2 = new_tmp();
7024 tcg_gen_movi_i32(tmp2, s->pc | 1);
7025 store_reg(s, 14, tmp2);
7026 gen_bx(s, tmp);
7027 return 0;
7029 if (insn & (1 << 11)) {
7030 /* Second half of bl. */
7031 offset = ((insn & 0x7ff) << 1) | 1;
7032 tmp = load_reg(s, 14);
7033 tcg_gen_addi_i32(tmp, tmp, offset);
7035 tmp2 = new_tmp();
7036 tcg_gen_movi_i32(tmp2, s->pc | 1);
7037 store_reg(s, 14, tmp2);
7038 gen_bx(s, tmp);
7039 return 0;
7041 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7042 /* Instruction spans a page boundary. Implement it as two
7043 16-bit instructions in case the second half causes an
7044 prefetch abort. */
7045 offset = ((int32_t)insn << 21) >> 9;
7046 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7047 return 0;
7049 /* Fall through to 32-bit decode. */
7052 insn = lduw_code(s->pc);
7053 s->pc += 2;
7054 insn |= (uint32_t)insn_hw1 << 16;
7056 if ((insn & 0xf800e800) != 0xf000e800) {
7057 ARCH(6T2);
7060 rn = (insn >> 16) & 0xf;
7061 rs = (insn >> 12) & 0xf;
7062 rd = (insn >> 8) & 0xf;
7063 rm = insn & 0xf;
7064 switch ((insn >> 25) & 0xf) {
7065 case 0: case 1: case 2: case 3:
7066 /* 16-bit instructions. Should never happen. */
7067 abort();
7068 case 4:
7069 if (insn & (1 << 22)) {
7070 /* Other load/store, table branch. */
7071 if (insn & 0x01200000) {
7072 /* Load/store doubleword. */
7073 ARCH(5);
7074 if (rn == 15) {
7075 addr = new_tmp();
7076 tcg_gen_movi_i32(addr, s->pc & ~3);
7077 } else {
7078 addr = load_reg(s, rn);
7080 offset = (insn & 0xff) * 4;
7081 if ((insn & (1 << 23)) == 0)
7082 offset = -offset;
7083 if (insn & (1 << 24)) {
7084 tcg_gen_addi_i32(addr, addr, offset);
7085 offset = 0;
7087 if (insn & (1 << 20)) {
7088 /* ldrd */
7089 tmp = gen_ld32(addr, IS_USER(s));
7090 store_reg(s, rs, tmp);
7091 tcg_gen_addi_i32(addr, addr, 4);
7092 tmp = gen_ld32(addr, IS_USER(s));
7093 store_reg(s, rd, tmp);
7094 } else {
7095 /* strd */
7096 tmp = load_reg(s, rs);
7097 gen_st32(tmp, addr, IS_USER(s));
7098 tcg_gen_addi_i32(addr, addr, 4);
7099 tmp = load_reg(s, rd);
7100 gen_st32(tmp, addr, IS_USER(s));
7102 if (insn & (1 << 21)) {
7103 /* Base writeback. */
7104 if (rn == 15)
7105 goto illegal_op;
7106 tcg_gen_addi_i32(addr, addr, offset - 4);
7107 store_reg(s, rn, addr);
7108 } else {
7109 dead_tmp(addr);
7111 } else if ((insn & (1 << 23)) == 0) {
7112 /* Load/store exclusive word. */
7113 addr = tcg_temp_local_new();
7114 tcg_gen_mov_i32(addr, cpu_R[rn]);
7115 if (insn & (1 << 20)) {
7116 gen_helper_mark_exclusive(cpu_env, addr);
7117 tmp = gen_ld32(addr, IS_USER(s));
7118 store_reg(s, rd, tmp);
7119 } else {
7120 int label = gen_new_label();
7121 tmp2 = tcg_temp_local_new();
7122 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7123 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7124 tmp = load_reg(s, rs);
7125 gen_st32(tmp, addr, IS_USER(s));
7126 gen_set_label(label);
7127 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7128 tcg_temp_free(tmp2);
7130 tcg_temp_free(addr);
7131 } else if ((insn & (1 << 6)) == 0) {
7132 /* Table Branch. */
7133 if (rn == 15) {
7134 addr = new_tmp();
7135 tcg_gen_movi_i32(addr, s->pc);
7136 } else {
7137 addr = load_reg(s, rn);
7139 tmp = load_reg(s, rm);
7140 tcg_gen_add_i32(addr, addr, tmp);
7141 if (insn & (1 << 4)) {
7142 /* tbh */
7143 tcg_gen_add_i32(addr, addr, tmp);
7144 dead_tmp(tmp);
7145 tmp = gen_ld16u(addr, IS_USER(s));
7146 } else { /* tbb */
7147 dead_tmp(tmp);
7148 tmp = gen_ld8u(addr, IS_USER(s));
7150 dead_tmp(addr);
7151 tcg_gen_shli_i32(tmp, tmp, 1);
7152 tcg_gen_addi_i32(tmp, tmp, s->pc);
7153 store_reg(s, 15, tmp);
7154 } else {
7155 /* Load/store exclusive byte/halfword/doubleword. */
7156 /* ??? These are not really atomic. However we know
7157 we never have multiple CPUs running in parallel,
7158 so it is good enough. */
7159 op = (insn >> 4) & 0x3;
7160 addr = tcg_temp_local_new();
7161 tcg_gen_mov_i32(addr, cpu_R[rn]);
7162 if (insn & (1 << 20)) {
7163 gen_helper_mark_exclusive(cpu_env, addr);
7164 switch (op) {
7165 case 0:
7166 tmp = gen_ld8u(addr, IS_USER(s));
7167 break;
7168 case 1:
7169 tmp = gen_ld16u(addr, IS_USER(s));
7170 break;
7171 case 3:
7172 tmp = gen_ld32(addr, IS_USER(s));
7173 tcg_gen_addi_i32(addr, addr, 4);
7174 tmp2 = gen_ld32(addr, IS_USER(s));
7175 store_reg(s, rd, tmp2);
7176 break;
7177 default:
7178 goto illegal_op;
7180 store_reg(s, rs, tmp);
7181 } else {
7182 int label = gen_new_label();
7183 tmp2 = tcg_temp_local_new();
7184 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7185 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7186 tmp = load_reg(s, rs);
7187 switch (op) {
7188 case 0:
7189 gen_st8(tmp, addr, IS_USER(s));
7190 break;
7191 case 1:
7192 gen_st16(tmp, addr, IS_USER(s));
7193 break;
7194 case 3:
7195 gen_st32(tmp, addr, IS_USER(s));
7196 tcg_gen_addi_i32(addr, addr, 4);
7197 tmp = load_reg(s, rd);
7198 gen_st32(tmp, addr, IS_USER(s));
7199 break;
7200 default:
7201 goto illegal_op;
7203 gen_set_label(label);
7204 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7205 tcg_temp_free(tmp2);
7207 tcg_temp_free(addr);
7209 } else {
7210 /* Load/store multiple, RFE, SRS. */
7211 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7212 /* Not available in user mode. */
7213 if (IS_USER(s))
7214 goto illegal_op;
7215 if (insn & (1 << 20)) {
7216 /* rfe */
7217 addr = load_reg(s, rn);
7218 if ((insn & (1 << 24)) == 0)
7219 tcg_gen_addi_i32(addr, addr, -8);
7220 /* Load PC into tmp and CPSR into tmp2. */
7221 tmp = gen_ld32(addr, 0);
7222 tcg_gen_addi_i32(addr, addr, 4);
7223 tmp2 = gen_ld32(addr, 0);
7224 if (insn & (1 << 21)) {
7225 /* Base writeback. */
7226 if (insn & (1 << 24)) {
7227 tcg_gen_addi_i32(addr, addr, 4);
7228 } else {
7229 tcg_gen_addi_i32(addr, addr, -4);
7231 store_reg(s, rn, addr);
7232 } else {
7233 dead_tmp(addr);
7235 gen_rfe(s, tmp, tmp2);
7236 } else {
7237 /* srs */
7238 op = (insn & 0x1f);
7239 if (op == (env->uncached_cpsr & CPSR_M)) {
7240 addr = load_reg(s, 13);
7241 } else {
7242 addr = new_tmp();
7243 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7245 if ((insn & (1 << 24)) == 0) {
7246 tcg_gen_addi_i32(addr, addr, -8);
7248 tmp = load_reg(s, 14);
7249 gen_st32(tmp, addr, 0);
7250 tcg_gen_addi_i32(addr, addr, 4);
7251 tmp = new_tmp();
7252 gen_helper_cpsr_read(tmp);
7253 gen_st32(tmp, addr, 0);
7254 if (insn & (1 << 21)) {
7255 if ((insn & (1 << 24)) == 0) {
7256 tcg_gen_addi_i32(addr, addr, -4);
7257 } else {
7258 tcg_gen_addi_i32(addr, addr, 4);
7260 if (op == (env->uncached_cpsr & CPSR_M)) {
7261 store_reg(s, 13, addr);
7262 } else {
7263 gen_helper_set_r13_banked(cpu_env,
7264 tcg_const_i32(op), addr);
7266 } else {
7267 dead_tmp(addr);
7270 } else {
7271 int i;
7272 /* Load/store multiple. */
7273 addr = load_reg(s, rn);
7274 offset = 0;
7275 for (i = 0; i < 16; i++) {
7276 if (insn & (1 << i))
7277 offset += 4;
7279 if (insn & (1 << 24)) {
7280 tcg_gen_addi_i32(addr, addr, -offset);
7283 for (i = 0; i < 16; i++) {
7284 if ((insn & (1 << i)) == 0)
7285 continue;
7286 if (insn & (1 << 20)) {
7287 /* Load. */
7288 tmp = gen_ld32(addr, IS_USER(s));
7289 if (i == 15 && ENABLE_ARCH_5) {
7290 gen_bx(s, tmp);
7291 } else {
7292 store_reg(s, i, tmp);
7294 } else {
7295 /* Store. */
7296 tmp = load_reg(s, i);
7297 gen_st32(tmp, addr, IS_USER(s));
7299 tcg_gen_addi_i32(addr, addr, 4);
7301 if (insn & (1 << 21)) {
7302 /* Base register writeback. */
7303 if (insn & (1 << 24)) {
7304 tcg_gen_addi_i32(addr, addr, -offset);
7306 /* Fault if writeback register is in register list. */
7307 if (insn & (1 << rn))
7308 goto illegal_op;
7309 store_reg(s, rn, addr);
7310 } else {
7311 dead_tmp(addr);
7315 break;
7316 case 5: /* Data processing register constant shift. */
7317 if (rn == 15) {
7318 tmp = new_tmp();
7319 tcg_gen_movi_i32(tmp, 0);
7320 } else {
7321 tmp = load_reg(s, rn);
7323 tmp2 = load_reg(s, rm);
7324 op = (insn >> 21) & 0xf;
7325 shiftop = (insn >> 4) & 3;
7326 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7327 conds = (insn & (1 << 20)) != 0;
7328 logic_cc = (conds && thumb2_logic_op(op));
7329 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7330 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7331 goto illegal_op;
7332 dead_tmp(tmp2);
7333 if (rd != 15) {
7334 store_reg(s, rd, tmp);
7335 } else {
7336 dead_tmp(tmp);
7338 break;
7339 case 13: /* Misc data processing. */
7340 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7341 if (op < 4 && (insn & 0xf000) != 0xf000)
7342 goto illegal_op;
7343 switch (op) {
7344 case 0: /* Register controlled shift. */
7345 tmp = load_reg(s, rn);
7346 tmp2 = load_reg(s, rm);
7347 if ((insn & 0x70) != 0)
7348 goto illegal_op;
7349 op = (insn >> 21) & 3;
7350 logic_cc = (insn & (1 << 20)) != 0;
7351 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7352 if (logic_cc)
7353 gen_logic_CC(tmp);
7354 store_reg_bx(env, s, rd, tmp);
7355 break;
7356 case 1: /* Sign/zero extend. */
7357 tmp = load_reg(s, rm);
7358 shift = (insn >> 4) & 3;
7359 /* ??? In many cases it's not neccessary to do a
7360 rotate, a shift is sufficient. */
7361 if (shift != 0)
7362 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7363 op = (insn >> 20) & 7;
7364 switch (op) {
7365 case 0: gen_sxth(tmp); break;
7366 case 1: gen_uxth(tmp); break;
7367 case 2: gen_sxtb16(tmp); break;
7368 case 3: gen_uxtb16(tmp); break;
7369 case 4: gen_sxtb(tmp); break;
7370 case 5: gen_uxtb(tmp); break;
7371 default: goto illegal_op;
7373 if (rn != 15) {
7374 tmp2 = load_reg(s, rn);
7375 if ((op >> 1) == 1) {
7376 gen_add16(tmp, tmp2);
7377 } else {
7378 tcg_gen_add_i32(tmp, tmp, tmp2);
7379 dead_tmp(tmp2);
7382 store_reg(s, rd, tmp);
7383 break;
7384 case 2: /* SIMD add/subtract. */
7385 op = (insn >> 20) & 7;
7386 shift = (insn >> 4) & 7;
7387 if ((op & 3) == 3 || (shift & 3) == 3)
7388 goto illegal_op;
7389 tmp = load_reg(s, rn);
7390 tmp2 = load_reg(s, rm);
7391 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7392 dead_tmp(tmp2);
7393 store_reg(s, rd, tmp);
7394 break;
7395 case 3: /* Other data processing. */
7396 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7397 if (op < 4) {
7398 /* Saturating add/subtract. */
7399 tmp = load_reg(s, rn);
7400 tmp2 = load_reg(s, rm);
7401 if (op & 2)
7402 gen_helper_double_saturate(tmp, tmp);
7403 if (op & 1)
7404 gen_helper_sub_saturate(tmp, tmp2, tmp);
7405 else
7406 gen_helper_add_saturate(tmp, tmp, tmp2);
7407 dead_tmp(tmp2);
7408 } else {
7409 tmp = load_reg(s, rn);
7410 switch (op) {
7411 case 0x0a: /* rbit */
7412 gen_helper_rbit(tmp, tmp);
7413 break;
7414 case 0x08: /* rev */
7415 tcg_gen_bswap32_i32(tmp, tmp);
7416 break;
7417 case 0x09: /* rev16 */
7418 gen_rev16(tmp);
7419 break;
7420 case 0x0b: /* revsh */
7421 gen_revsh(tmp);
7422 break;
7423 case 0x10: /* sel */
7424 tmp2 = load_reg(s, rm);
7425 tmp3 = new_tmp();
7426 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7427 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7428 dead_tmp(tmp3);
7429 dead_tmp(tmp2);
7430 break;
7431 case 0x18: /* clz */
7432 gen_helper_clz(tmp, tmp);
7433 break;
7434 default:
7435 goto illegal_op;
7438 store_reg(s, rd, tmp);
7439 break;
7440 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7441 op = (insn >> 4) & 0xf;
7442 tmp = load_reg(s, rn);
7443 tmp2 = load_reg(s, rm);
7444 switch ((insn >> 20) & 7) {
7445 case 0: /* 32 x 32 -> 32 */
7446 tcg_gen_mul_i32(tmp, tmp, tmp2);
7447 dead_tmp(tmp2);
7448 if (rs != 15) {
7449 tmp2 = load_reg(s, rs);
7450 if (op)
7451 tcg_gen_sub_i32(tmp, tmp2, tmp);
7452 else
7453 tcg_gen_add_i32(tmp, tmp, tmp2);
7454 dead_tmp(tmp2);
7456 break;
7457 case 1: /* 16 x 16 -> 32 */
7458 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7459 dead_tmp(tmp2);
7460 if (rs != 15) {
7461 tmp2 = load_reg(s, rs);
7462 gen_helper_add_setq(tmp, tmp, tmp2);
7463 dead_tmp(tmp2);
7465 break;
7466 case 2: /* Dual multiply add. */
7467 case 4: /* Dual multiply subtract. */
7468 if (op)
7469 gen_swap_half(tmp2);
7470 gen_smul_dual(tmp, tmp2);
7471 /* This addition cannot overflow. */
7472 if (insn & (1 << 22)) {
7473 tcg_gen_sub_i32(tmp, tmp, tmp2);
7474 } else {
7475 tcg_gen_add_i32(tmp, tmp, tmp2);
7477 dead_tmp(tmp2);
7478 if (rs != 15)
7480 tmp2 = load_reg(s, rs);
7481 gen_helper_add_setq(tmp, tmp, tmp2);
7482 dead_tmp(tmp2);
7484 break;
7485 case 3: /* 32 * 16 -> 32msb */
7486 if (op)
7487 tcg_gen_sari_i32(tmp2, tmp2, 16);
7488 else
7489 gen_sxth(tmp2);
7490 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7491 tcg_gen_shri_i64(tmp64, tmp64, 16);
7492 tmp = new_tmp();
7493 tcg_gen_trunc_i64_i32(tmp, tmp64);
7494 if (rs != 15)
7496 tmp2 = load_reg(s, rs);
7497 gen_helper_add_setq(tmp, tmp, tmp2);
7498 dead_tmp(tmp2);
7500 break;
7501 case 5: case 6: /* 32 * 32 -> 32msb */
7502 gen_imull(tmp, tmp2);
7503 if (insn & (1 << 5)) {
7504 gen_roundqd(tmp, tmp2);
7505 dead_tmp(tmp2);
7506 } else {
7507 dead_tmp(tmp);
7508 tmp = tmp2;
7510 if (rs != 15) {
7511 tmp2 = load_reg(s, rs);
7512 if (insn & (1 << 21)) {
7513 tcg_gen_add_i32(tmp, tmp, tmp2);
7514 } else {
7515 tcg_gen_sub_i32(tmp, tmp2, tmp);
7517 dead_tmp(tmp2);
7519 break;
7520 case 7: /* Unsigned sum of absolute differences. */
7521 gen_helper_usad8(tmp, tmp, tmp2);
7522 dead_tmp(tmp2);
7523 if (rs != 15) {
7524 tmp2 = load_reg(s, rs);
7525 tcg_gen_add_i32(tmp, tmp, tmp2);
7526 dead_tmp(tmp2);
7528 break;
7530 store_reg(s, rd, tmp);
7531 break;
7532 case 6: case 7: /* 64-bit multiply, Divide. */
7533 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7534 tmp = load_reg(s, rn);
7535 tmp2 = load_reg(s, rm);
7536 if ((op & 0x50) == 0x10) {
7537 /* sdiv, udiv */
7538 if (!arm_feature(env, ARM_FEATURE_DIV))
7539 goto illegal_op;
7540 if (op & 0x20)
7541 gen_helper_udiv(tmp, tmp, tmp2);
7542 else
7543 gen_helper_sdiv(tmp, tmp, tmp2);
7544 dead_tmp(tmp2);
7545 store_reg(s, rd, tmp);
7546 } else if ((op & 0xe) == 0xc) {
7547 /* Dual multiply accumulate long. */
7548 if (op & 1)
7549 gen_swap_half(tmp2);
7550 gen_smul_dual(tmp, tmp2);
7551 if (op & 0x10) {
7552 tcg_gen_sub_i32(tmp, tmp, tmp2);
7553 } else {
7554 tcg_gen_add_i32(tmp, tmp, tmp2);
7556 dead_tmp(tmp2);
7557 /* BUGFIX */
7558 tmp64 = tcg_temp_new_i64();
7559 tcg_gen_ext_i32_i64(tmp64, tmp);
7560 dead_tmp(tmp);
7561 gen_addq(s, tmp64, rs, rd);
7562 gen_storeq_reg(s, rs, rd, tmp64);
7563 } else {
7564 if (op & 0x20) {
7565 /* Unsigned 64-bit multiply */
7566 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7567 } else {
7568 if (op & 8) {
7569 /* smlalxy */
7570 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7571 dead_tmp(tmp2);
7572 tmp64 = tcg_temp_new_i64();
7573 tcg_gen_ext_i32_i64(tmp64, tmp);
7574 dead_tmp(tmp);
7575 } else {
7576 /* Signed 64-bit multiply */
7577 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7580 if (op & 4) {
7581 /* umaal */
7582 gen_addq_lo(s, tmp64, rs);
7583 gen_addq_lo(s, tmp64, rd);
7584 } else if (op & 0x40) {
7585 /* 64-bit accumulate. */
7586 gen_addq(s, tmp64, rs, rd);
7588 gen_storeq_reg(s, rs, rd, tmp64);
7590 break;
7592 break;
7593 case 6: case 7: case 14: case 15:
7594 /* Coprocessor. */
7595 if (((insn >> 24) & 3) == 3) {
7596 /* Translate into the equivalent ARM encoding. */
7597 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7598 if (disas_neon_data_insn(env, s, insn))
7599 goto illegal_op;
7600 } else {
7601 if (insn & (1 << 28))
7602 goto illegal_op;
7603 if (disas_coproc_insn (env, s, insn))
7604 goto illegal_op;
7606 break;
7607 case 8: case 9: case 10: case 11:
7608 if (insn & (1 << 15)) {
7609 /* Branches, misc control. */
7610 if (insn & 0x5000) {
7611 /* Unconditional branch. */
7612 /* signextend(hw1[10:0]) -> offset[:12]. */
7613 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7614 /* hw1[10:0] -> offset[11:1]. */
7615 offset |= (insn & 0x7ff) << 1;
7616 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7617 offset[24:22] already have the same value because of the
7618 sign extension above. */
7619 offset ^= ((~insn) & (1 << 13)) << 10;
7620 offset ^= ((~insn) & (1 << 11)) << 11;
7622 if (insn & (1 << 14)) {
7623 /* Branch and link. */
7624 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7627 offset += s->pc;
7628 if (insn & (1 << 12)) {
7629 /* b/bl */
7630 gen_jmp(s, offset);
7631 } else {
7632 /* blx */
7633 ARCH(5);
7634 offset &= ~(uint32_t)2;
7635 gen_bx_im(s, offset);
7637 } else if (((insn >> 23) & 7) == 7) {
7638 /* Misc control */
7639 if (insn & (1 << 13))
7640 goto illegal_op;
7642 if (insn & (1 << 26)) {
7643 /* Secure monitor call (v6Z) */
7644 goto illegal_op; /* not implemented. */
7645 } else {
7646 op = (insn >> 20) & 7;
7647 switch (op) {
7648 case 0: /* msr cpsr. */
7649 if (IS_M(env)) {
7650 tmp = load_reg(s, rn);
7651 addr = tcg_const_i32(insn & 0xff);
7652 gen_helper_v7m_msr(cpu_env, addr, tmp);
7653 gen_lookup_tb(s);
7654 break;
7656 /* fall through */
7657 case 1: /* msr spsr. */
7658 if (IS_M(env))
7659 goto illegal_op;
7660 tmp = load_reg(s, rn);
7661 if (gen_set_psr(s,
7662 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7663 op == 1, tmp))
7664 goto illegal_op;
7665 break;
7666 case 2: /* cps, nop-hint. */
7667 if (((insn >> 8) & 7) == 0) {
7668 gen_nop_hint(s, insn & 0xff);
7670 /* Implemented as NOP in user mode. */
7671 if (IS_USER(s))
7672 break;
7673 offset = 0;
7674 imm = 0;
7675 if (insn & (1 << 10)) {
7676 if (insn & (1 << 7))
7677 offset |= CPSR_A;
7678 if (insn & (1 << 6))
7679 offset |= CPSR_I;
7680 if (insn & (1 << 5))
7681 offset |= CPSR_F;
7682 if (insn & (1 << 9))
7683 imm = CPSR_A | CPSR_I | CPSR_F;
7685 if (insn & (1 << 8)) {
7686 offset |= 0x1f;
7687 imm |= (insn & 0x1f);
7689 if (offset) {
7690 gen_set_psr_im(s, offset, 0, imm);
7692 break;
7693 case 3: /* Special control operations. */
7694 op = (insn >> 4) & 0xf;
7695 switch (op) {
7696 case 2: /* clrex */
7697 gen_helper_clrex(cpu_env);
7698 break;
7699 case 4: /* dsb */
7700 case 5: /* dmb */
7701 case 6: /* isb */
7702 /* These execute as NOPs. */
7703 ARCH(7);
7704 break;
7705 default:
7706 goto illegal_op;
7708 break;
7709 case 4: /* bxj */
7710 /* Trivial implementation equivalent to bx. */
7711 tmp = load_reg(s, rn);
7712 gen_bx(s, tmp);
7713 break;
7714 case 5: /* Exception return. */
7715 /* Unpredictable in user mode. */
7716 goto illegal_op;
7717 case 6: /* mrs cpsr. */
7718 tmp = new_tmp();
7719 if (IS_M(env)) {
7720 addr = tcg_const_i32(insn & 0xff);
7721 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7722 } else {
7723 gen_helper_cpsr_read(tmp);
7725 store_reg(s, rd, tmp);
7726 break;
7727 case 7: /* mrs spsr. */
7728 /* Not accessible in user mode. */
7729 if (IS_USER(s) || IS_M(env))
7730 goto illegal_op;
7731 tmp = load_cpu_field(spsr);
7732 store_reg(s, rd, tmp);
7733 break;
7736 } else {
7737 /* Conditional branch. */
7738 op = (insn >> 22) & 0xf;
7739 /* Generate a conditional jump to next instruction. */
7740 s->condlabel = gen_new_label();
7741 gen_test_cc(op ^ 1, s->condlabel);
7742 s->condjmp = 1;
7744 /* offset[11:1] = insn[10:0] */
7745 offset = (insn & 0x7ff) << 1;
7746 /* offset[17:12] = insn[21:16]. */
7747 offset |= (insn & 0x003f0000) >> 4;
7748 /* offset[31:20] = insn[26]. */
7749 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7750 /* offset[18] = insn[13]. */
7751 offset |= (insn & (1 << 13)) << 5;
7752 /* offset[19] = insn[11]. */
7753 offset |= (insn & (1 << 11)) << 8;
7755 /* jump to the offset */
7756 gen_jmp(s, s->pc + offset);
7758 } else {
7759 /* Data processing immediate. */
7760 if (insn & (1 << 25)) {
7761 if (insn & (1 << 24)) {
7762 if (insn & (1 << 20))
7763 goto illegal_op;
7764 /* Bitfield/Saturate. */
7765 op = (insn >> 21) & 7;
7766 imm = insn & 0x1f;
7767 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7768 if (rn == 15) {
7769 tmp = new_tmp();
7770 tcg_gen_movi_i32(tmp, 0);
7771 } else {
7772 tmp = load_reg(s, rn);
7774 switch (op) {
7775 case 2: /* Signed bitfield extract. */
7776 imm++;
7777 if (shift + imm > 32)
7778 goto illegal_op;
7779 if (imm < 32)
7780 gen_sbfx(tmp, shift, imm);
7781 break;
7782 case 6: /* Unsigned bitfield extract. */
7783 imm++;
7784 if (shift + imm > 32)
7785 goto illegal_op;
7786 if (imm < 32)
7787 gen_ubfx(tmp, shift, (1u << imm) - 1);
7788 break;
7789 case 3: /* Bitfield insert/clear. */
7790 if (imm < shift)
7791 goto illegal_op;
7792 imm = imm + 1 - shift;
7793 if (imm != 32) {
7794 tmp2 = load_reg(s, rd);
7795 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7796 dead_tmp(tmp2);
7798 break;
7799 case 7:
7800 goto illegal_op;
7801 default: /* Saturate. */
7802 if (shift) {
7803 if (op & 1)
7804 tcg_gen_sari_i32(tmp, tmp, shift);
7805 else
7806 tcg_gen_shli_i32(tmp, tmp, shift);
7808 tmp2 = tcg_const_i32(imm);
7809 if (op & 4) {
7810 /* Unsigned. */
7811 if ((op & 1) && shift == 0)
7812 gen_helper_usat16(tmp, tmp, tmp2);
7813 else
7814 gen_helper_usat(tmp, tmp, tmp2);
7815 } else {
7816 /* Signed. */
7817 if ((op & 1) && shift == 0)
7818 gen_helper_ssat16(tmp, tmp, tmp2);
7819 else
7820 gen_helper_ssat(tmp, tmp, tmp2);
7822 break;
7824 store_reg(s, rd, tmp);
7825 } else {
7826 imm = ((insn & 0x04000000) >> 15)
7827 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7828 if (insn & (1 << 22)) {
7829 /* 16-bit immediate. */
7830 imm |= (insn >> 4) & 0xf000;
7831 if (insn & (1 << 23)) {
7832 /* movt */
7833 tmp = load_reg(s, rd);
7834 tcg_gen_ext16u_i32(tmp, tmp);
7835 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7836 } else {
7837 /* movw */
7838 tmp = new_tmp();
7839 tcg_gen_movi_i32(tmp, imm);
7841 } else {
7842 /* Add/sub 12-bit immediate. */
7843 if (rn == 15) {
7844 offset = s->pc & ~(uint32_t)3;
7845 if (insn & (1 << 23))
7846 offset -= imm;
7847 else
7848 offset += imm;
7849 tmp = new_tmp();
7850 tcg_gen_movi_i32(tmp, offset);
7851 } else {
7852 tmp = load_reg(s, rn);
7853 if (insn & (1 << 23))
7854 tcg_gen_subi_i32(tmp, tmp, imm);
7855 else
7856 tcg_gen_addi_i32(tmp, tmp, imm);
7859 store_reg(s, rd, tmp);
7861 } else {
7862 int shifter_out = 0;
7863 /* modified 12-bit immediate. */
7864 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7865 imm = (insn & 0xff);
7866 switch (shift) {
7867 case 0: /* XY */
7868 /* Nothing to do. */
7869 break;
7870 case 1: /* 00XY00XY */
7871 imm |= imm << 16;
7872 break;
7873 case 2: /* XY00XY00 */
7874 imm |= imm << 16;
7875 imm <<= 8;
7876 break;
7877 case 3: /* XYXYXYXY */
7878 imm |= imm << 16;
7879 imm |= imm << 8;
7880 break;
7881 default: /* Rotated constant. */
7882 shift = (shift << 1) | (imm >> 7);
7883 imm |= 0x80;
7884 imm = imm << (32 - shift);
7885 shifter_out = 1;
7886 break;
7888 tmp2 = new_tmp();
7889 tcg_gen_movi_i32(tmp2, imm);
7890 rn = (insn >> 16) & 0xf;
7891 if (rn == 15) {
7892 tmp = new_tmp();
7893 tcg_gen_movi_i32(tmp, 0);
7894 } else {
7895 tmp = load_reg(s, rn);
7897 op = (insn >> 21) & 0xf;
7898 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7899 shifter_out, tmp, tmp2))
7900 goto illegal_op;
7901 dead_tmp(tmp2);
7902 rd = (insn >> 8) & 0xf;
7903 if (rd != 15) {
7904 store_reg(s, rd, tmp);
7905 } else {
7906 dead_tmp(tmp);
7910 break;
7911 case 12: /* Load/store single data item. */
7913 int postinc = 0;
7914 int writeback = 0;
7915 int user;
7916 if ((insn & 0x01100000) == 0x01000000) {
7917 if (disas_neon_ls_insn(env, s, insn))
7918 goto illegal_op;
7919 break;
7921 user = IS_USER(s);
7922 if (rn == 15) {
7923 addr = new_tmp();
7924 /* PC relative. */
7925 /* s->pc has already been incremented by 4. */
7926 imm = s->pc & 0xfffffffc;
7927 if (insn & (1 << 23))
7928 imm += insn & 0xfff;
7929 else
7930 imm -= insn & 0xfff;
7931 tcg_gen_movi_i32(addr, imm);
7932 } else {
7933 addr = load_reg(s, rn);
7934 if (insn & (1 << 23)) {
7935 /* Positive offset. */
7936 imm = insn & 0xfff;
7937 tcg_gen_addi_i32(addr, addr, imm);
7938 } else {
7939 op = (insn >> 8) & 7;
7940 imm = insn & 0xff;
7941 switch (op) {
7942 case 0: case 8: /* Shifted Register. */
7943 shift = (insn >> 4) & 0xf;
7944 if (shift > 3)
7945 goto illegal_op;
7946 tmp = load_reg(s, rm);
7947 if (shift)
7948 tcg_gen_shli_i32(tmp, tmp, shift);
7949 tcg_gen_add_i32(addr, addr, tmp);
7950 dead_tmp(tmp);
7951 break;
7952 case 4: /* Negative offset. */
7953 tcg_gen_addi_i32(addr, addr, -imm);
7954 break;
7955 case 6: /* User privilege. */
7956 tcg_gen_addi_i32(addr, addr, imm);
7957 user = 1;
7958 break;
7959 case 1: /* Post-decrement. */
7960 imm = -imm;
7961 /* Fall through. */
7962 case 3: /* Post-increment. */
7963 postinc = 1;
7964 writeback = 1;
7965 break;
7966 case 5: /* Pre-decrement. */
7967 imm = -imm;
7968 /* Fall through. */
7969 case 7: /* Pre-increment. */
7970 tcg_gen_addi_i32(addr, addr, imm);
7971 writeback = 1;
7972 break;
7973 default:
7974 goto illegal_op;
7978 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7979 if (insn & (1 << 20)) {
7980 /* Load. */
7981 if (rs == 15 && op != 2) {
7982 if (op & 2)
7983 goto illegal_op;
7984 /* Memory hint. Implemented as NOP. */
7985 } else {
7986 switch (op) {
7987 case 0: tmp = gen_ld8u(addr, user); break;
7988 case 4: tmp = gen_ld8s(addr, user); break;
7989 case 1: tmp = gen_ld16u(addr, user); break;
7990 case 5: tmp = gen_ld16s(addr, user); break;
7991 case 2: tmp = gen_ld32(addr, user); break;
7992 default: goto illegal_op;
7994 if (rs == 15 && ENABLE_ARCH_5) {
7995 gen_bx(s, tmp);
7996 } else {
7997 store_reg(s, rs, tmp);
8000 } else {
8001 /* Store. */
8002 if (rs == 15)
8003 goto illegal_op;
8004 tmp = load_reg(s, rs);
8005 switch (op) {
8006 case 0: gen_st8(tmp, addr, user); break;
8007 case 1: gen_st16(tmp, addr, user); break;
8008 case 2: gen_st32(tmp, addr, user); break;
8009 default: goto illegal_op;
8012 if (postinc)
8013 tcg_gen_addi_i32(addr, addr, imm);
8014 if (writeback) {
8015 store_reg(s, rn, addr);
8016 } else {
8017 dead_tmp(addr);
8020 break;
8021 default:
8022 goto illegal_op;
8024 return 0;
8025 illegal_op:
8026 return 1;
8029 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8031 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8032 int32_t offset;
8033 int i;
8034 TCGv tmp;
8035 TCGv tmp2;
8036 TCGv addr;
8037 int crement;
8039 if (s->condexec_mask) {
8040 cond = s->condexec_cond;
8041 s->condlabel = gen_new_label();
8042 gen_test_cc(cond ^ 1, s->condlabel);
8043 s->condjmp = 1;
8046 insn = lduw_code(s->pc);
8047 s->pc += 2;
8049 switch (insn >> 12) {
8050 case 0: case 1:
8052 rd = insn & 7;
8053 op = (insn >> 11) & 3;
8054 if (op == 3) {
8055 /* add/subtract */
8056 rn = (insn >> 3) & 7;
8057 tmp = load_reg(s, rn);
8058 if (insn & (1 << 10)) {
8059 /* immediate */
8060 tmp2 = new_tmp();
8061 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8062 } else {
8063 /* reg */
8064 rm = (insn >> 6) & 7;
8065 tmp2 = load_reg(s, rm);
8067 if (insn & (1 << 9)) {
8068 if (s->condexec_mask)
8069 tcg_gen_sub_i32(tmp, tmp, tmp2);
8070 else
8071 gen_helper_sub_cc(tmp, tmp, tmp2);
8072 } else {
8073 if (s->condexec_mask)
8074 tcg_gen_add_i32(tmp, tmp, tmp2);
8075 else
8076 gen_helper_add_cc(tmp, tmp, tmp2);
8078 dead_tmp(tmp2);
8079 store_reg(s, rd, tmp);
8080 } else {
8081 /* shift immediate */
8082 rm = (insn >> 3) & 7;
8083 shift = (insn >> 6) & 0x1f;
8084 tmp = load_reg(s, rm);
8085 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8086 if (!s->condexec_mask)
8087 gen_logic_CC(tmp);
8088 store_reg(s, rd, tmp);
8090 break;
8091 case 2: case 3:
8092 /* arithmetic large immediate */
8093 op = (insn >> 11) & 3;
8094 rd = (insn >> 8) & 0x7;
8095 if (op == 0) { /* mov */
8096 tmp = new_tmp();
8097 tcg_gen_movi_i32(tmp, insn & 0xff);
8098 if (!s->condexec_mask)
8099 gen_logic_CC(tmp);
8100 store_reg(s, rd, tmp);
8101 } else {
8102 tmp = load_reg(s, rd);
8103 tmp2 = new_tmp();
8104 tcg_gen_movi_i32(tmp2, insn & 0xff);
8105 switch (op) {
8106 case 1: /* cmp */
8107 gen_helper_sub_cc(tmp, tmp, tmp2);
8108 dead_tmp(tmp);
8109 dead_tmp(tmp2);
8110 break;
8111 case 2: /* add */
8112 if (s->condexec_mask)
8113 tcg_gen_add_i32(tmp, tmp, tmp2);
8114 else
8115 gen_helper_add_cc(tmp, tmp, tmp2);
8116 dead_tmp(tmp2);
8117 store_reg(s, rd, tmp);
8118 break;
8119 case 3: /* sub */
8120 if (s->condexec_mask)
8121 tcg_gen_sub_i32(tmp, tmp, tmp2);
8122 else
8123 gen_helper_sub_cc(tmp, tmp, tmp2);
8124 dead_tmp(tmp2);
8125 store_reg(s, rd, tmp);
8126 break;
8129 break;
8130 case 4:
8131 if (insn & (1 << 11)) {
8132 rd = (insn >> 8) & 7;
8133 /* load pc-relative. Bit 1 of PC is ignored. */
8134 val = s->pc + 2 + ((insn & 0xff) * 4);
8135 val &= ~(uint32_t)2;
8136 addr = new_tmp();
8137 tcg_gen_movi_i32(addr, val);
8138 tmp = gen_ld32(addr, IS_USER(s));
8139 dead_tmp(addr);
8140 store_reg(s, rd, tmp);
8141 break;
8143 if (insn & (1 << 10)) {
8144 /* data processing extended or blx */
8145 rd = (insn & 7) | ((insn >> 4) & 8);
8146 rm = (insn >> 3) & 0xf;
8147 op = (insn >> 8) & 3;
8148 switch (op) {
8149 case 0: /* add */
8150 tmp = load_reg(s, rd);
8151 tmp2 = load_reg(s, rm);
8152 tcg_gen_add_i32(tmp, tmp, tmp2);
8153 dead_tmp(tmp2);
8154 store_reg(s, rd, tmp);
8155 break;
8156 case 1: /* cmp */
8157 tmp = load_reg(s, rd);
8158 tmp2 = load_reg(s, rm);
8159 gen_helper_sub_cc(tmp, tmp, tmp2);
8160 dead_tmp(tmp2);
8161 dead_tmp(tmp);
8162 break;
8163 case 2: /* mov/cpy */
8164 tmp = load_reg(s, rm);
8165 store_reg(s, rd, tmp);
8166 break;
8167 case 3:/* branch [and link] exchange thumb register */
8168 tmp = load_reg(s, rm);
8169 if (insn & (1 << 7)) {
8170 ARCH(5);
8171 val = (uint32_t)s->pc | 1;
8172 tmp2 = new_tmp();
8173 tcg_gen_movi_i32(tmp2, val);
8174 store_reg(s, 14, tmp2);
8176 gen_bx(s, tmp);
8177 break;
8179 break;
8182 /* data processing register */
8183 rd = insn & 7;
8184 rm = (insn >> 3) & 7;
8185 op = (insn >> 6) & 0xf;
8186 if (op == 2 || op == 3 || op == 4 || op == 7) {
8187 /* the shift/rotate ops want the operands backwards */
8188 val = rm;
8189 rm = rd;
8190 rd = val;
8191 val = 1;
8192 } else {
8193 val = 0;
8196 if (op == 9) { /* neg */
8197 tmp = new_tmp();
8198 tcg_gen_movi_i32(tmp, 0);
8199 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8200 tmp = load_reg(s, rd);
8201 } else {
8202 TCGV_UNUSED(tmp);
8205 tmp2 = load_reg(s, rm);
8206 switch (op) {
8207 case 0x0: /* and */
8208 tcg_gen_and_i32(tmp, tmp, tmp2);
8209 if (!s->condexec_mask)
8210 gen_logic_CC(tmp);
8211 break;
8212 case 0x1: /* eor */
8213 tcg_gen_xor_i32(tmp, tmp, tmp2);
8214 if (!s->condexec_mask)
8215 gen_logic_CC(tmp);
8216 break;
8217 case 0x2: /* lsl */
8218 if (s->condexec_mask) {
8219 gen_helper_shl(tmp2, tmp2, tmp);
8220 } else {
8221 gen_helper_shl_cc(tmp2, tmp2, tmp);
8222 gen_logic_CC(tmp2);
8224 break;
8225 case 0x3: /* lsr */
8226 if (s->condexec_mask) {
8227 gen_helper_shr(tmp2, tmp2, tmp);
8228 } else {
8229 gen_helper_shr_cc(tmp2, tmp2, tmp);
8230 gen_logic_CC(tmp2);
8232 break;
8233 case 0x4: /* asr */
8234 if (s->condexec_mask) {
8235 gen_helper_sar(tmp2, tmp2, tmp);
8236 } else {
8237 gen_helper_sar_cc(tmp2, tmp2, tmp);
8238 gen_logic_CC(tmp2);
8240 break;
8241 case 0x5: /* adc */
8242 if (s->condexec_mask)
8243 gen_add_carry(tmp, tmp, tmp2);
8244 else
8245 gen_helper_adc_cc(tmp, tmp, tmp2);
8246 break;
8247 case 0x6: /* sbc */
8248 if (s->condexec_mask)
8249 gen_sub_carry(tmp, tmp, tmp2);
8250 else
8251 gen_helper_sbc_cc(tmp, tmp, tmp2);
8252 break;
8253 case 0x7: /* ror */
8254 if (s->condexec_mask) {
8255 gen_helper_ror(tmp2, tmp2, tmp);
8256 } else {
8257 gen_helper_ror_cc(tmp2, tmp2, tmp);
8258 gen_logic_CC(tmp2);
8260 break;
8261 case 0x8: /* tst */
8262 tcg_gen_and_i32(tmp, tmp, tmp2);
8263 gen_logic_CC(tmp);
8264 rd = 16;
8265 break;
8266 case 0x9: /* neg */
8267 if (s->condexec_mask)
8268 tcg_gen_neg_i32(tmp, tmp2);
8269 else
8270 gen_helper_sub_cc(tmp, tmp, tmp2);
8271 break;
8272 case 0xa: /* cmp */
8273 gen_helper_sub_cc(tmp, tmp, tmp2);
8274 rd = 16;
8275 break;
8276 case 0xb: /* cmn */
8277 gen_helper_add_cc(tmp, tmp, tmp2);
8278 rd = 16;
8279 break;
8280 case 0xc: /* orr */
8281 tcg_gen_or_i32(tmp, tmp, tmp2);
8282 if (!s->condexec_mask)
8283 gen_logic_CC(tmp);
8284 break;
8285 case 0xd: /* mul */
8286 gen_mull(tmp, tmp2);
8287 if (!s->condexec_mask)
8288 gen_logic_CC(tmp);
8289 break;
8290 case 0xe: /* bic */
8291 tcg_gen_bic_i32(tmp, tmp, tmp2);
8292 if (!s->condexec_mask)
8293 gen_logic_CC(tmp);
8294 break;
8295 case 0xf: /* mvn */
8296 tcg_gen_not_i32(tmp2, tmp2);
8297 if (!s->condexec_mask)
8298 gen_logic_CC(tmp2);
8299 val = 1;
8300 rm = rd;
8301 break;
8303 if (rd != 16) {
8304 if (val) {
8305 store_reg(s, rm, tmp2);
8306 dead_tmp(tmp);
8307 } else {
8308 store_reg(s, rd, tmp);
8309 dead_tmp(tmp2);
8311 } else {
8312 dead_tmp(tmp);
8313 dead_tmp(tmp2);
8315 break;
8317 case 5:
8318 /* load/store register offset. */
8319 rd = insn & 7;
8320 rn = (insn >> 3) & 7;
8321 rm = (insn >> 6) & 7;
8322 op = (insn >> 9) & 7;
8323 addr = load_reg(s, rn);
8324 tmp = load_reg(s, rm);
8325 tcg_gen_add_i32(addr, addr, tmp);
8326 dead_tmp(tmp);
8328 if (op < 3) /* store */
8329 tmp = load_reg(s, rd);
8331 switch (op) {
8332 case 0: /* str */
8333 gen_st32(tmp, addr, IS_USER(s));
8334 break;
8335 case 1: /* strh */
8336 gen_st16(tmp, addr, IS_USER(s));
8337 break;
8338 case 2: /* strb */
8339 gen_st8(tmp, addr, IS_USER(s));
8340 break;
8341 case 3: /* ldrsb */
8342 tmp = gen_ld8s(addr, IS_USER(s));
8343 break;
8344 case 4: /* ldr */
8345 tmp = gen_ld32(addr, IS_USER(s));
8346 break;
8347 case 5: /* ldrh */
8348 tmp = gen_ld16u(addr, IS_USER(s));
8349 break;
8350 case 6: /* ldrb */
8351 tmp = gen_ld8u(addr, IS_USER(s));
8352 break;
8353 case 7: /* ldrsh */
8354 tmp = gen_ld16s(addr, IS_USER(s));
8355 break;
8357 if (op >= 3) /* load */
8358 store_reg(s, rd, tmp);
8359 dead_tmp(addr);
8360 break;
8362 case 6:
8363 /* load/store word immediate offset */
8364 rd = insn & 7;
8365 rn = (insn >> 3) & 7;
8366 addr = load_reg(s, rn);
8367 val = (insn >> 4) & 0x7c;
8368 tcg_gen_addi_i32(addr, addr, val);
8370 if (insn & (1 << 11)) {
8371 /* load */
8372 tmp = gen_ld32(addr, IS_USER(s));
8373 store_reg(s, rd, tmp);
8374 } else {
8375 /* store */
8376 tmp = load_reg(s, rd);
8377 gen_st32(tmp, addr, IS_USER(s));
8379 dead_tmp(addr);
8380 break;
8382 case 7:
8383 /* load/store byte immediate offset */
8384 rd = insn & 7;
8385 rn = (insn >> 3) & 7;
8386 addr = load_reg(s, rn);
8387 val = (insn >> 6) & 0x1f;
8388 tcg_gen_addi_i32(addr, addr, val);
8390 if (insn & (1 << 11)) {
8391 /* load */
8392 tmp = gen_ld8u(addr, IS_USER(s));
8393 store_reg(s, rd, tmp);
8394 } else {
8395 /* store */
8396 tmp = load_reg(s, rd);
8397 gen_st8(tmp, addr, IS_USER(s));
8399 dead_tmp(addr);
8400 break;
8402 case 8:
8403 /* load/store halfword immediate offset */
8404 rd = insn & 7;
8405 rn = (insn >> 3) & 7;
8406 addr = load_reg(s, rn);
8407 val = (insn >> 5) & 0x3e;
8408 tcg_gen_addi_i32(addr, addr, val);
8410 if (insn & (1 << 11)) {
8411 /* load */
8412 tmp = gen_ld16u(addr, IS_USER(s));
8413 store_reg(s, rd, tmp);
8414 } else {
8415 /* store */
8416 tmp = load_reg(s, rd);
8417 gen_st16(tmp, addr, IS_USER(s));
8419 dead_tmp(addr);
8420 break;
8422 case 9:
8423 /* load/store from stack */
8424 rd = (insn >> 8) & 7;
8425 addr = load_reg(s, 13);
8426 val = (insn & 0xff) * 4;
8427 tcg_gen_addi_i32(addr, addr, val);
8429 if (insn & (1 << 11)) {
8430 /* load */
8431 tmp = gen_ld32(addr, IS_USER(s));
8432 store_reg(s, rd, tmp);
8433 } else {
8434 /* store */
8435 tmp = load_reg(s, rd);
8436 gen_st32(tmp, addr, IS_USER(s));
8438 dead_tmp(addr);
8439 break;
8441 case 10:
8442 /* add to high reg */
8443 rd = (insn >> 8) & 7;
8444 if (insn & (1 << 11)) {
8445 /* SP */
8446 tmp = load_reg(s, 13);
8447 } else {
8448 /* PC. bit 1 is ignored. */
8449 tmp = new_tmp();
8450 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8452 val = (insn & 0xff) * 4;
8453 tcg_gen_addi_i32(tmp, tmp, val);
8454 store_reg(s, rd, tmp);
8455 break;
8457 case 11:
8458 /* misc */
8459 op = (insn >> 8) & 0xf;
8460 switch (op) {
8461 case 0:
8462 /* adjust stack pointer */
8463 tmp = load_reg(s, 13);
8464 val = (insn & 0x7f) * 4;
8465 if (insn & (1 << 7))
8466 val = -(int32_t)val;
8467 tcg_gen_addi_i32(tmp, tmp, val);
8468 store_reg(s, 13, tmp);
8469 break;
8471 case 2: /* sign/zero extend. */
8472 ARCH(6);
8473 rd = insn & 7;
8474 rm = (insn >> 3) & 7;
8475 tmp = load_reg(s, rm);
8476 switch ((insn >> 6) & 3) {
8477 case 0: gen_sxth(tmp); break;
8478 case 1: gen_sxtb(tmp); break;
8479 case 2: gen_uxth(tmp); break;
8480 case 3: gen_uxtb(tmp); break;
8482 store_reg(s, rd, tmp);
8483 break;
8484 case 4: case 5: case 0xc: case 0xd:
8485 /* push/pop */
8486 addr = load_reg(s, 13);
8487 if (insn & (1 << 8))
8488 offset = 4;
8489 else
8490 offset = 0;
8491 for (i = 0; i < 8; i++) {
8492 if (insn & (1 << i))
8493 offset += 4;
8495 if ((insn & (1 << 11)) == 0) {
8496 tcg_gen_addi_i32(addr, addr, -offset);
8498 for (i = 0; i < 8; i++) {
8499 if (insn & (1 << i)) {
8500 if (insn & (1 << 11)) {
8501 /* pop */
8502 tmp = gen_ld32(addr, IS_USER(s));
8503 store_reg(s, i, tmp);
8504 } else {
8505 /* push */
8506 tmp = load_reg(s, i);
8507 gen_st32(tmp, addr, IS_USER(s));
8509 /* advance to the next address. */
8510 tcg_gen_addi_i32(addr, addr, 4);
8513 TCGV_UNUSED(tmp);
8514 if (insn & (1 << 8)) {
8515 if (insn & (1 << 11)) {
8516 /* pop pc */
8517 tmp = gen_ld32(addr, IS_USER(s));
8518 /* don't set the pc until the rest of the instruction
8519 has completed */
8520 } else {
8521 /* push lr */
8522 tmp = load_reg(s, 14);
8523 gen_st32(tmp, addr, IS_USER(s));
8525 tcg_gen_addi_i32(addr, addr, 4);
8527 if ((insn & (1 << 11)) == 0) {
8528 tcg_gen_addi_i32(addr, addr, -offset);
8530 /* write back the new stack pointer */
8531 store_reg(s, 13, addr);
8532 /* set the new PC value */
8533 if ((insn & 0x0900) == 0x0900) {
8534 if (ENABLE_ARCH_5) {
8535 gen_bx(s, tmp);
8536 } else {
8537 store_reg(s, 15, tmp);
8540 break;
8542 case 1: case 3: case 9: case 11: /* czb */
8543 rm = insn & 7;
8544 tmp = load_reg(s, rm);
8545 s->condlabel = gen_new_label();
8546 s->condjmp = 1;
8547 if (insn & (1 << 11))
8548 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8549 else
8550 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8551 dead_tmp(tmp);
8552 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8553 val = (uint32_t)s->pc + 2;
8554 val += offset;
8555 gen_jmp(s, val);
8556 break;
8558 case 15: /* IT, nop-hint. */
8559 if ((insn & 0xf) == 0) {
8560 gen_nop_hint(s, (insn >> 4) & 0xf);
8561 break;
8563 /* If Then. */
8564 s->condexec_cond = (insn >> 4) & 0xe;
8565 s->condexec_mask = insn & 0x1f;
8566 /* No actual code generated for this insn, just setup state. */
8567 break;
8569 case 0xe: /* bkpt */
8570 gen_set_condexec(s);
8571 gen_set_pc_im(s->pc - 2);
8572 gen_exception(EXCP_BKPT);
8573 s->is_jmp = DISAS_JUMP;
8574 break;
8576 case 0xa: /* rev */
8577 ARCH(6);
8578 rn = (insn >> 3) & 0x7;
8579 rd = insn & 0x7;
8580 tmp = load_reg(s, rn);
8581 switch ((insn >> 6) & 3) {
8582 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8583 case 1: gen_rev16(tmp); break;
8584 case 3: gen_revsh(tmp); break;
8585 default: goto illegal_op;
8587 store_reg(s, rd, tmp);
8588 break;
8590 case 6: /* cps */
8591 ARCH(6);
8592 if (IS_USER(s))
8593 break;
8594 if (IS_M(env)) {
8595 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8596 /* PRIMASK */
8597 if (insn & 1) {
8598 addr = tcg_const_i32(16);
8599 gen_helper_v7m_msr(cpu_env, addr, tmp);
8601 /* FAULTMASK */
8602 if (insn & 2) {
8603 addr = tcg_const_i32(17);
8604 gen_helper_v7m_msr(cpu_env, addr, tmp);
8606 gen_lookup_tb(s);
8607 } else {
8608 if (insn & (1 << 4))
8609 shift = CPSR_A | CPSR_I | CPSR_F;
8610 else
8611 shift = 0;
8612 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8614 break;
8616 default:
8617 goto undef;
8619 break;
8621 case 12:
8622 /* load/store multiple */
8623 rn = (insn >> 8) & 0x7;
8624 addr = load_reg(s, rn);
8625 if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8626 /* base-updated abort model: update base register
8627 before an abort can happen */
8628 crement = 0;
8629 for (i = 0; i < 8; i++) {
8630 if (insn & (1 << i)) {
8631 crement += 4;
8634 tmp = new_tmp();
8635 tcg_gen_addi_i32(tmp, addr, crement);
8636 store_reg(s, rn, tmp);
8638 for (i = 0; i < 8; i++) {
8639 if (insn & (1 << i)) {
8640 if (insn & (1 << 11)) {
8641 /* load */
8642 tmp = gen_ld32(addr, IS_USER(s));
8643 store_reg(s, i, tmp);
8644 } else {
8645 /* store */
8646 tmp = load_reg(s, i);
8647 gen_st32(tmp, addr, IS_USER(s));
8649 /* advance to the next address */
8650 tcg_gen_addi_i32(addr, addr, 4);
8653 /* Base register writeback. */
8654 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8655 store_reg(s, rn, addr);
8656 } else {
8657 dead_tmp(addr);
8659 break;
8661 case 13:
8662 /* conditional branch or swi */
8663 cond = (insn >> 8) & 0xf;
8664 if (cond == 0xe)
8665 goto undef;
8667 if (cond == 0xf) {
8668 /* swi */
8669 gen_set_condexec(s);
8670 gen_set_pc_im(s->pc);
8671 s->is_jmp = DISAS_SWI;
8672 break;
8674 /* generate a conditional jump to next instruction */
8675 s->condlabel = gen_new_label();
8676 gen_test_cc(cond ^ 1, s->condlabel);
8677 s->condjmp = 1;
8679 /* jump to the offset */
8680 val = (uint32_t)s->pc + 2;
8681 offset = ((int32_t)insn << 24) >> 24;
8682 val += offset << 1;
8683 gen_jmp(s, val);
8684 break;
8686 case 14:
8687 if (insn & (1 << 11)) {
8688 if (disas_thumb2_insn(env, s, insn))
8689 goto undef32;
8690 break;
8692 /* unconditional branch */
8693 val = (uint32_t)s->pc;
8694 offset = ((int32_t)insn << 21) >> 21;
8695 val += (offset << 1) + 2;
8696 gen_jmp(s, val);
8697 break;
8699 case 15:
8700 if (disas_thumb2_insn(env, s, insn))
8701 goto undef32;
8702 break;
8704 return;
8705 undef32:
8706 gen_set_condexec(s);
8707 gen_set_pc_im(s->pc - 4);
8708 gen_exception(EXCP_UDEF);
8709 s->is_jmp = DISAS_JUMP;
8710 return;
8711 illegal_op:
8712 undef:
8713 gen_set_condexec(s);
8714 gen_set_pc_im(s->pc - 2);
8715 gen_exception(EXCP_UDEF);
8716 s->is_jmp = DISAS_JUMP;
8719 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8720 basic block 'tb'. If search_pc is TRUE, also generate PC
8721 information for each intermediate instruction. */
8722 static inline void gen_intermediate_code_internal(CPUState *env,
8723 TranslationBlock *tb,
8724 int search_pc)
8726 DisasContext dc1, *dc = &dc1;
8727 CPUBreakpoint *bp;
8728 uint16_t *gen_opc_end;
8729 int j, lj;
8730 target_ulong pc_start;
8731 uint32_t next_page_start;
8732 int num_insns;
8733 int max_insns;
8735 /* generate intermediate code */
8736 num_temps = 0;
8738 pc_start = tb->pc;
8740 dc->tb = tb;
8742 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8744 dc->is_jmp = DISAS_NEXT;
8745 dc->pc = pc_start;
8746 dc->singlestep_enabled = env->singlestep_enabled;
8747 dc->condjmp = 0;
8748 dc->thumb = env->thumb;
8749 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8750 dc->condexec_cond = env->condexec_bits >> 4;
8751 #if !defined(CONFIG_USER_ONLY)
8752 if (IS_M(env)) {
8753 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8754 } else {
8755 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8757 #endif
8758 cpu_F0s = tcg_temp_new_i32();
8759 cpu_F1s = tcg_temp_new_i32();
8760 cpu_F0d = tcg_temp_new_i64();
8761 cpu_F1d = tcg_temp_new_i64();
8762 cpu_V0 = cpu_F0d;
8763 cpu_V1 = cpu_F1d;
8764 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8765 cpu_M0 = tcg_temp_new_i64();
8766 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8767 lj = -1;
8768 num_insns = 0;
8769 max_insns = tb->cflags & CF_COUNT_MASK;
8770 if (max_insns == 0)
8771 max_insns = CF_COUNT_MASK;
8773 gen_icount_start();
8774 /* Reset the conditional execution bits immediately. This avoids
8775 complications trying to do it at the end of the block. */
8776 if (env->condexec_bits)
8778 TCGv tmp = new_tmp();
8779 tcg_gen_movi_i32(tmp, 0);
8780 store_cpu_field(tmp, condexec_bits);
8782 do {
8783 #ifdef CONFIG_USER_ONLY
8784 /* Intercept jump to the magic kernel page. */
8785 if (dc->pc >= 0xffff0000) {
8786 /* We always get here via a jump, so know we are not in a
8787 conditional execution block. */
8788 gen_exception(EXCP_KERNEL_TRAP);
8789 dc->is_jmp = DISAS_UPDATE;
8790 break;
8792 #else
8793 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8794 /* We always get here via a jump, so know we are not in a
8795 conditional execution block. */
8796 gen_exception(EXCP_EXCEPTION_EXIT);
8797 dc->is_jmp = DISAS_UPDATE;
8798 break;
8800 #endif
8802 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8803 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8804 if (bp->pc == dc->pc) {
8805 gen_set_condexec(dc);
8806 gen_set_pc_im(dc->pc);
8807 gen_exception(EXCP_DEBUG);
8808 dc->is_jmp = DISAS_JUMP;
8809 /* Advance PC so that clearing the breakpoint will
8810 invalidate this TB. */
8811 dc->pc += 2;
8812 goto done_generating;
8813 break;
8817 if (search_pc) {
8818 j = gen_opc_ptr - gen_opc_buf;
8819 if (lj < j) {
8820 lj++;
8821 while (lj < j)
8822 gen_opc_instr_start[lj++] = 0;
8824 gen_opc_pc[lj] = dc->pc;
8825 gen_opc_instr_start[lj] = 1;
8826 gen_opc_icount[lj] = num_insns;
8829 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8830 gen_io_start();
8832 if (env->thumb) {
8833 disas_thumb_insn(env, dc);
8834 if (dc->condexec_mask) {
8835 dc->condexec_cond = (dc->condexec_cond & 0xe)
8836 | ((dc->condexec_mask >> 4) & 1);
8837 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8838 if (dc->condexec_mask == 0) {
8839 dc->condexec_cond = 0;
8842 } else {
8843 disas_arm_insn(env, dc);
8845 if (num_temps) {
8846 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8847 num_temps = 0;
8850 if (dc->condjmp && !dc->is_jmp) {
8851 gen_set_label(dc->condlabel);
8852 dc->condjmp = 0;
8854 /* Translation stops when a conditional branch is encountered.
8855 * Otherwise the subsequent code could get translated several times.
8856 * Also stop translation when a page boundary is reached. This
8857 * ensures prefetch aborts occur at the right place. */
8858 num_insns ++;
8859 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8860 !env->singlestep_enabled &&
8861 !singlestep &&
8862 dc->pc < next_page_start &&
8863 num_insns < max_insns);
8865 if (tb->cflags & CF_LAST_IO) {
8866 if (dc->condjmp) {
8867 /* FIXME: This can theoretically happen with self-modifying
8868 code. */
8869 cpu_abort(env, "IO on conditional branch instruction");
8871 gen_io_end();
8874 /* At this stage dc->condjmp will only be set when the skipped
8875 instruction was a conditional branch or trap, and the PC has
8876 already been written. */
8877 if (unlikely(env->singlestep_enabled)) {
8878 /* Make sure the pc is updated, and raise a debug exception. */
8879 if (dc->condjmp) {
8880 gen_set_condexec(dc);
8881 if (dc->is_jmp == DISAS_SWI) {
8882 gen_exception(EXCP_SWI);
8883 } else {
8884 gen_exception(EXCP_DEBUG);
8886 gen_set_label(dc->condlabel);
8888 if (dc->condjmp || !dc->is_jmp) {
8889 gen_set_pc_im(dc->pc);
8890 dc->condjmp = 0;
8892 gen_set_condexec(dc);
8893 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8894 gen_exception(EXCP_SWI);
8895 } else {
8896 /* FIXME: Single stepping a WFI insn will not halt
8897 the CPU. */
8898 gen_exception(EXCP_DEBUG);
8900 } else {
8901 /* While branches must always occur at the end of an IT block,
8902 there are a few other things that can cause us to terminate
8903 the TB in the middel of an IT block:
8904 - Exception generating instructions (bkpt, swi, undefined).
8905 - Page boundaries.
8906 - Hardware watchpoints.
8907 Hardware breakpoints have already been handled and skip this code.
8909 gen_set_condexec(dc);
8910 switch(dc->is_jmp) {
8911 case DISAS_NEXT:
8912 gen_goto_tb(dc, 1, dc->pc);
8913 break;
8914 default:
8915 case DISAS_JUMP:
8916 case DISAS_UPDATE:
8917 /* indicate that the hash table must be used to find the next TB */
8918 tcg_gen_exit_tb(0);
8919 break;
8920 case DISAS_TB_JUMP:
8921 /* nothing more to generate */
8922 break;
8923 case DISAS_WFI:
8924 gen_helper_wfi();
8925 break;
8926 case DISAS_SWI:
8927 gen_exception(EXCP_SWI);
8928 break;
8930 if (dc->condjmp) {
8931 gen_set_label(dc->condlabel);
8932 gen_set_condexec(dc);
8933 gen_goto_tb(dc, 1, dc->pc);
8934 dc->condjmp = 0;
8938 done_generating:
8939 gen_icount_end(tb, num_insns);
8940 *gen_opc_ptr = INDEX_op_end;
8942 #ifdef DEBUG_DISAS
8943 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8944 qemu_log("----------------\n");
8945 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8946 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8947 qemu_log("\n");
8949 #endif
8950 if (search_pc) {
8951 j = gen_opc_ptr - gen_opc_buf;
8952 lj++;
8953 while (lj <= j)
8954 gen_opc_instr_start[lj++] = 0;
8955 } else {
8956 tb->size = dc->pc - pc_start;
8957 tb->icount = num_insns;
8961 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8963 gen_intermediate_code_internal(env, tb, 0);
8966 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8968 gen_intermediate_code_internal(env, tb, 1);
8971 static const char *cpu_mode_names[16] = {
8972 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8973 "???", "???", "???", "und", "???", "???", "???", "sys"
8976 void cpu_dump_state(CPUState *env, FILE *f,
8977 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8978 int flags)
8980 int i;
8981 #if 0
8982 union {
8983 uint32_t i;
8984 float s;
8985 } s0, s1;
8986 CPU_DoubleU d;
8987 /* ??? This assumes float64 and double have the same layout.
8988 Oh well, it's only debug dumps. */
8989 union {
8990 float64 f64;
8991 double d;
8992 } d0;
8993 #endif
8994 uint32_t psr;
8996 for(i=0;i<16;i++) {
8997 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8998 if ((i % 4) == 3)
8999 cpu_fprintf(f, "\n");
9000 else
9001 cpu_fprintf(f, " ");
9003 psr = cpsr_read(env);
9004 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9005 psr,
9006 psr & (1 << 31) ? 'N' : '-',
9007 psr & (1 << 30) ? 'Z' : '-',
9008 psr & (1 << 29) ? 'C' : '-',
9009 psr & (1 << 28) ? 'V' : '-',
9010 psr & CPSR_T ? 'T' : 'A',
9011 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9013 #if 0
9014 for (i = 0; i < 16; i++) {
9015 d.d = env->vfp.regs[i];
9016 s0.i = d.l.lower;
9017 s1.i = d.l.upper;
9018 d0.f64 = d.d;
9019 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9020 i * 2, (int)s0.i, s0.s,
9021 i * 2 + 1, (int)s1.i, s1.s,
9022 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9023 d0.d);
9025 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9026 #endif
9029 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9030 unsigned long searched_pc, int pc_pos, void *puc)
9032 env->regs[15] = gen_opc_pc[pc_pos];