Fix bugs reported by Juha Riihimäki <juha.riihimaki@nokia.com>:
[qemu/navara.git] / target-arm / translate.c
blobfacccbe28dbcde3d0cf47f2c65fcb1b17c124111
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_movi_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 dead_tmp(addr);
3143 } else {
3144 /* load/store multiple */
3145 if (dp)
3146 n = (insn >> 1) & 0x7f;
3147 else
3148 n = insn & 0xff;
3150 if (insn & (1 << 24)) /* pre-decrement */
3151 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3153 if (dp)
3154 offset = 8;
3155 else
3156 offset = 4;
3157 for (i = 0; i < n; i++) {
3158 if (insn & ARM_CP_RW_BIT) {
3159 /* load */
3160 gen_vfp_ld(s, dp, addr);
3161 gen_mov_vreg_F0(dp, rd + i);
3162 } else {
3163 /* store */
3164 gen_mov_F0_vreg(dp, rd + i);
3165 gen_vfp_st(s, dp, addr);
3167 tcg_gen_addi_i32(addr, addr, offset);
3169 if (insn & (1 << 21)) {
3170 /* writeback */
3171 if (insn & (1 << 24))
3172 offset = -offset * n;
3173 else if (dp && (insn & 1))
3174 offset = 4;
3175 else
3176 offset = 0;
3178 if (offset != 0)
3179 tcg_gen_addi_i32(addr, addr, offset);
3180 store_reg(s, rn, addr);
3181 } else {
3182 dead_tmp(addr);
3186 break;
3187 default:
3188 /* Should never happen. */
3189 return 1;
3191 return 0;
3194 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3196 TranslationBlock *tb;
3198 tb = s->tb;
3199 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3200 tcg_gen_goto_tb(n);
3201 gen_set_pc_im(dest);
3202 tcg_gen_exit_tb((intptr_t)tb + n);
3203 } else {
3204 gen_set_pc_im(dest);
3205 tcg_gen_exit_tb(0);
3209 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3211 if (unlikely(s->singlestep_enabled)) {
3212 /* An indirect jump so that we still trigger the debug exception. */
3213 if (s->thumb)
3214 dest |= 1;
3215 gen_bx_im(s, dest);
3216 } else {
3217 gen_goto_tb(s, 0, dest);
3218 s->is_jmp = DISAS_TB_JUMP;
3222 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3224 if (x)
3225 tcg_gen_sari_i32(t0, t0, 16);
3226 else
3227 gen_sxth(t0);
3228 if (y)
3229 tcg_gen_sari_i32(t1, t1, 16);
3230 else
3231 gen_sxth(t1);
3232 tcg_gen_mul_i32(t0, t0, t1);
3235 /* Return the mask of PSR bits set by a MSR instruction. */
3236 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3237 uint32_t mask;
3239 mask = 0;
3240 if (flags & (1 << 0))
3241 mask |= 0xff;
3242 if (flags & (1 << 1))
3243 mask |= 0xff00;
3244 if (flags & (1 << 2))
3245 mask |= 0xff0000;
3246 if (flags & (1 << 3))
3247 mask |= 0xff000000;
3249 /* Mask out undefined bits. */
3250 mask &= ~CPSR_RESERVED;
3251 if (!arm_feature(env, ARM_FEATURE_V6))
3252 mask &= ~(CPSR_E | CPSR_GE);
3253 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3254 mask &= ~CPSR_IT;
3255 /* Mask out execution state bits. */
3256 if (!spsr)
3257 mask &= ~CPSR_EXEC;
3258 /* Mask out privileged bits. */
3259 if (IS_USER(s))
3260 mask &= CPSR_USER;
3261 return mask;
3264 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3265 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3267 TCGv tmp;
3268 if (spsr) {
3269 /* ??? This is also undefined in system mode. */
3270 if (IS_USER(s))
3271 return 1;
3273 tmp = load_cpu_field(spsr);
3274 tcg_gen_andi_i32(tmp, tmp, ~mask);
3275 tcg_gen_andi_i32(t0, t0, mask);
3276 tcg_gen_or_i32(tmp, tmp, t0);
3277 store_cpu_field(tmp, spsr);
3278 } else {
3279 gen_set_cpsr(t0, mask);
3281 dead_tmp(t0);
3282 gen_lookup_tb(s);
3283 return 0;
3286 /* Returns nonzero if access to the PSR is not permitted. */
3287 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3289 TCGv tmp;
3290 tmp = new_tmp();
3291 tcg_gen_movi_i32(tmp, val);
3292 return gen_set_psr(s, mask, spsr, tmp);
3295 /* Generate an old-style exception return. Marks pc as dead. */
3296 static void gen_exception_return(DisasContext *s, TCGv pc)
3298 TCGv tmp;
3299 store_reg(s, 15, pc);
3300 tmp = load_cpu_field(spsr);
3301 gen_set_cpsr(tmp, 0xffffffff);
3302 dead_tmp(tmp);
3303 s->is_jmp = DISAS_UPDATE;
3306 /* Generate a v6 exception return. Marks both values as dead. */
3307 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3309 gen_set_cpsr(cpsr, 0xffffffff);
3310 dead_tmp(cpsr);
3311 store_reg(s, 15, pc);
3312 s->is_jmp = DISAS_UPDATE;
3315 static inline void
3316 gen_set_condexec (DisasContext *s)
3318 if (s->condexec_mask) {
3319 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3320 TCGv tmp = new_tmp();
3321 tcg_gen_movi_i32(tmp, val);
3322 store_cpu_field(tmp, condexec_bits);
3326 static void gen_nop_hint(DisasContext *s, int val)
3328 switch (val) {
3329 case 3: /* wfi */
3330 gen_set_pc_im(s->pc);
3331 s->is_jmp = DISAS_WFI;
3332 break;
3333 case 2: /* wfe */
3334 case 4: /* sev */
3335 /* TODO: Implement SEV and WFE. May help SMP performance. */
3336 default: /* nop */
3337 break;
3341 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3343 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3345 switch (size) {
3346 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3347 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3348 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3349 default: return 1;
3351 return 0;
3354 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3356 switch (size) {
3357 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3358 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3359 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3360 default: return;
3364 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3365 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3366 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3367 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3368 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3370 /* FIXME: This is wrong. They set the wrong overflow bit. */
3371 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3372 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3373 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3374 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3376 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3377 switch ((size << 1) | u) { \
3378 case 0: \
3379 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3380 break; \
3381 case 1: \
3382 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3383 break; \
3384 case 2: \
3385 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3386 break; \
3387 case 3: \
3388 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3389 break; \
3390 case 4: \
3391 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3392 break; \
3393 case 5: \
3394 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3395 break; \
3396 default: return 1; \
3397 }} while (0)
3399 #define GEN_NEON_INTEGER_OP(name) do { \
3400 switch ((size << 1) | u) { \
3401 case 0: \
3402 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3403 break; \
3404 case 1: \
3405 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3406 break; \
3407 case 2: \
3408 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3409 break; \
3410 case 3: \
3411 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3412 break; \
3413 case 4: \
3414 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3415 break; \
3416 case 5: \
3417 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3418 break; \
3419 default: return 1; \
3420 }} while (0)
3422 static TCGv neon_load_scratch(int scratch)
3424 TCGv tmp = new_tmp();
3425 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3426 return tmp;
3429 static void neon_store_scratch(int scratch, TCGv var)
3431 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3432 dead_tmp(var);
3435 static inline TCGv neon_get_scalar(int size, int reg)
3437 TCGv tmp;
3438 if (size == 1) {
3439 tmp = neon_load_reg(reg >> 1, reg & 1);
3440 } else {
3441 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3442 if (reg & 1) {
3443 gen_neon_dup_low16(tmp);
3444 } else {
3445 gen_neon_dup_high16(tmp);
3448 return tmp;
3451 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3453 TCGv rd, rm, tmp;
3455 rd = new_tmp();
3456 rm = new_tmp();
3457 tmp = new_tmp();
3459 tcg_gen_andi_i32(rd, t0, 0xff);
3460 tcg_gen_shri_i32(tmp, t0, 8);
3461 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3462 tcg_gen_or_i32(rd, rd, tmp);
3463 tcg_gen_shli_i32(tmp, t1, 16);
3464 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3465 tcg_gen_or_i32(rd, rd, tmp);
3466 tcg_gen_shli_i32(tmp, t1, 8);
3467 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3468 tcg_gen_or_i32(rd, rd, tmp);
3470 tcg_gen_shri_i32(rm, t0, 8);
3471 tcg_gen_andi_i32(rm, rm, 0xff);
3472 tcg_gen_shri_i32(tmp, t0, 16);
3473 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3474 tcg_gen_or_i32(rm, rm, tmp);
3475 tcg_gen_shli_i32(tmp, t1, 8);
3476 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3477 tcg_gen_or_i32(rm, rm, tmp);
3478 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3479 tcg_gen_or_i32(t1, rm, tmp);
3480 tcg_gen_mov_i32(t0, rd);
3482 dead_tmp(tmp);
3483 dead_tmp(rm);
3484 dead_tmp(rd);
3487 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3489 TCGv rd, rm, tmp;
3491 rd = new_tmp();
3492 rm = new_tmp();
3493 tmp = new_tmp();
3495 tcg_gen_andi_i32(rd, t0, 0xff);
3496 tcg_gen_shli_i32(tmp, t1, 8);
3497 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3498 tcg_gen_or_i32(rd, rd, tmp);
3499 tcg_gen_shli_i32(tmp, t0, 16);
3500 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3501 tcg_gen_or_i32(rd, rd, tmp);
3502 tcg_gen_shli_i32(tmp, t1, 24);
3503 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3504 tcg_gen_or_i32(rd, rd, tmp);
3506 tcg_gen_andi_i32(rm, t1, 0xff000000);
3507 tcg_gen_shri_i32(tmp, t0, 8);
3508 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3509 tcg_gen_or_i32(rm, rm, tmp);
3510 tcg_gen_shri_i32(tmp, t1, 8);
3511 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3512 tcg_gen_or_i32(rm, rm, tmp);
3513 tcg_gen_shri_i32(tmp, t0, 16);
3514 tcg_gen_andi_i32(tmp, tmp, 0xff);
3515 tcg_gen_or_i32(t1, rm, tmp);
3516 tcg_gen_mov_i32(t0, rd);
3518 dead_tmp(tmp);
3519 dead_tmp(rm);
3520 dead_tmp(rd);
3523 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3525 TCGv tmp, tmp2;
3527 tmp = new_tmp();
3528 tmp2 = new_tmp();
3530 tcg_gen_andi_i32(tmp, t0, 0xffff);
3531 tcg_gen_shli_i32(tmp2, t1, 16);
3532 tcg_gen_or_i32(tmp, tmp, tmp2);
3533 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3534 tcg_gen_shri_i32(tmp2, t0, 16);
3535 tcg_gen_or_i32(t1, t1, tmp2);
3536 tcg_gen_mov_i32(t0, tmp);
3538 dead_tmp(tmp2);
3539 dead_tmp(tmp);
3542 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3544 int n;
3545 TCGv t0, t1;
3547 for (n = 0; n < q + 1; n += 2) {
3548 t0 = neon_load_reg(reg, n);
3549 t1 = neon_load_reg(reg, n + 1);
3550 switch (size) {
3551 case 0: gen_neon_unzip_u8(t0, t1); break;
3552 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3553 case 2: /* no-op */; break;
3554 default: abort();
3556 neon_store_scratch(tmp + n, t0);
3557 neon_store_scratch(tmp + n + 1, t1);
3561 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3563 TCGv rd, tmp;
3565 rd = new_tmp();
3566 tmp = new_tmp();
3568 tcg_gen_shli_i32(rd, t0, 8);
3569 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3570 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3571 tcg_gen_or_i32(rd, rd, tmp);
3573 tcg_gen_shri_i32(t1, t1, 8);
3574 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3575 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3576 tcg_gen_or_i32(t1, t1, tmp);
3577 tcg_gen_mov_i32(t0, rd);
3579 dead_tmp(tmp);
3580 dead_tmp(rd);
3583 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3585 TCGv rd, tmp;
3587 rd = new_tmp();
3588 tmp = new_tmp();
3590 tcg_gen_shli_i32(rd, t0, 16);
3591 tcg_gen_andi_i32(tmp, t1, 0xffff);
3592 tcg_gen_or_i32(rd, rd, tmp);
3593 tcg_gen_shri_i32(t1, t1, 16);
3594 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3595 tcg_gen_or_i32(t1, t1, tmp);
3596 tcg_gen_mov_i32(t0, rd);
3598 dead_tmp(tmp);
3599 dead_tmp(rd);
3603 static struct {
3604 int nregs;
3605 int interleave;
3606 int spacing;
3607 } neon_ls_element_type[11] = {
3608 {4, 4, 1},
3609 {4, 4, 2},
3610 {4, 1, 1},
3611 {4, 2, 1},
3612 {3, 3, 1},
3613 {3, 3, 2},
3614 {3, 1, 1},
3615 {1, 1, 1},
3616 {2, 2, 1},
3617 {2, 2, 2},
3618 {2, 1, 1}
3621 /* Translate a NEON load/store element instruction. Return nonzero if the
3622 instruction is invalid. */
3623 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3625 int rd, rn, rm;
3626 int op;
3627 int nregs;
3628 int interleave;
3629 int stride;
3630 int size;
3631 int reg;
3632 int pass;
3633 int load;
3634 int shift;
3635 int n;
3636 TCGv addr;
3637 TCGv tmp;
3638 TCGv tmp2;
3640 if (!vfp_enabled(env))
3641 return 1;
3642 VFP_DREG_D(rd, insn);
3643 rn = (insn >> 16) & 0xf;
3644 rm = insn & 0xf;
3645 load = (insn & (1 << 21)) != 0;
3646 addr = new_tmp();
3647 if ((insn & (1 << 23)) == 0) {
3648 /* Load store all elements. */
3649 op = (insn >> 8) & 0xf;
3650 size = (insn >> 6) & 3;
3651 if (op > 10 || size == 3)
3652 return 1;
3653 nregs = neon_ls_element_type[op].nregs;
3654 interleave = neon_ls_element_type[op].interleave;
3655 tcg_gen_mov_i32(addr, cpu_R[rn]);
3656 stride = (1 << size) * interleave;
3657 for (reg = 0; reg < nregs; reg++) {
3658 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3659 tcg_gen_add_i32(addr, cpu_R[rn], (1 << size) * reg);
3660 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3661 tcg_gen_add_i32(addr, cpu_R[rn], 1 << size);
3663 for (pass = 0; pass < 2; pass++) {
3664 if (size == 2) {
3665 if (load) {
3666 tmp = gen_ld32(addr, IS_USER(s));
3667 neon_store_reg(rd, pass, tmp);
3668 } else {
3669 tmp = neon_load_reg(rd, pass);
3670 gen_st32(tmp, addr, IS_USER(s));
3672 tcg_gen_addi_i32(addr, addr, stride);
3673 } else if (size == 1) {
3674 if (load) {
3675 tmp = gen_ld16u(addr, IS_USER(s));
3676 tcg_gen_addi_i32(addr, addr, stride);
3677 tmp2 = gen_ld16u(addr, IS_USER(s));
3678 tcg_gen_addi_i32(addr, addr, stride);
3679 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3680 dead_tmp(tmp2);
3681 neon_store_reg(rd, pass, tmp);
3682 } else {
3683 tmp = neon_load_reg(rd, pass);
3684 tmp2 = new_tmp();
3685 tcg_gen_shri_i32(tmp2, tmp, 16);
3686 gen_st16(tmp, addr, IS_USER(s));
3687 tcg_gen_addi_i32(addr, addr, stride);
3688 gen_st16(tmp2, addr, IS_USER(s));
3689 tcg_gen_addi_i32(addr, addr, stride);
3691 } else /* size == 0 */ {
3692 if (load) {
3693 TCGV_UNUSED(tmp2);
3694 for (n = 0; n < 4; n++) {
3695 tmp = gen_ld8u(addr, IS_USER(s));
3696 tcg_gen_addi_i32(addr, addr, stride);
3697 if (n == 0) {
3698 tmp2 = tmp;
3699 } else {
3700 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3701 dead_tmp(tmp);
3704 neon_store_reg(rd, pass, tmp2);
3705 } else {
3706 tmp2 = neon_load_reg(rd, pass);
3707 for (n = 0; n < 4; n++) {
3708 tmp = new_tmp();
3709 if (n == 0) {
3710 tcg_gen_mov_i32(tmp, tmp2);
3711 } else {
3712 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3714 gen_st8(tmp, addr, IS_USER(s));
3715 tcg_gen_addi_i32(addr, addr, stride);
3717 dead_tmp(tmp2);
3721 rd += neon_ls_element_type[op].spacing;
3723 stride = nregs * 8;
3724 } else {
3725 size = (insn >> 10) & 3;
3726 if (size == 3) {
3727 /* Load single element to all lanes. */
3728 if (!load)
3729 return 1;
3730 size = (insn >> 6) & 3;
3731 nregs = ((insn >> 8) & 3) + 1;
3732 stride = (insn & (1 << 5)) ? 2 : 1;
3733 tcg_gen_mov_i32(addr, cpu_R[rn]);
3734 for (reg = 0; reg < nregs; reg++) {
3735 switch (size) {
3736 case 0:
3737 tmp = gen_ld8u(addr, IS_USER(s));
3738 gen_neon_dup_u8(tmp, 0);
3739 break;
3740 case 1:
3741 tmp = gen_ld16u(addr, IS_USER(s));
3742 gen_neon_dup_low16(tmp);
3743 break;
3744 case 2:
3745 tmp = gen_ld32(addr, IS_USER(s));
3746 break;
3747 case 3:
3748 return 1;
3749 default: /* Avoid compiler warnings. */
3750 abort();
3752 tcg_gen_addi_i32(addr, addr, 1 << size);
3753 tmp2 = new_tmp();
3754 tcg_gen_mov_i32(tmp2, tmp);
3755 neon_store_reg(rd, 0, tmp2);
3756 neon_store_reg(rd, 1, tmp);
3757 rd += stride;
3759 stride = (1 << size) * nregs;
3760 } else {
3761 /* Single element. */
3762 pass = (insn >> 7) & 1;
3763 switch (size) {
3764 case 0:
3765 shift = ((insn >> 5) & 3) * 8;
3766 stride = 1;
3767 break;
3768 case 1:
3769 shift = ((insn >> 6) & 1) * 16;
3770 stride = (insn & (1 << 5)) ? 2 : 1;
3771 break;
3772 case 2:
3773 shift = 0;
3774 stride = (insn & (1 << 6)) ? 2 : 1;
3775 break;
3776 default:
3777 abort();
3779 nregs = ((insn >> 8) & 3) + 1;
3780 tcg_gen_mov_i32(addr, cpu_R[rn]);
3781 for (reg = 0; reg < nregs; reg++) {
3782 if (load) {
3783 switch (size) {
3784 case 0:
3785 tmp = gen_ld8u(addr, IS_USER(s));
3786 break;
3787 case 1:
3788 tmp = gen_ld16u(addr, IS_USER(s));
3789 break;
3790 case 2:
3791 tmp = gen_ld32(addr, IS_USER(s));
3792 break;
3793 default: /* Avoid compiler warnings. */
3794 abort();
3796 if (size != 2) {
3797 tmp2 = neon_load_reg(rd, pass);
3798 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3799 dead_tmp(tmp2);
3801 neon_store_reg(rd, pass, tmp);
3802 } else { /* Store */
3803 tmp = neon_load_reg(rd, pass);
3804 if (shift)
3805 tcg_gen_shri_i32(tmp, tmp, shift);
3806 switch (size) {
3807 case 0:
3808 gen_st8(tmp, addr, IS_USER(s));
3809 break;
3810 case 1:
3811 gen_st16(tmp, addr, IS_USER(s));
3812 break;
3813 case 2:
3814 gen_st32(tmp, addr, IS_USER(s));
3815 break;
3818 rd += stride;
3819 tcg_gen_addi_i32(addr, addr, 1 << size);
3821 stride = nregs * (1 << size);
3824 dead_tmp(addr);
3825 if (rm != 15) {
3826 TCGv base;
3828 base = load_reg(s, rn);
3829 if (rm == 13) {
3830 tcg_gen_addi_i32(base, base, stride);
3831 } else {
3832 TCGv index;
3833 index = load_reg(s, rm);
3834 tcg_gen_add_i32(base, base, index);
3835 dead_tmp(index);
3837 store_reg(s, rn, base);
3839 return 0;
3842 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3843 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3845 tcg_gen_and_i32(t, t, c);
3846 tcg_gen_bic_i32(f, f, c);
3847 tcg_gen_or_i32(dest, t, f);
3850 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3852 switch (size) {
3853 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3854 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3855 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3856 default: abort();
3860 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3862 switch (size) {
3863 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3864 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3865 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3866 default: abort();
3870 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3872 switch (size) {
3873 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3874 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3875 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3876 default: abort();
3880 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3881 int q, int u)
3883 if (q) {
3884 if (u) {
3885 switch (size) {
3886 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3887 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3888 default: abort();
3890 } else {
3891 switch (size) {
3892 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3893 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3894 default: abort();
3897 } else {
3898 if (u) {
3899 switch (size) {
3900 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3901 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3902 default: abort();
3904 } else {
3905 switch (size) {
3906 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3907 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3908 default: abort();
3914 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3916 if (u) {
3917 switch (size) {
3918 case 0: gen_helper_neon_widen_u8(dest, src); break;
3919 case 1: gen_helper_neon_widen_u16(dest, src); break;
3920 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3921 default: abort();
3923 } else {
3924 switch (size) {
3925 case 0: gen_helper_neon_widen_s8(dest, src); break;
3926 case 1: gen_helper_neon_widen_s16(dest, src); break;
3927 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3928 default: abort();
3931 dead_tmp(src);
3934 static inline void gen_neon_addl(int size)
3936 switch (size) {
3937 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3938 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3939 case 2: tcg_gen_add_i64(CPU_V001); break;
3940 default: abort();
3944 static inline void gen_neon_subl(int size)
3946 switch (size) {
3947 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3948 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3949 case 2: tcg_gen_sub_i64(CPU_V001); break;
3950 default: abort();
3954 static inline void gen_neon_negl(TCGv_i64 var, int size)
3956 switch (size) {
3957 case 0: gen_helper_neon_negl_u16(var, var); break;
3958 case 1: gen_helper_neon_negl_u32(var, var); break;
3959 case 2: gen_helper_neon_negl_u64(var, var); break;
3960 default: abort();
3964 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
3966 switch (size) {
3967 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3968 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
3969 default: abort();
3973 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
3975 TCGv_i64 tmp;
3977 switch ((size << 1) | u) {
3978 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3979 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3980 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3981 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3982 case 4:
3983 tmp = gen_muls_i64_i32(a, b);
3984 tcg_gen_mov_i64(dest, tmp);
3985 break;
3986 case 5:
3987 tmp = gen_mulu_i64_i32(a, b);
3988 tcg_gen_mov_i64(dest, tmp);
3989 break;
3990 default: abort();
3994 /* Translate a NEON data processing instruction. Return nonzero if the
3995 instruction is invalid.
3996 We process data in a mixture of 32-bit and 64-bit chunks.
3997 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
3999 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4001 int op;
4002 int q;
4003 int rd, rn, rm;
4004 int size;
4005 int shift;
4006 int pass;
4007 int count;
4008 int pairwise;
4009 int u;
4010 int n;
4011 uint32_t imm;
4012 TCGv tmp;
4013 TCGv tmp2;
4014 TCGv tmp3;
4015 TCGv_i64 tmp64;
4017 if (!vfp_enabled(env))
4018 return 1;
4019 q = (insn & (1 << 6)) != 0;
4020 u = (insn >> 24) & 1;
4021 VFP_DREG_D(rd, insn);
4022 VFP_DREG_N(rn, insn);
4023 VFP_DREG_M(rm, insn);
4024 size = (insn >> 20) & 3;
4025 if ((insn & (1 << 23)) == 0) {
4026 /* Three register same length. */
4027 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4028 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4029 || op == 10 || op == 11 || op == 16)) {
4030 /* 64-bit element instructions. */
4031 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4032 neon_load_reg64(cpu_V0, rn + pass);
4033 neon_load_reg64(cpu_V1, rm + pass);
4034 switch (op) {
4035 case 1: /* VQADD */
4036 if (u) {
4037 gen_helper_neon_add_saturate_u64(CPU_V001);
4038 } else {
4039 gen_helper_neon_add_saturate_s64(CPU_V001);
4041 break;
4042 case 5: /* VQSUB */
4043 if (u) {
4044 gen_helper_neon_sub_saturate_u64(CPU_V001);
4045 } else {
4046 gen_helper_neon_sub_saturate_s64(CPU_V001);
4048 break;
4049 case 8: /* VSHL */
4050 if (u) {
4051 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4052 } else {
4053 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4055 break;
4056 case 9: /* VQSHL */
4057 if (u) {
4058 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4059 cpu_V0, cpu_V0);
4060 } else {
4061 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4062 cpu_V1, cpu_V0);
4064 break;
4065 case 10: /* VRSHL */
4066 if (u) {
4067 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4068 } else {
4069 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4071 break;
4072 case 11: /* VQRSHL */
4073 if (u) {
4074 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4075 cpu_V1, cpu_V0);
4076 } else {
4077 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4078 cpu_V1, cpu_V0);
4080 break;
4081 case 16:
4082 if (u) {
4083 tcg_gen_sub_i64(CPU_V001);
4084 } else {
4085 tcg_gen_add_i64(CPU_V001);
4087 break;
4088 default:
4089 abort();
4091 neon_store_reg64(cpu_V0, rd + pass);
4093 return 0;
4095 switch (op) {
4096 case 8: /* VSHL */
4097 case 9: /* VQSHL */
4098 case 10: /* VRSHL */
4099 case 11: /* VQRSHL */
4101 int rtmp;
4102 /* Shift instruction operands are reversed. */
4103 rtmp = rn;
4104 rn = rm;
4105 rm = rtmp;
4106 pairwise = 0;
4108 break;
4109 case 20: /* VPMAX */
4110 case 21: /* VPMIN */
4111 case 23: /* VPADD */
4112 pairwise = 1;
4113 break;
4114 case 26: /* VPADD (float) */
4115 pairwise = (u && size < 2);
4116 break;
4117 case 30: /* VPMIN/VPMAX (float) */
4118 pairwise = u;
4119 break;
4120 default:
4121 pairwise = 0;
4122 break;
4125 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4127 if (pairwise) {
4128 /* Pairwise. */
4129 if (q)
4130 n = (pass & 1) * 2;
4131 else
4132 n = 0;
4133 if (pass < q + 1) {
4134 tmp = neon_load_reg(rn, n);
4135 tmp2 = neon_load_reg(rn, n + 1);
4136 } else {
4137 tmp = neon_load_reg(rm, n);
4138 tmp2 = neon_load_reg(rm, n + 1);
4140 } else {
4141 /* Elementwise. */
4142 tmp = neon_load_reg(rn, pass);
4143 tmp2 = neon_load_reg(rm, pass);
4145 switch (op) {
4146 case 0: /* VHADD */
4147 GEN_NEON_INTEGER_OP(hadd);
4148 break;
4149 case 1: /* VQADD */
4150 GEN_NEON_INTEGER_OP_ENV(qadd);
4151 break;
4152 case 2: /* VRHADD */
4153 GEN_NEON_INTEGER_OP(rhadd);
4154 break;
4155 case 3: /* Logic ops. */
4156 switch ((u << 2) | size) {
4157 case 0: /* VAND */
4158 tcg_gen_and_i32(tmp, tmp, tmp2);
4159 break;
4160 case 1: /* BIC */
4161 tcg_gen_bic_i32(tmp, tmp, tmp2);
4162 break;
4163 case 2: /* VORR */
4164 tcg_gen_or_i32(tmp, tmp, tmp2);
4165 break;
4166 case 3: /* VORN */
4167 tcg_gen_not_i32(tmp2, tmp2);
4168 tcg_gen_or_i32(tmp, tmp, tmp2);
4169 break;
4170 case 4: /* VEOR */
4171 tcg_gen_xor_i32(tmp, tmp, tmp2);
4172 break;
4173 case 5: /* VBSL */
4174 tmp3 = neon_load_reg(rd, pass);
4175 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4176 dead_tmp(tmp3);
4177 break;
4178 case 6: /* VBIT */
4179 tmp3 = neon_load_reg(rd, pass);
4180 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4181 dead_tmp(tmp3);
4182 break;
4183 case 7: /* VBIF */
4184 tmp3 = neon_load_reg(rd, pass);
4185 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4186 dead_tmp(tmp3);
4187 break;
4189 break;
4190 case 4: /* VHSUB */
4191 GEN_NEON_INTEGER_OP(hsub);
4192 break;
4193 case 5: /* VQSUB */
4194 GEN_NEON_INTEGER_OP_ENV(qsub);
4195 break;
4196 case 6: /* VCGT */
4197 GEN_NEON_INTEGER_OP(cgt);
4198 break;
4199 case 7: /* VCGE */
4200 GEN_NEON_INTEGER_OP(cge);
4201 break;
4202 case 8: /* VSHL */
4203 GEN_NEON_INTEGER_OP(shl);
4204 break;
4205 case 9: /* VQSHL */
4206 GEN_NEON_INTEGER_OP_ENV(qshl);
4207 break;
4208 case 10: /* VRSHL */
4209 GEN_NEON_INTEGER_OP(rshl);
4210 break;
4211 case 11: /* VQRSHL */
4212 GEN_NEON_INTEGER_OP_ENV(qrshl);
4213 break;
4214 case 12: /* VMAX */
4215 GEN_NEON_INTEGER_OP(max);
4216 break;
4217 case 13: /* VMIN */
4218 GEN_NEON_INTEGER_OP(min);
4219 break;
4220 case 14: /* VABD */
4221 GEN_NEON_INTEGER_OP(abd);
4222 break;
4223 case 15: /* VABA */
4224 GEN_NEON_INTEGER_OP(abd);
4225 dead_tmp(tmp2);
4226 tmp2 = neon_load_reg(rd, pass);
4227 gen_neon_add(size, tmp, tmp2);
4228 break;
4229 case 16:
4230 if (!u) { /* VADD */
4231 if (gen_neon_add(size, tmp, tmp2))
4232 return 1;
4233 } else { /* VSUB */
4234 switch (size) {
4235 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4236 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4237 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4238 default: return 1;
4241 break;
4242 case 17:
4243 if (!u) { /* VTST */
4244 switch (size) {
4245 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4246 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4247 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4248 default: return 1;
4250 } else { /* VCEQ */
4251 switch (size) {
4252 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4253 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4254 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4255 default: return 1;
4258 break;
4259 case 18: /* Multiply. */
4260 switch (size) {
4261 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4262 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4263 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4264 default: return 1;
4266 dead_tmp(tmp2);
4267 tmp2 = neon_load_reg(rd, pass);
4268 if (u) { /* VMLS */
4269 gen_neon_rsb(size, tmp, tmp2);
4270 } else { /* VMLA */
4271 gen_neon_add(size, tmp, tmp2);
4273 break;
4274 case 19: /* VMUL */
4275 if (u) { /* polynomial */
4276 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4277 } else { /* Integer */
4278 switch (size) {
4279 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4280 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4281 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4282 default: return 1;
4285 break;
4286 case 20: /* VPMAX */
4287 GEN_NEON_INTEGER_OP(pmax);
4288 break;
4289 case 21: /* VPMIN */
4290 GEN_NEON_INTEGER_OP(pmin);
4291 break;
4292 case 22: /* Hultiply high. */
4293 if (!u) { /* VQDMULH */
4294 switch (size) {
4295 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4296 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4297 default: return 1;
4299 } else { /* VQRDHMUL */
4300 switch (size) {
4301 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4302 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4303 default: return 1;
4306 break;
4307 case 23: /* VPADD */
4308 if (u)
4309 return 1;
4310 switch (size) {
4311 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4312 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4313 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4314 default: return 1;
4316 break;
4317 case 26: /* Floating point arithnetic. */
4318 switch ((u << 2) | size) {
4319 case 0: /* VADD */
4320 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4321 break;
4322 case 2: /* VSUB */
4323 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4324 break;
4325 case 4: /* VPADD */
4326 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4327 break;
4328 case 6: /* VABD */
4329 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4330 break;
4331 default:
4332 return 1;
4334 break;
4335 case 27: /* Float multiply. */
4336 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4337 if (!u) {
4338 dead_tmp(tmp2);
4339 tmp2 = neon_load_reg(rd, pass);
4340 if (size == 0) {
4341 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4342 } else {
4343 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4346 break;
4347 case 28: /* Float compare. */
4348 if (!u) {
4349 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4350 } else {
4351 if (size == 0)
4352 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4353 else
4354 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4356 break;
4357 case 29: /* Float compare absolute. */
4358 if (!u)
4359 return 1;
4360 if (size == 0)
4361 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4362 else
4363 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4364 break;
4365 case 30: /* Float min/max. */
4366 if (size == 0)
4367 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4368 else
4369 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4370 break;
4371 case 31:
4372 if (size == 0)
4373 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4374 else
4375 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4376 break;
4377 default:
4378 abort();
4380 dead_tmp(tmp2);
4382 /* Save the result. For elementwise operations we can put it
4383 straight into the destination register. For pairwise operations
4384 we have to be careful to avoid clobbering the source operands. */
4385 if (pairwise && rd == rm) {
4386 neon_store_scratch(pass, tmp);
4387 } else {
4388 neon_store_reg(rd, pass, tmp);
4391 } /* for pass */
4392 if (pairwise && rd == rm) {
4393 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4394 tmp = neon_load_scratch(pass);
4395 neon_store_reg(rd, pass, tmp);
4398 /* End of 3 register same size operations. */
4399 } else if (insn & (1 << 4)) {
4400 if ((insn & 0x00380080) != 0) {
4401 /* Two registers and shift. */
4402 op = (insn >> 8) & 0xf;
4403 if (insn & (1 << 7)) {
4404 /* 64-bit shift. */
4405 size = 3;
4406 } else {
4407 size = 2;
4408 while ((insn & (1 << (size + 19))) == 0)
4409 size--;
4411 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4412 /* To avoid excessive dumplication of ops we implement shift
4413 by immediate using the variable shift operations. */
4414 if (op < 8) {
4415 /* Shift by immediate:
4416 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4417 /* Right shifts are encoded as N - shift, where N is the
4418 element size in bits. */
4419 if (op <= 4)
4420 shift = shift - (1 << (size + 3));
4421 if (size == 3) {
4422 count = q + 1;
4423 } else {
4424 count = q ? 4: 2;
4426 switch (size) {
4427 case 0:
4428 imm = (uint8_t) shift;
4429 imm |= imm << 8;
4430 imm |= imm << 16;
4431 break;
4432 case 1:
4433 imm = (uint16_t) shift;
4434 imm |= imm << 16;
4435 break;
4436 case 2:
4437 case 3:
4438 imm = shift;
4439 break;
4440 default:
4441 abort();
4444 for (pass = 0; pass < count; pass++) {
4445 if (size == 3) {
4446 neon_load_reg64(cpu_V0, rm + pass);
4447 tcg_gen_movi_i64(cpu_V1, imm);
4448 switch (op) {
4449 case 0: /* VSHR */
4450 case 1: /* VSRA */
4451 if (u)
4452 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4453 else
4454 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4455 break;
4456 case 2: /* VRSHR */
4457 case 3: /* VRSRA */
4458 if (u)
4459 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4460 else
4461 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4462 break;
4463 case 4: /* VSRI */
4464 if (!u)
4465 return 1;
4466 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4467 break;
4468 case 5: /* VSHL, VSLI */
4469 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4470 break;
4471 case 6: /* VQSHL */
4472 if (u)
4473 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4474 else
4475 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4476 break;
4477 case 7: /* VQSHLU */
4478 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4479 break;
4481 if (op == 1 || op == 3) {
4482 /* Accumulate. */
4483 neon_load_reg64(cpu_V0, rd + pass);
4484 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4485 } else if (op == 4 || (op == 5 && u)) {
4486 /* Insert */
4487 cpu_abort(env, "VS[LR]I.64 not implemented");
4489 neon_store_reg64(cpu_V0, rd + pass);
4490 } else { /* size < 3 */
4491 /* Operands in T0 and T1. */
4492 tmp = neon_load_reg(rm, pass);
4493 tmp2 = new_tmp();
4494 tcg_gen_movi_i32(tmp2, imm);
4495 switch (op) {
4496 case 0: /* VSHR */
4497 case 1: /* VSRA */
4498 GEN_NEON_INTEGER_OP(shl);
4499 break;
4500 case 2: /* VRSHR */
4501 case 3: /* VRSRA */
4502 GEN_NEON_INTEGER_OP(rshl);
4503 break;
4504 case 4: /* VSRI */
4505 if (!u)
4506 return 1;
4507 GEN_NEON_INTEGER_OP(shl);
4508 break;
4509 case 5: /* VSHL, VSLI */
4510 switch (size) {
4511 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4512 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4513 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4514 default: return 1;
4516 break;
4517 case 6: /* VQSHL */
4518 GEN_NEON_INTEGER_OP_ENV(qshl);
4519 break;
4520 case 7: /* VQSHLU */
4521 switch (size) {
4522 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4523 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4524 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4525 default: return 1;
4527 break;
4529 dead_tmp(tmp2);
4531 if (op == 1 || op == 3) {
4532 /* Accumulate. */
4533 tmp2 = neon_load_reg(rd, pass);
4534 gen_neon_add(size, tmp2, tmp);
4535 dead_tmp(tmp2);
4536 } else if (op == 4 || (op == 5 && u)) {
4537 /* Insert */
4538 switch (size) {
4539 case 0:
4540 if (op == 4)
4541 imm = 0xff >> -shift;
4542 else
4543 imm = (uint8_t)(0xff << shift);
4544 imm |= imm << 8;
4545 imm |= imm << 16;
4546 break;
4547 case 1:
4548 if (op == 4)
4549 imm = 0xffff >> -shift;
4550 else
4551 imm = (uint16_t)(0xffff << shift);
4552 imm |= imm << 16;
4553 break;
4554 case 2:
4555 if (op == 4)
4556 imm = 0xffffffffu >> -shift;
4557 else
4558 imm = 0xffffffffu << shift;
4559 break;
4560 default:
4561 abort();
4563 tmp2 = neon_load_reg(rd, pass);
4564 tcg_gen_andi_i32(tmp, tmp, imm);
4565 tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4566 tcg_gen_or_i32(tmp, tmp, tmp2);
4567 dead_tmp(tmp2);
4569 neon_store_reg(rd, pass, tmp);
4571 } /* for pass */
4572 } else if (op < 10) {
4573 /* Shift by immediate and narrow:
4574 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4575 shift = shift - (1 << (size + 3));
4576 size++;
4577 switch (size) {
4578 case 1:
4579 imm = (uint16_t)shift;
4580 imm |= imm << 16;
4581 tmp2 = tcg_const_i32(imm);
4582 TCGV_UNUSED_I64(tmp64);
4583 break;
4584 case 2:
4585 imm = (uint32_t)shift;
4586 tmp2 = tcg_const_i32(imm);
4587 TCGV_UNUSED_I64(tmp64);
4588 break;
4589 case 3:
4590 tmp64 = tcg_const_i64(shift);
4591 TCGV_UNUSED(tmp2);
4592 break;
4593 default:
4594 abort();
4597 for (pass = 0; pass < 2; pass++) {
4598 if (size == 3) {
4599 neon_load_reg64(cpu_V0, rm + pass);
4600 if (q) {
4601 if (u)
4602 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4603 else
4604 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4605 } else {
4606 if (u)
4607 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4608 else
4609 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4611 } else {
4612 tmp = neon_load_reg(rm + pass, 0);
4613 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4614 tmp3 = neon_load_reg(rm + pass, 1);
4615 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4616 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4617 dead_tmp(tmp);
4618 dead_tmp(tmp3);
4620 tmp = new_tmp();
4621 if (op == 8 && !u) {
4622 gen_neon_narrow(size - 1, tmp, cpu_V0);
4623 } else {
4624 if (op == 8)
4625 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4626 else
4627 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4629 if (pass == 0) {
4630 tmp2 = tmp;
4631 } else {
4632 neon_store_reg(rd, 0, tmp2);
4633 neon_store_reg(rd, 1, tmp);
4635 } /* for pass */
4636 } else if (op == 10) {
4637 /* VSHLL */
4638 if (q || size == 3)
4639 return 1;
4640 tmp = neon_load_reg(rm, 0);
4641 tmp2 = neon_load_reg(rm, 1);
4642 for (pass = 0; pass < 2; pass++) {
4643 if (pass == 1)
4644 tmp = tmp2;
4646 gen_neon_widen(cpu_V0, tmp, size, u);
4648 if (shift != 0) {
4649 /* The shift is less than the width of the source
4650 type, so we can just shift the whole register. */
4651 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4652 if (size < 2 || !u) {
4653 uint64_t imm64;
4654 if (size == 0) {
4655 imm = (0xffu >> (8 - shift));
4656 imm |= imm << 16;
4657 } else {
4658 imm = 0xffff >> (16 - shift);
4660 imm64 = imm | (((uint64_t)imm) << 32);
4661 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4664 neon_store_reg64(cpu_V0, rd + pass);
4666 } else if (op == 15 || op == 16) {
4667 /* VCVT fixed-point. */
4668 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4669 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4670 if (op & 1) {
4671 if (u)
4672 gen_vfp_ulto(0, shift);
4673 else
4674 gen_vfp_slto(0, shift);
4675 } else {
4676 if (u)
4677 gen_vfp_toul(0, shift);
4678 else
4679 gen_vfp_tosl(0, shift);
4681 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4683 } else {
4684 return 1;
4686 } else { /* (insn & 0x00380080) == 0 */
4687 int invert;
4689 op = (insn >> 8) & 0xf;
4690 /* One register and immediate. */
4691 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4692 invert = (insn & (1 << 5)) != 0;
4693 switch (op) {
4694 case 0: case 1:
4695 /* no-op */
4696 break;
4697 case 2: case 3:
4698 imm <<= 8;
4699 break;
4700 case 4: case 5:
4701 imm <<= 16;
4702 break;
4703 case 6: case 7:
4704 imm <<= 24;
4705 break;
4706 case 8: case 9:
4707 imm |= imm << 16;
4708 break;
4709 case 10: case 11:
4710 imm = (imm << 8) | (imm << 24);
4711 break;
4712 case 12:
4713 imm = (imm < 8) | 0xff;
4714 break;
4715 case 13:
4716 imm = (imm << 16) | 0xffff;
4717 break;
4718 case 14:
4719 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4720 if (invert)
4721 imm = ~imm;
4722 break;
4723 case 15:
4724 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4725 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4726 break;
4728 if (invert)
4729 imm = ~imm;
4731 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4732 if (op & 1 && op < 12) {
4733 tmp = neon_load_reg(rd, pass);
4734 if (invert) {
4735 /* The immediate value has already been inverted, so
4736 BIC becomes AND. */
4737 tcg_gen_andi_i32(tmp, tmp, imm);
4738 } else {
4739 tcg_gen_ori_i32(tmp, tmp, imm);
4741 } else {
4742 /* VMOV, VMVN. */
4743 tmp = new_tmp();
4744 if (op == 14 && invert) {
4745 uint32_t val;
4746 val = 0;
4747 for (n = 0; n < 4; n++) {
4748 if (imm & (1 << (n + (pass & 1) * 4)))
4749 val |= 0xff << (n * 8);
4751 tcg_gen_movi_i32(tmp, val);
4752 } else {
4753 tcg_gen_movi_i32(tmp, imm);
4756 neon_store_reg(rd, pass, tmp);
4759 } else { /* (insn & 0x00800010 == 0x00800000) */
4760 if (size != 3) {
4761 op = (insn >> 8) & 0xf;
4762 if ((insn & (1 << 6)) == 0) {
4763 /* Three registers of different lengths. */
4764 int src1_wide;
4765 int src2_wide;
4766 int prewiden;
4767 /* prewiden, src1_wide, src2_wide */
4768 static const int neon_3reg_wide[16][3] = {
4769 {1, 0, 0}, /* VADDL */
4770 {1, 1, 0}, /* VADDW */
4771 {1, 0, 0}, /* VSUBL */
4772 {1, 1, 0}, /* VSUBW */
4773 {0, 1, 1}, /* VADDHN */
4774 {0, 0, 0}, /* VABAL */
4775 {0, 1, 1}, /* VSUBHN */
4776 {0, 0, 0}, /* VABDL */
4777 {0, 0, 0}, /* VMLAL */
4778 {0, 0, 0}, /* VQDMLAL */
4779 {0, 0, 0}, /* VMLSL */
4780 {0, 0, 0}, /* VQDMLSL */
4781 {0, 0, 0}, /* Integer VMULL */
4782 {0, 0, 0}, /* VQDMULL */
4783 {0, 0, 0} /* Polynomial VMULL */
4786 prewiden = neon_3reg_wide[op][0];
4787 src1_wide = neon_3reg_wide[op][1];
4788 src2_wide = neon_3reg_wide[op][2];
4790 if (size == 0 && (op == 9 || op == 11 || op == 13))
4791 return 1;
4793 /* Avoid overlapping operands. Wide source operands are
4794 always aligned so will never overlap with wide
4795 destinations in problematic ways. */
4796 if (rd == rm && !src2_wide) {
4797 tmp = neon_load_reg(rm, 1);
4798 neon_store_scratch(2, tmp);
4799 } else if (rd == rn && !src1_wide) {
4800 tmp = neon_load_reg(rn, 1);
4801 neon_store_scratch(2, tmp);
4803 TCGV_UNUSED(tmp3);
4804 for (pass = 0; pass < 2; pass++) {
4805 if (src1_wide) {
4806 neon_load_reg64(cpu_V0, rn + pass);
4807 TCGV_UNUSED(tmp);
4808 } else {
4809 if (pass == 1 && rd == rn) {
4810 tmp = neon_load_scratch(2);
4811 } else {
4812 tmp = neon_load_reg(rn, pass);
4814 if (prewiden) {
4815 gen_neon_widen(cpu_V0, tmp, size, u);
4818 if (src2_wide) {
4819 neon_load_reg64(cpu_V1, rm + pass);
4820 TCGV_UNUSED(tmp2);
4821 } else {
4822 if (pass == 1 && rd == rm) {
4823 tmp2 = neon_load_scratch(2);
4824 } else {
4825 tmp2 = neon_load_reg(rm, pass);
4827 if (prewiden) {
4828 gen_neon_widen(cpu_V1, tmp2, size, u);
4831 switch (op) {
4832 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4833 gen_neon_addl(size);
4834 break;
4835 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4836 gen_neon_subl(size);
4837 break;
4838 case 5: case 7: /* VABAL, VABDL */
4839 switch ((size << 1) | u) {
4840 case 0:
4841 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4842 break;
4843 case 1:
4844 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4845 break;
4846 case 2:
4847 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4848 break;
4849 case 3:
4850 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4851 break;
4852 case 4:
4853 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4854 break;
4855 case 5:
4856 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4857 break;
4858 default: abort();
4860 dead_tmp(tmp2);
4861 dead_tmp(tmp);
4862 break;
4863 case 8: case 9: case 10: case 11: case 12: case 13:
4864 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4865 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4866 dead_tmp(tmp2);
4867 dead_tmp(tmp);
4868 break;
4869 case 14: /* Polynomial VMULL */
4870 cpu_abort(env, "Polynomial VMULL not implemented");
4872 default: /* 15 is RESERVED. */
4873 return 1;
4875 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4876 /* Accumulate. */
4877 if (op == 10 || op == 11) {
4878 gen_neon_negl(cpu_V0, size);
4881 if (op != 13) {
4882 neon_load_reg64(cpu_V1, rd + pass);
4885 switch (op) {
4886 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4887 gen_neon_addl(size);
4888 break;
4889 case 9: case 11: /* VQDMLAL, VQDMLSL */
4890 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4891 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4892 break;
4893 /* Fall through. */
4894 case 13: /* VQDMULL */
4895 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4896 break;
4897 default:
4898 abort();
4900 neon_store_reg64(cpu_V0, rd + pass);
4901 } else if (op == 4 || op == 6) {
4902 /* Narrowing operation. */
4903 tmp = new_tmp();
4904 if (u) {
4905 switch (size) {
4906 case 0:
4907 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4908 break;
4909 case 1:
4910 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4911 break;
4912 case 2:
4913 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4914 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4915 break;
4916 default: abort();
4918 } else {
4919 switch (size) {
4920 case 0:
4921 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4922 break;
4923 case 1:
4924 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4925 break;
4926 case 2:
4927 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4928 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4929 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4930 break;
4931 default: abort();
4934 if (pass == 0) {
4935 tmp3 = tmp;
4936 } else {
4937 neon_store_reg(rd, 0, tmp3);
4938 neon_store_reg(rd, 1, tmp);
4940 } else {
4941 /* Write back the result. */
4942 neon_store_reg64(cpu_V0, rd + pass);
4945 } else {
4946 /* Two registers and a scalar. */
4947 switch (op) {
4948 case 0: /* Integer VMLA scalar */
4949 case 1: /* Float VMLA scalar */
4950 case 4: /* Integer VMLS scalar */
4951 case 5: /* Floating point VMLS scalar */
4952 case 8: /* Integer VMUL scalar */
4953 case 9: /* Floating point VMUL scalar */
4954 case 12: /* VQDMULH scalar */
4955 case 13: /* VQRDMULH scalar */
4956 tmp = neon_get_scalar(size, rm);
4957 neon_store_scratch(0, tmp);
4958 for (pass = 0; pass < (u ? 4 : 2); pass++) {
4959 tmp = neon_load_scratch(0);
4960 tmp2 = neon_load_reg(rn, pass);
4961 if (op == 12) {
4962 if (size == 1) {
4963 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4964 } else {
4965 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4967 } else if (op == 13) {
4968 if (size == 1) {
4969 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4970 } else {
4971 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4973 } else if (op & 1) {
4974 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4975 } else {
4976 switch (size) {
4977 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4978 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4979 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4980 default: return 1;
4983 dead_tmp(tmp2);
4984 if (op < 8) {
4985 /* Accumulate. */
4986 tmp2 = neon_load_reg(rd, pass);
4987 switch (op) {
4988 case 0:
4989 gen_neon_add(size, tmp, tmp2);
4990 break;
4991 case 1:
4992 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4993 break;
4994 case 4:
4995 gen_neon_rsb(size, tmp, tmp2);
4996 break;
4997 case 5:
4998 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4999 break;
5000 default:
5001 abort();
5003 dead_tmp(tmp2);
5005 neon_store_reg(rd, pass, tmp);
5007 break;
5008 case 2: /* VMLAL sclar */
5009 case 3: /* VQDMLAL scalar */
5010 case 6: /* VMLSL scalar */
5011 case 7: /* VQDMLSL scalar */
5012 case 10: /* VMULL scalar */
5013 case 11: /* VQDMULL scalar */
5014 if (size == 0 && (op == 3 || op == 7 || op == 11))
5015 return 1;
5017 tmp2 = neon_get_scalar(size, rm);
5018 tmp3 = neon_load_reg(rn, 1);
5020 for (pass = 0; pass < 2; pass++) {
5021 if (pass == 0) {
5022 tmp = neon_load_reg(rn, 0);
5023 } else {
5024 tmp = tmp3;
5026 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5027 dead_tmp(tmp);
5028 if (op == 6 || op == 7) {
5029 gen_neon_negl(cpu_V0, size);
5031 if (op != 11) {
5032 neon_load_reg64(cpu_V1, rd + pass);
5034 switch (op) {
5035 case 2: case 6:
5036 gen_neon_addl(size);
5037 break;
5038 case 3: case 7:
5039 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5040 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5041 break;
5042 case 10:
5043 /* no-op */
5044 break;
5045 case 11:
5046 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5047 break;
5048 default:
5049 abort();
5051 neon_store_reg64(cpu_V0, rd + pass);
5054 dead_tmp(tmp2);
5056 break;
5057 default: /* 14 and 15 are RESERVED */
5058 return 1;
5061 } else { /* size == 3 */
5062 if (!u) {
5063 /* Extract. */
5064 imm = (insn >> 8) & 0xf;
5065 count = q + 1;
5067 if (imm > 7 && !q)
5068 return 1;
5070 if (imm == 0) {
5071 neon_load_reg64(cpu_V0, rn);
5072 if (q) {
5073 neon_load_reg64(cpu_V1, rn + 1);
5075 } else if (imm == 8) {
5076 neon_load_reg64(cpu_V0, rn + 1);
5077 if (q) {
5078 neon_load_reg64(cpu_V1, rm);
5080 } else if (q) {
5081 tmp64 = tcg_temp_new_i64();
5082 if (imm < 8) {
5083 neon_load_reg64(cpu_V0, rn);
5084 neon_load_reg64(tmp64, rn + 1);
5085 } else {
5086 neon_load_reg64(cpu_V0, rn + 1);
5087 neon_load_reg64(tmp64, rm);
5089 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5090 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5091 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5092 if (imm < 8) {
5093 neon_load_reg64(cpu_V1, rm);
5094 } else {
5095 neon_load_reg64(cpu_V1, rm + 1);
5096 imm -= 8;
5098 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5099 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5100 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5101 } else {
5102 /* BUGFIX */
5103 neon_load_reg64(cpu_V0, rn);
5104 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5105 neon_load_reg64(cpu_V1, rm);
5106 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5107 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5109 neon_store_reg64(cpu_V0, rd);
5110 if (q) {
5111 neon_store_reg64(cpu_V1, rd + 1);
5113 } else if ((insn & (1 << 11)) == 0) {
5114 /* Two register misc. */
5115 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5116 size = (insn >> 18) & 3;
5117 switch (op) {
5118 case 0: /* VREV64 */
5119 if (size == 3)
5120 return 1;
5121 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5122 tmp = neon_load_reg(rm, pass * 2);
5123 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5124 switch (size) {
5125 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5126 case 1: gen_swap_half(tmp); break;
5127 case 2: /* no-op */ break;
5128 default: abort();
5130 neon_store_reg(rd, pass * 2 + 1, tmp);
5131 if (size == 2) {
5132 neon_store_reg(rd, pass * 2, tmp2);
5133 } else {
5134 switch (size) {
5135 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5136 case 1: gen_swap_half(tmp2); break;
5137 default: abort();
5139 neon_store_reg(rd, pass * 2, tmp2);
5142 break;
5143 case 4: case 5: /* VPADDL */
5144 case 12: case 13: /* VPADAL */
5145 if (size == 3)
5146 return 1;
5147 for (pass = 0; pass < q + 1; pass++) {
5148 tmp = neon_load_reg(rm, pass * 2);
5149 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5150 tmp = neon_load_reg(rm, pass * 2 + 1);
5151 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5152 switch (size) {
5153 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5154 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5155 case 2: tcg_gen_add_i64(CPU_V001); break;
5156 default: abort();
5158 if (op >= 12) {
5159 /* Accumulate. */
5160 neon_load_reg64(cpu_V1, rd + pass);
5161 gen_neon_addl(size);
5163 neon_store_reg64(cpu_V0, rd + pass);
5165 break;
5166 case 33: /* VTRN */
5167 if (size == 2) {
5168 for (n = 0; n < (q ? 4 : 2); n += 2) {
5169 tmp = neon_load_reg(rm, n);
5170 tmp2 = neon_load_reg(rd, n + 1);
5171 neon_store_reg(rm, n, tmp2);
5172 neon_store_reg(rd, n + 1, tmp);
5174 } else {
5175 goto elementwise;
5177 break;
5178 case 34: /* VUZP */
5179 /* Reg Before After
5180 Rd A3 A2 A1 A0 B2 B0 A2 A0
5181 Rm B3 B2 B1 B0 B3 B1 A3 A1
5183 if (size == 3)
5184 return 1;
5185 gen_neon_unzip(rd, q, 0, size);
5186 gen_neon_unzip(rm, q, 4, size);
5187 if (q) {
5188 static int unzip_order_q[8] =
5189 {0, 2, 4, 6, 1, 3, 5, 7};
5190 for (n = 0; n < 8; n++) {
5191 int reg = (n < 4) ? rd : rm;
5192 tmp = neon_load_scratch(unzip_order_q[n]);
5193 neon_store_reg(reg, n % 4, tmp);
5195 } else {
5196 static int unzip_order[4] =
5197 {0, 4, 1, 5};
5198 for (n = 0; n < 4; n++) {
5199 int reg = (n < 2) ? rd : rm;
5200 tmp = neon_load_scratch(unzip_order[n]);
5201 neon_store_reg(reg, n % 2, tmp);
5204 break;
5205 case 35: /* VZIP */
5206 /* Reg Before After
5207 Rd A3 A2 A1 A0 B1 A1 B0 A0
5208 Rm B3 B2 B1 B0 B3 A3 B2 A2
5210 if (size == 3)
5211 return 1;
5212 count = (q ? 4 : 2);
5213 for (n = 0; n < count; n++) {
5214 tmp = neon_load_reg(rd, n);
5215 tmp2 = neon_load_reg(rd, n);
5216 switch (size) {
5217 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5218 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5219 case 2: /* no-op */; break;
5220 default: abort();
5222 neon_store_scratch(n * 2, tmp);
5223 neon_store_scratch(n * 2 + 1, tmp2);
5225 for (n = 0; n < count * 2; n++) {
5226 int reg = (n < count) ? rd : rm;
5227 tmp = neon_load_scratch(n);
5228 neon_store_reg(reg, n % count, tmp);
5230 break;
5231 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5232 if (size == 3)
5233 return 1;
5234 TCGV_UNUSED(tmp2);
5235 for (pass = 0; pass < 2; pass++) {
5236 neon_load_reg64(cpu_V0, rm + pass);
5237 tmp = new_tmp();
5238 if (op == 36 && q == 0) {
5239 gen_neon_narrow(size, tmp, cpu_V0);
5240 } else if (q) {
5241 gen_neon_narrow_satu(size, tmp, cpu_V0);
5242 } else {
5243 gen_neon_narrow_sats(size, tmp, cpu_V0);
5245 if (pass == 0) {
5246 tmp2 = tmp;
5247 } else {
5248 neon_store_reg(rd, 0, tmp2);
5249 neon_store_reg(rd, 1, tmp);
5252 break;
5253 case 38: /* VSHLL */
5254 if (q || size == 3)
5255 return 1;
5256 tmp = neon_load_reg(rm, 0);
5257 tmp2 = neon_load_reg(rm, 1);
5258 for (pass = 0; pass < 2; pass++) {
5259 if (pass == 1)
5260 tmp = tmp2;
5261 gen_neon_widen(cpu_V0, tmp, size, 1);
5262 neon_store_reg64(cpu_V0, rd + pass);
5264 break;
5265 default:
5266 elementwise:
5267 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5268 if (op == 30 || op == 31 || op >= 58) {
5269 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5270 neon_reg_offset(rm, pass));
5271 TCGV_UNUSED(tmp);
5272 } else {
5273 tmp = neon_load_reg(rm, pass);
5275 switch (op) {
5276 case 1: /* VREV32 */
5277 switch (size) {
5278 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5279 case 1: gen_swap_half(tmp); break;
5280 default: return 1;
5282 break;
5283 case 2: /* VREV16 */
5284 if (size != 0)
5285 return 1;
5286 gen_rev16(tmp);
5287 break;
5288 case 8: /* CLS */
5289 switch (size) {
5290 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5291 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5292 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5293 default: return 1;
5295 break;
5296 case 9: /* CLZ */
5297 switch (size) {
5298 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5299 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5300 case 2: gen_helper_clz(tmp, tmp); break;
5301 default: return 1;
5303 break;
5304 case 10: /* CNT */
5305 if (size != 0)
5306 return 1;
5307 gen_helper_neon_cnt_u8(tmp, tmp);
5308 break;
5309 case 11: /* VNOT */
5310 if (size != 0)
5311 return 1;
5312 tcg_gen_not_i32(tmp, tmp);
5313 break;
5314 case 14: /* VQABS */
5315 switch (size) {
5316 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5317 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5318 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5319 default: return 1;
5321 break;
5322 case 15: /* VQNEG */
5323 switch (size) {
5324 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5325 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5326 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5327 default: return 1;
5329 break;
5330 case 16: case 19: /* VCGT #0, VCLE #0 */
5331 tmp2 = tcg_const_i32(0);
5332 switch(size) {
5333 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5334 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5335 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5336 default: return 1;
5338 tcg_temp_free(tmp2);
5339 if (op == 19)
5340 tcg_gen_not_i32(tmp, tmp);
5341 break;
5342 case 17: case 20: /* VCGE #0, VCLT #0 */
5343 tmp2 = tcg_const_i32(0);
5344 switch(size) {
5345 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5346 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5347 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5348 default: return 1;
5350 tcg_temp_free(tmp2);
5351 if (op == 20)
5352 tcg_gen_not_i32(tmp, tmp);
5353 break;
5354 case 18: /* VCEQ #0 */
5355 tmp2 = tcg_const_i32(0);
5356 switch(size) {
5357 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5358 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5359 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5360 default: return 1;
5362 tcg_temp_free(tmp2);
5363 break;
5364 case 22: /* VABS */
5365 switch(size) {
5366 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5367 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5368 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5369 default: return 1;
5371 break;
5372 case 23: /* VNEG */
5373 if (size == 3)
5374 return 1;
5375 tmp2 = tcg_const_i32(0);
5376 gen_neon_rsb(size, tmp, tmp2);
5377 tcg_temp_free(tmp2);
5378 break;
5379 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5380 tmp2 = tcg_const_i32(0);
5381 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5382 tcg_temp_free(tmp2);
5383 if (op == 27)
5384 tcg_gen_not_i32(tmp, tmp);
5385 break;
5386 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5387 tmp2 = tcg_const_i32(0);
5388 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5389 tcg_temp_free(tmp2);
5390 if (op == 28)
5391 tcg_gen_not_i32(tmp, tmp);
5392 break;
5393 case 26: /* Float VCEQ #0 */
5394 tmp2 = tcg_const_i32(0);
5395 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5396 tcg_temp_free(tmp2);
5397 break;
5398 case 30: /* Float VABS */
5399 gen_vfp_abs(0);
5400 break;
5401 case 31: /* Float VNEG */
5402 gen_vfp_neg(0);
5403 break;
5404 case 32: /* VSWP */
5405 tmp2 = neon_load_reg(rd, pass);
5406 neon_store_reg(rm, pass, tmp2);
5407 break;
5408 case 33: /* VTRN */
5409 tmp2 = neon_load_reg(rd, pass);
5410 switch (size) {
5411 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5412 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5413 case 2: abort();
5414 default: return 1;
5416 neon_store_reg(rm, pass, tmp2);
5417 break;
5418 case 56: /* Integer VRECPE */
5419 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5420 break;
5421 case 57: /* Integer VRSQRTE */
5422 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5423 break;
5424 case 58: /* Float VRECPE */
5425 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5426 break;
5427 case 59: /* Float VRSQRTE */
5428 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5429 break;
5430 case 60: /* VCVT.F32.S32 */
5431 gen_vfp_tosiz(0);
5432 break;
5433 case 61: /* VCVT.F32.U32 */
5434 gen_vfp_touiz(0);
5435 break;
5436 case 62: /* VCVT.S32.F32 */
5437 gen_vfp_sito(0);
5438 break;
5439 case 63: /* VCVT.U32.F32 */
5440 gen_vfp_uito(0);
5441 break;
5442 default:
5443 /* Reserved: 21, 29, 39-56 */
5444 return 1;
5446 if (op == 30 || op == 31 || op >= 58) {
5447 tcg_gen_st_f32(cpu_F0s, cpu_env,
5448 neon_reg_offset(rd, pass));
5449 } else {
5450 neon_store_reg(rd, pass, tmp);
5453 break;
5455 } else if ((insn & (1 << 10)) == 0) {
5456 /* VTBL, VTBX. */
5457 n = ((insn >> 5) & 0x18) + 8;
5458 if (insn & (1 << 6)) {
5459 tmp = neon_load_reg(rd, 0);
5460 } else {
5461 tmp = new_tmp();
5462 tcg_gen_movi_i32(tmp, 0);
5464 tmp2 = neon_load_reg(rm, 0);
5465 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5466 tcg_const_i32(n));
5467 dead_tmp(tmp);
5468 if (insn & (1 << 6)) {
5469 tmp = neon_load_reg(rd, 1);
5470 } else {
5471 tmp = new_tmp();
5472 tcg_gen_movi_i32(tmp, 0);
5474 tmp3 = neon_load_reg(rm, 1);
5475 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5476 tcg_const_i32(n));
5477 neon_store_reg(rd, 0, tmp2);
5478 neon_store_reg(rd, 1, tmp3);
5479 dead_tmp(tmp);
5480 } else if ((insn & 0x380) == 0) {
5481 /* VDUP */
5482 if (insn & (1 << 19)) {
5483 tmp = neon_load_reg(rm, 1);
5484 } else {
5485 tmp = neon_load_reg(rm, 0);
5487 if (insn & (1 << 16)) {
5488 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5489 } else if (insn & (1 << 17)) {
5490 if ((insn >> 18) & 1)
5491 gen_neon_dup_high16(tmp);
5492 else
5493 gen_neon_dup_low16(tmp);
5495 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5496 tmp2 = new_tmp();
5497 tcg_gen_mov_i32(tmp2, tmp);
5498 neon_store_reg(rd, pass, tmp2);
5500 dead_tmp(tmp);
5501 } else {
5502 return 1;
5506 return 0;
5509 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5511 int crn = (insn >> 16) & 0xf;
5512 int crm = insn & 0xf;
5513 int op1 = (insn >> 21) & 7;
5514 int op2 = (insn >> 5) & 7;
5515 int rt = (insn >> 12) & 0xf;
5516 TCGv tmp;
5518 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5519 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5520 /* TEECR */
5521 if (IS_USER(s))
5522 return 1;
5523 tmp = load_cpu_field(teecr);
5524 store_reg(s, rt, tmp);
5525 return 0;
5527 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5528 /* TEEHBR */
5529 if (IS_USER(s) && (env->teecr & 1))
5530 return 1;
5531 tmp = load_cpu_field(teehbr);
5532 store_reg(s, rt, tmp);
5533 return 0;
5536 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5537 op1, crn, crm, op2);
5538 return 1;
5541 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5543 int crn = (insn >> 16) & 0xf;
5544 int crm = insn & 0xf;
5545 int op1 = (insn >> 21) & 7;
5546 int op2 = (insn >> 5) & 7;
5547 int rt = (insn >> 12) & 0xf;
5548 TCGv tmp;
5550 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5551 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5552 /* TEECR */
5553 if (IS_USER(s))
5554 return 1;
5555 tmp = load_reg(s, rt);
5556 gen_helper_set_teecr(cpu_env, tmp);
5557 dead_tmp(tmp);
5558 return 0;
5560 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5561 /* TEEHBR */
5562 if (IS_USER(s) && (env->teecr & 1))
5563 return 1;
5564 tmp = load_reg(s, rt);
5565 store_cpu_field(tmp, teehbr);
5566 return 0;
5569 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5570 op1, crn, crm, op2);
5571 return 1;
5574 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5576 int cpnum;
5578 cpnum = (insn >> 8) & 0xf;
5579 if (arm_feature(env, ARM_FEATURE_XSCALE)
5580 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5581 return 1;
5583 switch (cpnum) {
5584 case 0:
5585 case 1:
5586 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5587 return disas_iwmmxt_insn(env, s, insn);
5588 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5589 return disas_dsp_insn(env, s, insn);
5591 return 1;
5592 case 10:
5593 case 11:
5594 return disas_vfp_insn (env, s, insn);
5595 case 14:
5596 /* Coprocessors 7-15 are architecturally reserved by ARM.
5597 Unfortunately Intel decided to ignore this. */
5598 if (arm_feature(env, ARM_FEATURE_XSCALE))
5599 goto board;
5600 if (insn & (1 << 20))
5601 return disas_cp14_read(env, s, insn);
5602 else
5603 return disas_cp14_write(env, s, insn);
5604 case 15:
5605 return disas_cp15_insn (env, s, insn);
5606 default:
5607 board:
5608 /* Unknown coprocessor. See if the board has hooked it. */
5609 return disas_cp_insn (env, s, insn);
5614 /* Store a 64-bit value to a register pair. Clobbers val. */
5615 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5617 TCGv tmp;
5618 tmp = new_tmp();
5619 tcg_gen_trunc_i64_i32(tmp, val);
5620 store_reg(s, rlow, tmp);
5621 tmp = new_tmp();
5622 tcg_gen_shri_i64(val, val, 32);
5623 tcg_gen_trunc_i64_i32(tmp, val);
5624 store_reg(s, rhigh, tmp);
5627 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5628 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5630 TCGv_i64 tmp;
5631 TCGv tmp2;
5633 /* Load value and extend to 64 bits. */
5634 tmp = tcg_temp_new_i64();
5635 tmp2 = load_reg(s, rlow);
5636 tcg_gen_extu_i32_i64(tmp, tmp2);
5637 dead_tmp(tmp2);
5638 tcg_gen_add_i64(val, val, tmp);
5641 /* load and add a 64-bit value from a register pair. */
5642 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5644 TCGv_i64 tmp;
5645 TCGv tmpl;
5646 TCGv tmph;
5648 /* Load 64-bit value rd:rn. */
5649 tmpl = load_reg(s, rlow);
5650 tmph = load_reg(s, rhigh);
5651 tmp = tcg_temp_new_i64();
5652 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5653 dead_tmp(tmpl);
5654 dead_tmp(tmph);
5655 tcg_gen_add_i64(val, val, tmp);
5658 /* Set N and Z flags from a 64-bit value. */
5659 static void gen_logicq_cc(TCGv_i64 val)
5661 TCGv tmp = new_tmp();
5662 gen_helper_logicq_cc(tmp, val);
5663 gen_logic_CC(tmp);
5664 dead_tmp(tmp);
5667 static void disas_arm_insn(CPUState * env, DisasContext *s)
5669 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5670 TCGv tmp;
5671 TCGv tmp2;
5672 TCGv tmp3;
5673 TCGv addr;
5674 TCGv_i64 tmp64;
5676 insn = ldl_code(s->pc);
5677 s->pc += 4;
5679 /* M variants do not implement ARM mode. */
5680 if (IS_M(env))
5681 goto illegal_op;
5682 cond = insn >> 28;
5683 if (cond == 0xf){
5684 /* Unconditional instructions. */
5685 if (((insn >> 25) & 7) == 1) {
5686 /* NEON Data processing. */
5687 if (!arm_feature(env, ARM_FEATURE_NEON))
5688 goto illegal_op;
5690 if (disas_neon_data_insn(env, s, insn))
5691 goto illegal_op;
5692 return;
5694 if ((insn & 0x0f100000) == 0x04000000) {
5695 /* NEON load/store. */
5696 if (!arm_feature(env, ARM_FEATURE_NEON))
5697 goto illegal_op;
5699 if (disas_neon_ls_insn(env, s, insn))
5700 goto illegal_op;
5701 return;
5703 if ((insn & 0x0d70f000) == 0x0550f000) {
5704 ARCH(5);
5705 return; /* PLD */
5706 } else if ((insn & 0x0ffffdff) == 0x01010000) {
5707 ARCH(6);
5708 /* setend */
5709 if (insn & (1 << 9)) {
5710 /* BE8 mode not implemented. */
5711 goto illegal_op;
5713 return;
5714 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5715 switch ((insn >> 4) & 0xf) {
5716 case 1: /* clrex */
5717 ARCH(6K);
5718 gen_helper_clrex(cpu_env);
5719 return;
5720 case 4: /* dsb */
5721 case 5: /* dmb */
5722 case 6: /* isb */
5723 ARCH(7);
5724 /* We don't emulate caches so these are a no-op. */
5725 return;
5726 default:
5727 goto illegal_op;
5729 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5730 /* srs */
5731 int32_t offset;
5732 if (IS_USER(s))
5733 goto illegal_op;
5734 ARCH(6);
5735 op1 = (insn & 0x1f);
5736 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5737 addr = load_reg(s, 13);
5738 } else {
5739 addr = new_tmp();
5740 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5742 i = (insn >> 23) & 3;
5743 switch (i) {
5744 case 0: offset = -4; break; /* DA */
5745 case 1: offset = 0; break; /* IA */
5746 case 2: offset = -8; break; /* DB */
5747 case 3: offset = 4; break; /* IB */
5748 default: abort();
5750 if (offset)
5751 tcg_gen_addi_i32(addr, addr, offset);
5752 tmp = load_reg(s, 14);
5753 gen_st32(tmp, addr, 0);
5754 tmp = load_cpu_field(spsr);
5755 tcg_gen_addi_i32(addr, addr, 4);
5756 gen_st32(tmp, addr, 0);
5757 if (insn & (1 << 21)) {
5758 /* Base writeback. */
5759 switch (i) {
5760 case 0: offset = -8; break;
5761 case 1: offset = 4; break;
5762 case 2: offset = -4; break;
5763 case 3: offset = 0; break;
5764 default: abort();
5766 if (offset)
5767 tcg_gen_addi_i32(addr, addr, offset);
5768 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5769 store_reg(s, 13, addr);
5770 } else {
5771 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5772 dead_tmp(addr);
5774 } else {
5775 dead_tmp(addr);
5777 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5778 /* rfe */
5779 int32_t offset;
5780 if (IS_USER(s))
5781 goto illegal_op;
5782 ARCH(6);
5783 rn = (insn >> 16) & 0xf;
5784 addr = load_reg(s, rn);
5785 i = (insn >> 23) & 3;
5786 switch (i) {
5787 case 0: offset = -4; break; /* DA */
5788 case 1: offset = 0; break; /* IA */
5789 case 2: offset = -8; break; /* DB */
5790 case 3: offset = 4; break; /* IB */
5791 default: abort();
5793 if (offset)
5794 tcg_gen_addi_i32(addr, addr, offset);
5795 /* Load PC into tmp and CPSR into tmp2. */
5796 tmp = gen_ld32(addr, 0);
5797 tcg_gen_addi_i32(addr, addr, 4);
5798 tmp2 = gen_ld32(addr, 0);
5799 if (insn & (1 << 21)) {
5800 /* Base writeback. */
5801 switch (i) {
5802 case 0: offset = -8; break;
5803 case 1: offset = 4; break;
5804 case 2: offset = -4; break;
5805 case 3: offset = 0; break;
5806 default: abort();
5808 if (offset)
5809 tcg_gen_addi_i32(addr, addr, offset);
5810 store_reg(s, rn, addr);
5811 } else {
5812 dead_tmp(addr);
5814 gen_rfe(s, tmp, tmp2);
5815 return;
5816 } else if ((insn & 0x0e000000) == 0x0a000000) {
5817 /* branch link and change to thumb (blx <offset>) */
5818 int32_t offset;
5819 ARCH(5);
5820 val = (uint32_t)s->pc;
5821 tmp = new_tmp();
5822 tcg_gen_movi_i32(tmp, val);
5823 store_reg(s, 14, tmp);
5824 /* Sign-extend the 24-bit offset */
5825 offset = (((int32_t)insn) << 8) >> 8;
5826 /* offset * 4 + bit24 * 2 + (thumb bit) */
5827 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5828 /* pipeline offset */
5829 val += 4;
5830 gen_bx_im(s, val);
5831 return;
5832 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5833 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5834 /* iWMMXt register transfer. */
5835 if (env->cp15.c15_cpar & (1 << 1))
5836 if (!disas_iwmmxt_insn(env, s, insn))
5837 return;
5839 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5840 /* Coprocessor double register transfer. */
5841 ARCH(5);
5842 } else if ((insn & 0x0f000010) == 0x0e000010) {
5843 /* Additional coprocessor register transfer. */
5844 ARCH(5);
5845 } else if ((insn & 0x0ff10020) == 0x01000000) {
5846 uint32_t mask;
5847 uint32_t val;
5848 /* cps (privileged) */
5849 if (IS_USER(s))
5850 return;
5851 mask = val = 0;
5852 if (insn & (1 << 19)) {
5853 if (insn & (1 << 8))
5854 mask |= CPSR_A;
5855 if (insn & (1 << 7))
5856 mask |= CPSR_I;
5857 if (insn & (1 << 6))
5858 mask |= CPSR_F;
5859 if (insn & (1 << 18))
5860 val |= mask;
5862 if (insn & (1 << 17)) {
5863 mask |= CPSR_M;
5864 val |= (insn & 0x1f);
5866 if (mask) {
5867 gen_set_psr_im(s, mask, 0, val);
5869 return;
5871 goto illegal_op;
5873 if (cond != 0xe) {
5874 /* if not always execute, we generate a conditional jump to
5875 next instruction */
5876 s->condlabel = gen_new_label();
5877 gen_test_cc(cond ^ 1, s->condlabel);
5878 s->condjmp = 1;
5880 if ((insn & 0x0f900000) == 0x03000000) {
5881 if ((insn & (1 << 21)) == 0) {
5882 ARCH(6T2);
5883 rd = (insn >> 12) & 0xf;
5884 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5885 if ((insn & (1 << 22)) == 0) {
5886 /* MOVW */
5887 tmp = new_tmp();
5888 tcg_gen_movi_i32(tmp, val);
5889 } else {
5890 /* MOVT */
5891 tmp = load_reg(s, rd);
5892 tcg_gen_ext16u_i32(tmp, tmp);
5893 tcg_gen_ori_i32(tmp, tmp, val << 16);
5895 store_reg(s, rd, tmp);
5896 } else {
5897 if (((insn >> 12) & 0xf) != 0xf)
5898 goto illegal_op;
5899 if (((insn >> 16) & 0xf) == 0) {
5900 gen_nop_hint(s, insn & 0xff);
5901 } else {
5902 /* CPSR = immediate */
5903 val = insn & 0xff;
5904 shift = ((insn >> 8) & 0xf) * 2;
5905 if (shift)
5906 val = (val >> shift) | (val << (32 - shift));
5907 i = ((insn & (1 << 22)) != 0);
5908 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
5909 goto illegal_op;
5912 } else if ((insn & 0x0f900000) == 0x01000000
5913 && (insn & 0x00000090) != 0x00000090) {
5914 /* miscellaneous instructions */
5915 op1 = (insn >> 21) & 3;
5916 sh = (insn >> 4) & 0xf;
5917 rm = insn & 0xf;
5918 switch (sh) {
5919 case 0x0: /* move program status register */
5920 if (op1 & 1) {
5921 /* PSR = reg */
5922 tmp = load_reg(s, rm);
5923 i = ((op1 & 2) != 0);
5924 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
5925 goto illegal_op;
5926 } else {
5927 /* reg = PSR */
5928 rd = (insn >> 12) & 0xf;
5929 if (op1 & 2) {
5930 if (IS_USER(s))
5931 goto illegal_op;
5932 tmp = load_cpu_field(spsr);
5933 } else {
5934 tmp = new_tmp();
5935 gen_helper_cpsr_read(tmp);
5937 store_reg(s, rd, tmp);
5939 break;
5940 case 0x1:
5941 if (op1 == 1) {
5942 /* branch/exchange thumb (bx). */
5943 tmp = load_reg(s, rm);
5944 gen_bx(s, tmp);
5945 } else if (op1 == 3) {
5946 /* clz */
5947 rd = (insn >> 12) & 0xf;
5948 tmp = load_reg(s, rm);
5949 gen_helper_clz(tmp, tmp);
5950 store_reg(s, rd, tmp);
5951 } else {
5952 goto illegal_op;
5954 break;
5955 case 0x2:
5956 if (op1 == 1) {
5957 ARCH(5J); /* bxj */
5958 /* Trivial implementation equivalent to bx. */
5959 tmp = load_reg(s, rm);
5960 gen_bx(s, tmp);
5961 } else {
5962 goto illegal_op;
5964 break;
5965 case 0x3:
5966 if (op1 != 1)
5967 goto illegal_op;
5968 ARCH(5);
5969 /* branch link/exchange thumb (blx) */
5970 tmp = load_reg(s, rm);
5971 tmp2 = new_tmp();
5972 tcg_gen_movi_i32(tmp2, s->pc);
5973 store_reg(s, 14, tmp2);
5974 gen_bx(s, tmp);
5975 break;
5976 case 0x5: /* saturating add/subtract */
5977 rd = (insn >> 12) & 0xf;
5978 rn = (insn >> 16) & 0xf;
5979 tmp = load_reg(s, rm);
5980 tmp2 = load_reg(s, rn);
5981 if (op1 & 2)
5982 gen_helper_double_saturate(tmp2, tmp2);
5983 if (op1 & 1)
5984 gen_helper_sub_saturate(tmp, tmp, tmp2);
5985 else
5986 gen_helper_add_saturate(tmp, tmp, tmp2);
5987 dead_tmp(tmp2);
5988 store_reg(s, rd, tmp);
5989 break;
5990 case 7: /* bkpt */
5991 ARCH(5);
5992 gen_set_condexec(s);
5993 gen_set_pc_im(s->pc - 4);
5994 gen_exception(EXCP_BKPT);
5995 s->is_jmp = DISAS_JUMP;
5996 break;
5997 case 0x8: /* signed multiply */
5998 case 0xa:
5999 case 0xc:
6000 case 0xe:
6001 rs = (insn >> 8) & 0xf;
6002 rn = (insn >> 12) & 0xf;
6003 rd = (insn >> 16) & 0xf;
6004 if (op1 == 1) {
6005 /* (32 * 16) >> 16 */
6006 tmp = load_reg(s, rm);
6007 tmp2 = load_reg(s, rs);
6008 if (sh & 4)
6009 tcg_gen_sari_i32(tmp2, tmp2, 16);
6010 else
6011 gen_sxth(tmp2);
6012 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6013 tcg_gen_shri_i64(tmp64, tmp64, 16);
6014 tmp = new_tmp();
6015 tcg_gen_trunc_i64_i32(tmp, tmp64);
6016 if ((sh & 2) == 0) {
6017 tmp2 = load_reg(s, rn);
6018 gen_helper_add_setq(tmp, tmp, tmp2);
6019 dead_tmp(tmp2);
6021 store_reg(s, rd, tmp);
6022 } else {
6023 /* 16 * 16 */
6024 tmp = load_reg(s, rm);
6025 tmp2 = load_reg(s, rs);
6026 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6027 dead_tmp(tmp2);
6028 if (op1 == 2) {
6029 tmp64 = tcg_temp_new_i64();
6030 tcg_gen_ext_i32_i64(tmp64, tmp);
6031 dead_tmp(tmp);
6032 gen_addq(s, tmp64, rn, rd);
6033 gen_storeq_reg(s, rn, rd, tmp64);
6034 } else {
6035 if (op1 == 0) {
6036 tmp2 = load_reg(s, rn);
6037 gen_helper_add_setq(tmp, tmp, tmp2);
6038 dead_tmp(tmp2);
6040 store_reg(s, rd, tmp);
6043 break;
6044 default:
6045 goto illegal_op;
6047 } else if (((insn & 0x0e000000) == 0 &&
6048 (insn & 0x00000090) != 0x90) ||
6049 ((insn & 0x0e000000) == (1 << 25))) {
6050 int set_cc, logic_cc, shiftop;
6052 op1 = (insn >> 21) & 0xf;
6053 set_cc = (insn >> 20) & 1;
6054 logic_cc = table_logic_cc[op1] & set_cc;
6056 /* data processing instruction */
6057 if (insn & (1 << 25)) {
6058 /* immediate operand */
6059 val = insn & 0xff;
6060 shift = ((insn >> 8) & 0xf) * 2;
6061 if (shift) {
6062 val = (val >> shift) | (val << (32 - shift));
6064 tmp2 = new_tmp();
6065 tcg_gen_movi_i32(tmp2, val);
6066 if (logic_cc && shift) {
6067 gen_set_CF_bit31(tmp2);
6069 } else {
6070 /* register */
6071 rm = (insn) & 0xf;
6072 tmp2 = load_reg(s, rm);
6073 shiftop = (insn >> 5) & 3;
6074 if (!(insn & (1 << 4))) {
6075 shift = (insn >> 7) & 0x1f;
6076 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6077 } else {
6078 rs = (insn >> 8) & 0xf;
6079 tmp = load_reg(s, rs);
6080 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6083 if (op1 != 0x0f && op1 != 0x0d) {
6084 rn = (insn >> 16) & 0xf;
6085 tmp = load_reg(s, rn);
6086 } else {
6087 TCGV_UNUSED(tmp);
6089 rd = (insn >> 12) & 0xf;
6090 switch(op1) {
6091 case 0x00:
6092 tcg_gen_and_i32(tmp, tmp, tmp2);
6093 if (logic_cc) {
6094 gen_logic_CC(tmp);
6096 store_reg_bx(env, s, rd, tmp);
6097 break;
6098 case 0x01:
6099 tcg_gen_xor_i32(tmp, tmp, tmp2);
6100 if (logic_cc) {
6101 gen_logic_CC(tmp);
6103 store_reg_bx(env, s, rd, tmp);
6104 break;
6105 case 0x02:
6106 if (set_cc && rd == 15) {
6107 /* SUBS r15, ... is used for exception return. */
6108 if (IS_USER(s)) {
6109 goto illegal_op;
6111 gen_helper_sub_cc(tmp, tmp, tmp2);
6112 gen_exception_return(s, tmp);
6113 } else {
6114 if (set_cc) {
6115 gen_helper_sub_cc(tmp, tmp, tmp2);
6116 } else {
6117 tcg_gen_sub_i32(tmp, tmp, tmp2);
6119 store_reg_bx(env, s, rd, tmp);
6121 break;
6122 case 0x03:
6123 if (set_cc) {
6124 gen_helper_sub_cc(tmp, tmp2, tmp);
6125 } else {
6126 tcg_gen_sub_i32(tmp, tmp2, tmp);
6128 store_reg_bx(env, s, rd, tmp);
6129 break;
6130 case 0x04:
6131 if (set_cc) {
6132 gen_helper_add_cc(tmp, tmp, tmp2);
6133 } else {
6134 tcg_gen_add_i32(tmp, tmp, tmp2);
6136 store_reg_bx(env, s, rd, tmp);
6137 break;
6138 case 0x05:
6139 if (set_cc) {
6140 gen_helper_adc_cc(tmp, tmp, tmp2);
6141 } else {
6142 gen_add_carry(tmp, tmp, tmp2);
6144 store_reg_bx(env, s, rd, tmp);
6145 break;
6146 case 0x06:
6147 if (set_cc) {
6148 gen_helper_sbc_cc(tmp, tmp, tmp2);
6149 } else {
6150 gen_sub_carry(tmp, tmp, tmp2);
6152 store_reg_bx(env, s, rd, tmp);
6153 break;
6154 case 0x07:
6155 if (set_cc) {
6156 gen_helper_sbc_cc(tmp, tmp2, tmp);
6157 } else {
6158 gen_sub_carry(tmp, tmp2, tmp);
6160 store_reg_bx(env, s, rd, tmp);
6161 break;
6162 case 0x08:
6163 if (set_cc) {
6164 tcg_gen_and_i32(tmp, tmp, tmp2);
6165 gen_logic_CC(tmp);
6167 dead_tmp(tmp);
6168 break;
6169 case 0x09:
6170 if (set_cc) {
6171 tcg_gen_xor_i32(tmp, tmp, tmp2);
6172 gen_logic_CC(tmp);
6174 dead_tmp(tmp);
6175 break;
6176 case 0x0a:
6177 if (set_cc) {
6178 gen_helper_sub_cc(tmp, tmp, tmp2);
6180 dead_tmp(tmp);
6181 break;
6182 case 0x0b:
6183 if (set_cc) {
6184 gen_helper_add_cc(tmp, tmp, tmp2);
6186 dead_tmp(tmp);
6187 break;
6188 case 0x0c:
6189 tcg_gen_or_i32(tmp, tmp, tmp2);
6190 if (logic_cc) {
6191 gen_logic_CC(tmp);
6193 store_reg_bx(env, s, rd, tmp);
6194 break;
6195 case 0x0d:
6196 if (logic_cc && rd == 15) {
6197 /* MOVS r15, ... is used for exception return. */
6198 if (IS_USER(s)) {
6199 goto illegal_op;
6201 gen_exception_return(s, tmp2);
6202 } else {
6203 if (logic_cc) {
6204 gen_logic_CC(tmp2);
6206 store_reg_bx(env, s, rd, tmp2);
6208 break;
6209 case 0x0e:
6210 tcg_gen_bic_i32(tmp, tmp, tmp2);
6211 if (logic_cc) {
6212 gen_logic_CC(tmp);
6214 store_reg_bx(env, s, rd, tmp);
6215 break;
6216 default:
6217 case 0x0f:
6218 tcg_gen_not_i32(tmp2, tmp2);
6219 if (logic_cc) {
6220 gen_logic_CC(tmp2);
6222 store_reg_bx(env, s, rd, tmp2);
6223 break;
6225 if (op1 != 0x0f && op1 != 0x0d) {
6226 dead_tmp(tmp2);
6228 } else {
6229 /* other instructions */
6230 op1 = (insn >> 24) & 0xf;
6231 switch(op1) {
6232 case 0x0:
6233 case 0x1:
6234 /* multiplies, extra load/stores */
6235 sh = (insn >> 5) & 3;
6236 if (sh == 0) {
6237 if (op1 == 0x0) {
6238 rd = (insn >> 16) & 0xf;
6239 rn = (insn >> 12) & 0xf;
6240 rs = (insn >> 8) & 0xf;
6241 rm = (insn) & 0xf;
6242 op1 = (insn >> 20) & 0xf;
6243 switch (op1) {
6244 case 0: case 1: case 2: case 3: case 6:
6245 /* 32 bit mul */
6246 tmp = load_reg(s, rs);
6247 tmp2 = load_reg(s, rm);
6248 tcg_gen_mul_i32(tmp, tmp, tmp2);
6249 dead_tmp(tmp2);
6250 if (insn & (1 << 22)) {
6251 /* Subtract (mls) */
6252 ARCH(6T2);
6253 tmp2 = load_reg(s, rn);
6254 tcg_gen_sub_i32(tmp, tmp2, tmp);
6255 dead_tmp(tmp2);
6256 } else if (insn & (1 << 21)) {
6257 /* Add */
6258 tmp2 = load_reg(s, rn);
6259 tcg_gen_add_i32(tmp, tmp, tmp2);
6260 dead_tmp(tmp2);
6262 if (insn & (1 << 20))
6263 gen_logic_CC(tmp);
6264 store_reg(s, rd, tmp);
6265 break;
6266 default:
6267 /* 64 bit mul */
6268 tmp = load_reg(s, rs);
6269 tmp2 = load_reg(s, rm);
6270 if (insn & (1 << 22))
6271 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6272 else
6273 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6274 if (insn & (1 << 21)) /* mult accumulate */
6275 gen_addq(s, tmp64, rn, rd);
6276 if (!(insn & (1 << 23))) { /* double accumulate */
6277 ARCH(6);
6278 gen_addq_lo(s, tmp64, rn);
6279 gen_addq_lo(s, tmp64, rd);
6281 if (insn & (1 << 20))
6282 gen_logicq_cc(tmp64);
6283 gen_storeq_reg(s, rn, rd, tmp64);
6284 break;
6286 } else {
6287 rn = (insn >> 16) & 0xf;
6288 rd = (insn >> 12) & 0xf;
6289 if (insn & (1 << 23)) {
6290 /* load/store exclusive */
6291 op1 = (insn >> 21) & 0x3;
6292 if (op1)
6293 ARCH(6K);
6294 else
6295 ARCH(6);
6296 addr = tcg_temp_local_new_i32();
6297 tcg_gen_mov_i32(addr, cpu_R[rn]);
6298 if (insn & (1 << 20)) {
6299 gen_helper_mark_exclusive(cpu_env, addr);
6300 switch (op1) {
6301 case 0: /* ldrex */
6302 tmp = gen_ld32(addr, IS_USER(s));
6303 break;
6304 case 1: /* ldrexd */
6305 tmp = gen_ld32(addr, IS_USER(s));
6306 store_reg(s, rd, tmp);
6307 tcg_gen_addi_i32(addr, addr, 4);
6308 tmp = gen_ld32(addr, IS_USER(s));
6309 rd++;
6310 break;
6311 case 2: /* ldrexb */
6312 tmp = gen_ld8u(addr, IS_USER(s));
6313 break;
6314 case 3: /* ldrexh */
6315 tmp = gen_ld16u(addr, IS_USER(s));
6316 break;
6317 default:
6318 abort();
6320 store_reg(s, rd, tmp);
6321 } else {
6322 int label = gen_new_label();
6323 rm = insn & 0xf;
6324 tmp2 = tcg_temp_local_new_i32();
6325 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6326 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6327 tmp = load_reg(s,rm);
6328 switch (op1) {
6329 case 0: /* strex */
6330 gen_st32(tmp, addr, IS_USER(s));
6331 break;
6332 case 1: /* strexd */
6333 gen_st32(tmp, addr, IS_USER(s));
6334 tcg_gen_addi_i32(addr, addr, 4);
6335 tmp = load_reg(s, rm + 1);
6336 gen_st32(tmp, addr, IS_USER(s));
6337 break;
6338 case 2: /* strexb */
6339 gen_st8(tmp, addr, IS_USER(s));
6340 break;
6341 case 3: /* strexh */
6342 gen_st16(tmp, addr, IS_USER(s));
6343 break;
6344 default:
6345 abort();
6347 gen_set_label(label);
6348 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6349 tcg_temp_free(tmp2);
6351 tcg_temp_free(addr);
6352 } else {
6353 /* SWP instruction */
6354 rm = (insn) & 0xf;
6356 /* ??? This is not really atomic. However we know
6357 we never have multiple CPUs running in parallel,
6358 so it is good enough. */
6359 addr = load_reg(s, rn);
6360 tmp = load_reg(s, rm);
6361 if (insn & (1 << 22)) {
6362 tmp2 = gen_ld8u(addr, IS_USER(s));
6363 gen_st8(tmp, addr, IS_USER(s));
6364 } else {
6365 tmp2 = gen_ld32(addr, IS_USER(s));
6366 gen_st32(tmp, addr, IS_USER(s));
6368 dead_tmp(addr);
6369 store_reg(s, rd, tmp2);
6372 } else {
6373 int address_offset;
6374 int load;
6375 /* Misc load/store */
6376 rn = (insn >> 16) & 0xf;
6377 rd = (insn >> 12) & 0xf;
6378 addr = load_reg(s, rn);
6379 if (insn & (1 << 24))
6380 gen_add_datah_offset(s, insn, 0, addr);
6381 address_offset = 0;
6382 if (insn & (1 << 20)) {
6383 /* load */
6384 switch(sh) {
6385 case 1:
6386 tmp = gen_ld16u(addr, IS_USER(s));
6387 break;
6388 case 2:
6389 tmp = gen_ld8s(addr, IS_USER(s));
6390 break;
6391 default:
6392 case 3:
6393 tmp = gen_ld16s(addr, IS_USER(s));
6394 break;
6396 load = 1;
6397 } else if (sh & 2) {
6398 /* doubleword */
6399 if (sh & 1) {
6400 /* store */
6401 tmp = load_reg(s, rd);
6402 gen_st32(tmp, addr, IS_USER(s));
6403 tcg_gen_addi_i32(addr, addr, 4);
6404 tmp = load_reg(s, rd + 1);
6405 gen_st32(tmp, addr, IS_USER(s));
6406 load = 0;
6407 } else {
6408 /* load */
6409 tmp = gen_ld32(addr, IS_USER(s));
6410 store_reg(s, rd, tmp);
6411 tcg_gen_addi_i32(addr, addr, 4);
6412 tmp = gen_ld32(addr, IS_USER(s));
6413 rd++;
6414 load = 1;
6416 address_offset = -4;
6417 } else {
6418 /* store */
6419 tmp = load_reg(s, rd);
6420 gen_st16(tmp, addr, IS_USER(s));
6421 load = 0;
6423 /* Perform base writeback before the loaded value to
6424 ensure correct behavior with overlapping index registers.
6425 ldrd with base writeback is is undefined if the
6426 destination and index registers overlap. */
6427 if (!(insn & (1 << 24))) {
6428 gen_add_datah_offset(s, insn, address_offset, addr);
6429 store_reg(s, rn, addr);
6430 } else if (insn & (1 << 21)) {
6431 if (address_offset)
6432 tcg_gen_addi_i32(addr, addr, address_offset);
6433 store_reg(s, rn, addr);
6434 } else {
6435 dead_tmp(addr);
6437 if (load) {
6438 /* Complete the load. */
6439 store_reg(s, rd, tmp);
6442 break;
6443 case 0x4:
6444 case 0x5:
6445 goto do_ldst;
6446 case 0x6:
6447 case 0x7:
6448 if (insn & (1 << 4)) {
6449 ARCH(6);
6450 /* Armv6 Media instructions. */
6451 rm = insn & 0xf;
6452 rn = (insn >> 16) & 0xf;
6453 rd = (insn >> 12) & 0xf;
6454 rs = (insn >> 8) & 0xf;
6455 switch ((insn >> 23) & 3) {
6456 case 0: /* Parallel add/subtract. */
6457 op1 = (insn >> 20) & 7;
6458 tmp = load_reg(s, rn);
6459 tmp2 = load_reg(s, rm);
6460 sh = (insn >> 5) & 7;
6461 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6462 goto illegal_op;
6463 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6464 dead_tmp(tmp2);
6465 store_reg(s, rd, tmp);
6466 break;
6467 case 1:
6468 if ((insn & 0x00700020) == 0) {
6469 /* Halfword pack. */
6470 tmp = load_reg(s, rn);
6471 tmp2 = load_reg(s, rm);
6472 shift = (insn >> 7) & 0x1f;
6473 if (insn & (1 << 6)) {
6474 /* pkhtb */
6475 if (shift == 0)
6476 shift = 31;
6477 tcg_gen_sari_i32(tmp2, tmp2, shift);
6478 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6479 tcg_gen_ext16u_i32(tmp2, tmp2);
6480 } else {
6481 /* pkhbt */
6482 if (shift)
6483 tcg_gen_shli_i32(tmp2, tmp2, shift);
6484 tcg_gen_ext16u_i32(tmp, tmp);
6485 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6487 tcg_gen_or_i32(tmp, tmp, tmp2);
6488 dead_tmp(tmp2);
6489 store_reg(s, rd, tmp);
6490 } else if ((insn & 0x00200020) == 0x00200000) {
6491 /* [us]sat */
6492 tmp = load_reg(s, rm);
6493 shift = (insn >> 7) & 0x1f;
6494 if (insn & (1 << 6)) {
6495 if (shift == 0)
6496 shift = 31;
6497 tcg_gen_sari_i32(tmp, tmp, shift);
6498 } else {
6499 tcg_gen_shli_i32(tmp, tmp, shift);
6501 sh = (insn >> 16) & 0x1f;
6502 if (sh != 0) {
6503 if (insn & (1 << 22))
6504 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6505 else
6506 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6508 store_reg(s, rd, tmp);
6509 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6510 /* [us]sat16 */
6511 tmp = load_reg(s, rm);
6512 sh = (insn >> 16) & 0x1f;
6513 if (sh != 0) {
6514 if (insn & (1 << 22))
6515 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6516 else
6517 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6519 store_reg(s, rd, tmp);
6520 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6521 /* Select bytes. */
6522 tmp = load_reg(s, rn);
6523 tmp2 = load_reg(s, rm);
6524 tmp3 = new_tmp();
6525 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6526 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6527 dead_tmp(tmp3);
6528 dead_tmp(tmp2);
6529 store_reg(s, rd, tmp);
6530 } else if ((insn & 0x000003e0) == 0x00000060) {
6531 tmp = load_reg(s, rm);
6532 shift = (insn >> 10) & 3;
6533 /* ??? In many cases it's not neccessary to do a
6534 rotate, a shift is sufficient. */
6535 if (shift != 0)
6536 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6537 op1 = (insn >> 20) & 7;
6538 switch (op1) {
6539 case 0: gen_sxtb16(tmp); break;
6540 case 2: gen_sxtb(tmp); break;
6541 case 3: gen_sxth(tmp); break;
6542 case 4: gen_uxtb16(tmp); break;
6543 case 6: gen_uxtb(tmp); break;
6544 case 7: gen_uxth(tmp); break;
6545 default: goto illegal_op;
6547 if (rn != 15) {
6548 tmp2 = load_reg(s, rn);
6549 if ((op1 & 3) == 0) {
6550 gen_add16(tmp, tmp2);
6551 } else {
6552 tcg_gen_add_i32(tmp, tmp, tmp2);
6553 dead_tmp(tmp2);
6556 store_reg(s, rd, tmp);
6557 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6558 /* rev */
6559 tmp = load_reg(s, rm);
6560 if (insn & (1 << 22)) {
6561 if (insn & (1 << 7)) {
6562 gen_revsh(tmp);
6563 } else {
6564 ARCH(6T2);
6565 gen_helper_rbit(tmp, tmp);
6567 } else {
6568 if (insn & (1 << 7))
6569 gen_rev16(tmp);
6570 else
6571 tcg_gen_bswap32_i32(tmp, tmp);
6573 store_reg(s, rd, tmp);
6574 } else {
6575 goto illegal_op;
6577 break;
6578 case 2: /* Multiplies (Type 3). */
6579 tmp = load_reg(s, rm);
6580 tmp2 = load_reg(s, rs);
6581 if (insn & (1 << 20)) {
6582 /* Signed multiply most significant [accumulate]. */
6583 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6584 if (insn & (1 << 5))
6585 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6586 tcg_gen_shri_i64(tmp64, tmp64, 32);
6587 tmp = new_tmp();
6588 tcg_gen_trunc_i64_i32(tmp, tmp64);
6589 if (rd != 15) {
6590 tmp2 = load_reg(s, rd);
6591 if (insn & (1 << 6)) {
6592 tcg_gen_sub_i32(tmp, tmp, tmp2);
6593 } else {
6594 tcg_gen_add_i32(tmp, tmp, tmp2);
6596 dead_tmp(tmp2);
6598 store_reg(s, rn, tmp);
6599 } else {
6600 if (insn & (1 << 5))
6601 gen_swap_half(tmp2);
6602 gen_smul_dual(tmp, tmp2);
6603 /* This addition cannot overflow. */
6604 if (insn & (1 << 6)) {
6605 tcg_gen_sub_i32(tmp, tmp, tmp2);
6606 } else {
6607 tcg_gen_add_i32(tmp, tmp, tmp2);
6609 dead_tmp(tmp2);
6610 if (insn & (1 << 22)) {
6611 /* smlald, smlsld */
6612 tmp64 = tcg_temp_new_i64();
6613 tcg_gen_ext_i32_i64(tmp64, tmp);
6614 dead_tmp(tmp);
6615 gen_addq(s, tmp64, rd, rn);
6616 gen_storeq_reg(s, rd, rn, tmp64);
6617 } else {
6618 /* smuad, smusd, smlad, smlsd */
6619 if (rd != 15)
6621 tmp2 = load_reg(s, rd);
6622 gen_helper_add_setq(tmp, tmp, tmp2);
6623 dead_tmp(tmp2);
6625 store_reg(s, rn, tmp);
6628 break;
6629 case 3:
6630 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6631 switch (op1) {
6632 case 0: /* Unsigned sum of absolute differences. */
6633 ARCH(6);
6634 tmp = load_reg(s, rm);
6635 tmp2 = load_reg(s, rs);
6636 gen_helper_usad8(tmp, tmp, tmp2);
6637 dead_tmp(tmp2);
6638 if (rd != 15) {
6639 tmp2 = load_reg(s, rd);
6640 tcg_gen_add_i32(tmp, tmp, tmp2);
6641 dead_tmp(tmp2);
6643 store_reg(s, rn, tmp);
6644 break;
6645 case 0x20: case 0x24: case 0x28: case 0x2c:
6646 /* Bitfield insert/clear. */
6647 ARCH(6T2);
6648 shift = (insn >> 7) & 0x1f;
6649 i = (insn >> 16) & 0x1f;
6650 i = i + 1 - shift;
6651 if (rm == 15) {
6652 tmp = new_tmp();
6653 tcg_gen_movi_i32(tmp, 0);
6654 } else {
6655 tmp = load_reg(s, rm);
6657 if (i != 32) {
6658 tmp2 = load_reg(s, rd);
6659 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6660 dead_tmp(tmp2);
6662 store_reg(s, rd, tmp);
6663 break;
6664 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6665 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6666 ARCH(6T2);
6667 tmp = load_reg(s, rm);
6668 shift = (insn >> 7) & 0x1f;
6669 i = ((insn >> 16) & 0x1f) + 1;
6670 if (shift + i > 32)
6671 goto illegal_op;
6672 if (i < 32) {
6673 if (op1 & 0x20) {
6674 gen_ubfx(tmp, shift, (1u << i) - 1);
6675 } else {
6676 gen_sbfx(tmp, shift, i);
6679 store_reg(s, rd, tmp);
6680 break;
6681 default:
6682 goto illegal_op;
6684 break;
6686 break;
6688 do_ldst:
6689 /* Check for undefined extension instructions
6690 * per the ARM Bible IE:
6691 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6693 sh = (0xf << 20) | (0xf << 4);
6694 if (op1 == 0x7 && ((insn & sh) == sh))
6696 goto illegal_op;
6698 /* load/store byte/word */
6699 rn = (insn >> 16) & 0xf;
6700 rd = (insn >> 12) & 0xf;
6701 tmp2 = load_reg(s, rn);
6702 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6703 if (insn & (1 << 24))
6704 gen_add_data_offset(s, insn, tmp2);
6705 if (insn & (1 << 20)) {
6706 /* load */
6707 if (insn & (1 << 22)) {
6708 tmp = gen_ld8u(tmp2, i);
6709 } else {
6710 tmp = gen_ld32(tmp2, i);
6712 } else {
6713 /* store */
6714 tmp = load_reg(s, rd);
6715 if (insn & (1 << 22))
6716 gen_st8(tmp, tmp2, i);
6717 else
6718 gen_st32(tmp, tmp2, i);
6720 if (!(insn & (1 << 24))) {
6721 gen_add_data_offset(s, insn, tmp2);
6722 store_reg(s, rn, tmp2);
6723 } else if (insn & (1 << 21)) {
6724 store_reg(s, rn, tmp2);
6725 } else {
6726 dead_tmp(tmp2);
6728 if (insn & (1 << 20)) {
6729 /* Complete the load. */
6730 if (rd == 15 && ENABLE_ARCH_5)
6731 gen_bx(s, tmp);
6732 else
6733 store_reg(s, rd, tmp);
6735 break;
6736 case 0x08:
6737 case 0x09:
6739 int j, n, user, loaded_base;
6740 int crement = 0;
6741 TCGv loaded_var;
6742 /* load/store multiple words */
6743 /* XXX: store correct base if write back */
6744 user = 0;
6745 if (insn & (1 << 22)) {
6746 if (IS_USER(s))
6747 goto illegal_op; /* only usable in supervisor mode */
6749 if ((insn & (1 << 15)) == 0)
6750 user = 1;
6752 rn = (insn >> 16) & 0xf;
6753 addr = load_reg(s, rn);
6755 /* compute total size */
6756 loaded_base = 0;
6757 TCGV_UNUSED(loaded_var);
6758 n = 0;
6759 for(i=0;i<16;i++) {
6760 if (insn & (1 << i))
6761 n++;
6763 /* XXX: test invalid n == 0 case ? */
6764 if (insn & (1 << 23)) {
6765 if (insn & (1 << 24)) {
6766 /* pre increment */
6767 tcg_gen_addi_i32(addr, addr, 4);
6768 } else {
6769 /* post increment */
6771 } else {
6772 if (insn & (1 << 24)) {
6773 /* pre decrement */
6774 tcg_gen_addi_i32(addr, addr, -(n * 4));
6775 } else {
6776 /* post decrement */
6777 if (n != 1)
6778 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6782 if (insn & (1 << 21)) {
6783 /* write back */
6784 if (insn & (1 << 23)) {
6785 if (insn & (1 << 24)) {
6786 /* pre increment */
6787 } else {
6788 /* post increment */
6789 crement = 4;
6791 } else {
6792 if (insn & (1 << 24)) {
6793 /* pre decrement */
6794 if (n != 1) {
6795 crement = -((n - 1) * 4);
6797 } else {
6798 /* post decrement */
6799 crement = -(n * 4);
6802 if (arm_feature(env, ARM_FEATURE_ABORT_BU)) {
6803 /* base-updated abort model: update base register
6804 before an abort can happen */
6805 crement += (n - 1) * 4;
6806 tmp = new_tmp();
6807 tcg_gen_addi_i32(tmp, addr, crement);
6808 store_reg(s, rn, tmp);
6813 j = 0;
6814 for(i=0;i<16;i++) {
6815 if (insn & (1 << i)) {
6816 if (insn & (1 << 20)) {
6817 /* load */
6818 tmp = gen_ld32(addr, IS_USER(s));
6819 if (i == 15) {
6820 if (ENABLE_ARCH_5) {
6821 gen_bx(s, tmp);
6822 } else {
6823 store_reg(s, i, tmp);
6825 } else if (user) {
6826 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6827 dead_tmp(tmp);
6828 } else if (i == rn) {
6829 loaded_var = tmp;
6830 loaded_base = 1;
6831 } else {
6832 store_reg(s, i, tmp);
6834 } else {
6835 /* store */
6836 if (i == 15) {
6837 /* special case: r15 = PC + 8 */
6838 val = (long)s->pc + 4;
6839 tmp = new_tmp();
6840 tcg_gen_movi_i32(tmp, val);
6841 } else if (user) {
6842 tmp = new_tmp();
6843 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6844 } else {
6845 tmp = load_reg(s, i);
6847 gen_st32(tmp, addr, IS_USER(s));
6849 j++;
6850 /* no need to add after the last transfer */
6851 if (j != n)
6852 tcg_gen_addi_i32(addr, addr, 4);
6855 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << 21))) {
6856 tcg_gen_addi_i32(addr, addr, crement);
6857 store_reg(s, rn, addr);
6858 } else {
6859 dead_tmp(addr);
6861 if (loaded_base) {
6862 store_reg(s, rn, loaded_var);
6864 if ((insn & (1 << 22)) && !user) {
6865 /* Restore CPSR from SPSR. */
6866 tmp = load_cpu_field(spsr);
6867 gen_set_cpsr(tmp, 0xffffffff);
6868 dead_tmp(tmp);
6869 s->is_jmp = DISAS_UPDATE;
6872 break;
6873 case 0xa:
6874 case 0xb:
6876 int32_t offset;
6878 /* branch (and link) */
6879 val = (int32_t)s->pc;
6880 if (insn & (1 << 24)) {
6881 tmp = new_tmp();
6882 tcg_gen_movi_i32(tmp, val);
6883 store_reg(s, 14, tmp);
6885 offset = (((int32_t)insn << 8) >> 8);
6886 val += (offset << 2) + 4;
6887 gen_jmp(s, val);
6889 break;
6890 case 0xc:
6891 case 0xd:
6892 case 0xe:
6893 /* Coprocessor. */
6894 if (disas_coproc_insn(env, s, insn))
6895 goto illegal_op;
6896 break;
6897 case 0xf:
6898 /* swi */
6899 gen_set_pc_im(s->pc);
6900 s->is_jmp = DISAS_SWI;
6901 break;
6902 default:
6903 illegal_op:
6904 gen_set_condexec(s);
6905 gen_set_pc_im(s->pc - 4);
6906 gen_exception(EXCP_UDEF);
6907 s->is_jmp = DISAS_JUMP;
6908 break;
6913 /* Return true if this is a Thumb-2 logical op. */
6914 static int
6915 thumb2_logic_op(int op)
6917 return (op < 8);
6920 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6921 then set condition code flags based on the result of the operation.
6922 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6923 to the high bit of T1.
6924 Returns zero if the opcode is valid. */
6926 static int
6927 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
6929 int logic_cc;
6931 logic_cc = 0;
6932 switch (op) {
6933 case 0: /* and */
6934 tcg_gen_and_i32(t0, t0, t1);
6935 logic_cc = conds;
6936 break;
6937 case 1: /* bic */
6938 tcg_gen_bic_i32(t0, t0, t1);
6939 logic_cc = conds;
6940 break;
6941 case 2: /* orr */
6942 tcg_gen_or_i32(t0, t0, t1);
6943 logic_cc = conds;
6944 break;
6945 case 3: /* orn */
6946 tcg_gen_not_i32(t1, t1);
6947 tcg_gen_or_i32(t0, t0, t1);
6948 logic_cc = conds;
6949 break;
6950 case 4: /* eor */
6951 tcg_gen_xor_i32(t0, t0, t1);
6952 logic_cc = conds;
6953 break;
6954 case 8: /* add */
6955 if (conds)
6956 gen_helper_add_cc(t0, t0, t1);
6957 else
6958 tcg_gen_add_i32(t0, t0, t1);
6959 break;
6960 case 10: /* adc */
6961 if (conds)
6962 gen_helper_adc_cc(t0, t0, t1);
6963 else
6964 gen_add_carry(t0, t0, t1);
6965 break;
6966 case 11: /* sbc */
6967 if (conds)
6968 gen_helper_sbc_cc(t0, t0, t1);
6969 else
6970 gen_sub_carry(t0, t0, t1);
6971 break;
6972 case 13: /* sub */
6973 if (conds)
6974 gen_helper_sub_cc(t0, t0, t1);
6975 else
6976 tcg_gen_sub_i32(t0, t0, t1);
6977 break;
6978 case 14: /* rsb */
6979 if (conds)
6980 gen_helper_sub_cc(t0, t1, t0);
6981 else
6982 tcg_gen_sub_i32(t0, t1, t0);
6983 break;
6984 default: /* 5, 6, 7, 9, 12, 15. */
6985 return 1;
6987 if (logic_cc) {
6988 gen_logic_CC(t0);
6989 if (shifter_out)
6990 gen_set_CF_bit31(t1);
6992 return 0;
6995 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6996 is not legal. */
6997 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6999 uint32_t insn, imm, shift, offset;
7000 uint32_t rd, rn, rm, rs;
7001 TCGv tmp;
7002 TCGv tmp2;
7003 TCGv tmp3;
7004 TCGv addr;
7005 TCGv_i64 tmp64;
7006 int op;
7007 int shiftop;
7008 int conds;
7009 int logic_cc;
7011 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7012 || arm_feature (env, ARM_FEATURE_M))) {
7013 /* Thumb-1 cores may need to treat bl and blx as a pair of
7014 16-bit instructions to get correct prefetch abort behavior. */
7015 insn = insn_hw1;
7016 if ((insn & (1 << 12)) == 0) {
7017 ARCH(5);
7018 /* Second half of blx. */
7019 offset = ((insn & 0x7ff) << 1);
7020 tmp = load_reg(s, 14);
7021 tcg_gen_addi_i32(tmp, tmp, offset);
7022 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7024 tmp2 = new_tmp();
7025 tcg_gen_movi_i32(tmp2, s->pc | 1);
7026 store_reg(s, 14, tmp2);
7027 gen_bx(s, tmp);
7028 return 0;
7030 if (insn & (1 << 11)) {
7031 /* Second half of bl. */
7032 offset = ((insn & 0x7ff) << 1) | 1;
7033 tmp = load_reg(s, 14);
7034 tcg_gen_addi_i32(tmp, tmp, offset);
7036 tmp2 = new_tmp();
7037 tcg_gen_movi_i32(tmp2, s->pc | 1);
7038 store_reg(s, 14, tmp2);
7039 gen_bx(s, tmp);
7040 return 0;
7042 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7043 /* Instruction spans a page boundary. Implement it as two
7044 16-bit instructions in case the second half causes an
7045 prefetch abort. */
7046 offset = ((int32_t)insn << 21) >> 9;
7047 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7048 return 0;
7050 /* Fall through to 32-bit decode. */
7053 insn = lduw_code(s->pc);
7054 s->pc += 2;
7055 insn |= (uint32_t)insn_hw1 << 16;
7057 if ((insn & 0xf800e800) != 0xf000e800) {
7058 ARCH(6T2);
7061 rn = (insn >> 16) & 0xf;
7062 rs = (insn >> 12) & 0xf;
7063 rd = (insn >> 8) & 0xf;
7064 rm = insn & 0xf;
7065 switch ((insn >> 25) & 0xf) {
7066 case 0: case 1: case 2: case 3:
7067 /* 16-bit instructions. Should never happen. */
7068 abort();
7069 case 4:
7070 if (insn & (1 << 22)) {
7071 /* Other load/store, table branch. */
7072 if (insn & 0x01200000) {
7073 /* Load/store doubleword. */
7074 ARCH(5);
7075 if (rn == 15) {
7076 addr = new_tmp();
7077 tcg_gen_movi_i32(addr, s->pc & ~3);
7078 } else {
7079 addr = load_reg(s, rn);
7081 offset = (insn & 0xff) * 4;
7082 if ((insn & (1 << 23)) == 0)
7083 offset = -offset;
7084 if (insn & (1 << 24)) {
7085 tcg_gen_addi_i32(addr, addr, offset);
7086 offset = 0;
7088 if (insn & (1 << 20)) {
7089 /* ldrd */
7090 tmp = gen_ld32(addr, IS_USER(s));
7091 store_reg(s, rs, tmp);
7092 tcg_gen_addi_i32(addr, addr, 4);
7093 tmp = gen_ld32(addr, IS_USER(s));
7094 store_reg(s, rd, tmp);
7095 } else {
7096 /* strd */
7097 tmp = load_reg(s, rs);
7098 gen_st32(tmp, addr, IS_USER(s));
7099 tcg_gen_addi_i32(addr, addr, 4);
7100 tmp = load_reg(s, rd);
7101 gen_st32(tmp, addr, IS_USER(s));
7103 if (insn & (1 << 21)) {
7104 /* Base writeback. */
7105 if (rn == 15)
7106 goto illegal_op;
7107 tcg_gen_addi_i32(addr, addr, offset - 4);
7108 store_reg(s, rn, addr);
7109 } else {
7110 dead_tmp(addr);
7112 } else if ((insn & (1 << 23)) == 0) {
7113 /* Load/store exclusive word. */
7114 addr = tcg_temp_local_new();
7115 tcg_gen_mov_i32(addr, cpu_R[rn]);
7116 if (insn & (1 << 20)) {
7117 gen_helper_mark_exclusive(cpu_env, addr);
7118 tmp = gen_ld32(addr, IS_USER(s));
7119 store_reg(s, rd, tmp);
7120 } else {
7121 int label = gen_new_label();
7122 tmp2 = tcg_temp_local_new();
7123 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7124 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7125 tmp = load_reg(s, rs);
7126 gen_st32(tmp, addr, IS_USER(s));
7127 gen_set_label(label);
7128 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7129 tcg_temp_free(tmp2);
7131 tcg_temp_free(addr);
7132 } else if ((insn & (1 << 6)) == 0) {
7133 /* Table Branch. */
7134 if (rn == 15) {
7135 addr = new_tmp();
7136 tcg_gen_movi_i32(addr, s->pc);
7137 } else {
7138 addr = load_reg(s, rn);
7140 tmp = load_reg(s, rm);
7141 tcg_gen_add_i32(addr, addr, tmp);
7142 if (insn & (1 << 4)) {
7143 /* tbh */
7144 tcg_gen_add_i32(addr, addr, tmp);
7145 dead_tmp(tmp);
7146 tmp = gen_ld16u(addr, IS_USER(s));
7147 } else { /* tbb */
7148 dead_tmp(tmp);
7149 tmp = gen_ld8u(addr, IS_USER(s));
7151 dead_tmp(addr);
7152 tcg_gen_shli_i32(tmp, tmp, 1);
7153 tcg_gen_addi_i32(tmp, tmp, s->pc);
7154 store_reg(s, 15, tmp);
7155 } else {
7156 /* Load/store exclusive byte/halfword/doubleword. */
7157 /* ??? These are not really atomic. However we know
7158 we never have multiple CPUs running in parallel,
7159 so it is good enough. */
7160 op = (insn >> 4) & 0x3;
7161 addr = tcg_temp_local_new();
7162 tcg_gen_mov_i32(addr, cpu_R[rn]);
7163 if (insn & (1 << 20)) {
7164 gen_helper_mark_exclusive(cpu_env, addr);
7165 switch (op) {
7166 case 0:
7167 tmp = gen_ld8u(addr, IS_USER(s));
7168 break;
7169 case 1:
7170 tmp = gen_ld16u(addr, IS_USER(s));
7171 break;
7172 case 3:
7173 tmp = gen_ld32(addr, IS_USER(s));
7174 tcg_gen_addi_i32(addr, addr, 4);
7175 tmp2 = gen_ld32(addr, IS_USER(s));
7176 store_reg(s, rd, tmp2);
7177 break;
7178 default:
7179 goto illegal_op;
7181 store_reg(s, rs, tmp);
7182 } else {
7183 int label = gen_new_label();
7184 tmp2 = tcg_temp_local_new();
7185 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7186 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7187 tmp = load_reg(s, rs);
7188 switch (op) {
7189 case 0:
7190 gen_st8(tmp, addr, IS_USER(s));
7191 break;
7192 case 1:
7193 gen_st16(tmp, addr, IS_USER(s));
7194 break;
7195 case 3:
7196 gen_st32(tmp, addr, IS_USER(s));
7197 tcg_gen_addi_i32(addr, addr, 4);
7198 tmp = load_reg(s, rd);
7199 gen_st32(tmp, addr, IS_USER(s));
7200 break;
7201 default:
7202 goto illegal_op;
7204 gen_set_label(label);
7205 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7206 tcg_temp_free(tmp2);
7208 tcg_temp_free(addr);
7210 } else {
7211 /* Load/store multiple, RFE, SRS. */
7212 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7213 /* Not available in user mode. */
7214 if (IS_USER(s))
7215 goto illegal_op;
7216 if (insn & (1 << 20)) {
7217 /* rfe */
7218 addr = load_reg(s, rn);
7219 if ((insn & (1 << 24)) == 0)
7220 tcg_gen_addi_i32(addr, addr, -8);
7221 /* Load PC into tmp and CPSR into tmp2. */
7222 tmp = gen_ld32(addr, 0);
7223 tcg_gen_addi_i32(addr, addr, 4);
7224 tmp2 = gen_ld32(addr, 0);
7225 if (insn & (1 << 21)) {
7226 /* Base writeback. */
7227 if (insn & (1 << 24)) {
7228 tcg_gen_addi_i32(addr, addr, 4);
7229 } else {
7230 tcg_gen_addi_i32(addr, addr, -4);
7232 store_reg(s, rn, addr);
7233 } else {
7234 dead_tmp(addr);
7236 gen_rfe(s, tmp, tmp2);
7237 } else {
7238 /* srs */
7239 op = (insn & 0x1f);
7240 if (op == (env->uncached_cpsr & CPSR_M)) {
7241 addr = load_reg(s, 13);
7242 } else {
7243 addr = new_tmp();
7244 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7246 if ((insn & (1 << 24)) == 0) {
7247 tcg_gen_addi_i32(addr, addr, -8);
7249 tmp = load_reg(s, 14);
7250 gen_st32(tmp, addr, 0);
7251 tcg_gen_addi_i32(addr, addr, 4);
7252 tmp = new_tmp();
7253 gen_helper_cpsr_read(tmp);
7254 gen_st32(tmp, addr, 0);
7255 if (insn & (1 << 21)) {
7256 if ((insn & (1 << 24)) == 0) {
7257 tcg_gen_addi_i32(addr, addr, -4);
7258 } else {
7259 tcg_gen_addi_i32(addr, addr, 4);
7261 if (op == (env->uncached_cpsr & CPSR_M)) {
7262 store_reg(s, 13, addr);
7263 } else {
7264 gen_helper_set_r13_banked(cpu_env,
7265 tcg_const_i32(op), addr);
7267 } else {
7268 dead_tmp(addr);
7271 } else {
7272 int i;
7273 /* Load/store multiple. */
7274 addr = load_reg(s, rn);
7275 offset = 0;
7276 for (i = 0; i < 16; i++) {
7277 if (insn & (1 << i))
7278 offset += 4;
7280 if (insn & (1 << 24)) {
7281 tcg_gen_addi_i32(addr, addr, -offset);
7284 for (i = 0; i < 16; i++) {
7285 if ((insn & (1 << i)) == 0)
7286 continue;
7287 if (insn & (1 << 20)) {
7288 /* Load. */
7289 tmp = gen_ld32(addr, IS_USER(s));
7290 if (i == 15 && ENABLE_ARCH_5) {
7291 gen_bx(s, tmp);
7292 } else {
7293 store_reg(s, i, tmp);
7295 } else {
7296 /* Store. */
7297 tmp = load_reg(s, i);
7298 gen_st32(tmp, addr, IS_USER(s));
7300 tcg_gen_addi_i32(addr, addr, 4);
7302 if (insn & (1 << 21)) {
7303 /* Base register writeback. */
7304 if (insn & (1 << 24)) {
7305 tcg_gen_addi_i32(addr, addr, -offset);
7307 /* Fault if writeback register is in register list. */
7308 if (insn & (1 << rn))
7309 goto illegal_op;
7310 store_reg(s, rn, addr);
7311 } else {
7312 dead_tmp(addr);
7316 break;
7317 case 5: /* Data processing register constant shift. */
7318 if (rn == 15) {
7319 tmp = new_tmp();
7320 tcg_gen_movi_i32(tmp, 0);
7321 } else {
7322 tmp = load_reg(s, rn);
7324 tmp2 = load_reg(s, rm);
7325 op = (insn >> 21) & 0xf;
7326 shiftop = (insn >> 4) & 3;
7327 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7328 conds = (insn & (1 << 20)) != 0;
7329 logic_cc = (conds && thumb2_logic_op(op));
7330 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7331 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7332 goto illegal_op;
7333 dead_tmp(tmp2);
7334 if (rd != 15) {
7335 store_reg(s, rd, tmp);
7336 } else {
7337 dead_tmp(tmp);
7339 break;
7340 case 13: /* Misc data processing. */
7341 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7342 if (op < 4 && (insn & 0xf000) != 0xf000)
7343 goto illegal_op;
7344 switch (op) {
7345 case 0: /* Register controlled shift. */
7346 tmp = load_reg(s, rn);
7347 tmp2 = load_reg(s, rm);
7348 if ((insn & 0x70) != 0)
7349 goto illegal_op;
7350 op = (insn >> 21) & 3;
7351 logic_cc = (insn & (1 << 20)) != 0;
7352 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7353 if (logic_cc)
7354 gen_logic_CC(tmp);
7355 store_reg_bx(env, s, rd, tmp);
7356 break;
7357 case 1: /* Sign/zero extend. */
7358 tmp = load_reg(s, rm);
7359 shift = (insn >> 4) & 3;
7360 /* ??? In many cases it's not neccessary to do a
7361 rotate, a shift is sufficient. */
7362 if (shift != 0)
7363 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7364 op = (insn >> 20) & 7;
7365 switch (op) {
7366 case 0: gen_sxth(tmp); break;
7367 case 1: gen_uxth(tmp); break;
7368 case 2: gen_sxtb16(tmp); break;
7369 case 3: gen_uxtb16(tmp); break;
7370 case 4: gen_sxtb(tmp); break;
7371 case 5: gen_uxtb(tmp); break;
7372 default: goto illegal_op;
7374 if (rn != 15) {
7375 tmp2 = load_reg(s, rn);
7376 if ((op >> 1) == 1) {
7377 gen_add16(tmp, tmp2);
7378 } else {
7379 tcg_gen_add_i32(tmp, tmp, tmp2);
7380 dead_tmp(tmp2);
7383 store_reg(s, rd, tmp);
7384 break;
7385 case 2: /* SIMD add/subtract. */
7386 op = (insn >> 20) & 7;
7387 shift = (insn >> 4) & 7;
7388 if ((op & 3) == 3 || (shift & 3) == 3)
7389 goto illegal_op;
7390 tmp = load_reg(s, rn);
7391 tmp2 = load_reg(s, rm);
7392 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7393 dead_tmp(tmp2);
7394 store_reg(s, rd, tmp);
7395 break;
7396 case 3: /* Other data processing. */
7397 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7398 if (op < 4) {
7399 /* Saturating add/subtract. */
7400 tmp = load_reg(s, rn);
7401 tmp2 = load_reg(s, rm);
7402 if (op & 2)
7403 gen_helper_double_saturate(tmp, tmp);
7404 if (op & 1)
7405 gen_helper_sub_saturate(tmp, tmp2, tmp);
7406 else
7407 gen_helper_add_saturate(tmp, tmp, tmp2);
7408 dead_tmp(tmp2);
7409 } else {
7410 tmp = load_reg(s, rn);
7411 switch (op) {
7412 case 0x0a: /* rbit */
7413 gen_helper_rbit(tmp, tmp);
7414 break;
7415 case 0x08: /* rev */
7416 tcg_gen_bswap32_i32(tmp, tmp);
7417 break;
7418 case 0x09: /* rev16 */
7419 gen_rev16(tmp);
7420 break;
7421 case 0x0b: /* revsh */
7422 gen_revsh(tmp);
7423 break;
7424 case 0x10: /* sel */
7425 tmp2 = load_reg(s, rm);
7426 tmp3 = new_tmp();
7427 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7428 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7429 dead_tmp(tmp3);
7430 dead_tmp(tmp2);
7431 break;
7432 case 0x18: /* clz */
7433 gen_helper_clz(tmp, tmp);
7434 break;
7435 default:
7436 goto illegal_op;
7439 store_reg(s, rd, tmp);
7440 break;
7441 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7442 op = (insn >> 4) & 0xf;
7443 tmp = load_reg(s, rn);
7444 tmp2 = load_reg(s, rm);
7445 switch ((insn >> 20) & 7) {
7446 case 0: /* 32 x 32 -> 32 */
7447 tcg_gen_mul_i32(tmp, tmp, tmp2);
7448 dead_tmp(tmp2);
7449 if (rs != 15) {
7450 tmp2 = load_reg(s, rs);
7451 if (op)
7452 tcg_gen_sub_i32(tmp, tmp2, tmp);
7453 else
7454 tcg_gen_add_i32(tmp, tmp, tmp2);
7455 dead_tmp(tmp2);
7457 break;
7458 case 1: /* 16 x 16 -> 32 */
7459 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7460 dead_tmp(tmp2);
7461 if (rs != 15) {
7462 tmp2 = load_reg(s, rs);
7463 gen_helper_add_setq(tmp, tmp, tmp2);
7464 dead_tmp(tmp2);
7466 break;
7467 case 2: /* Dual multiply add. */
7468 case 4: /* Dual multiply subtract. */
7469 if (op)
7470 gen_swap_half(tmp2);
7471 gen_smul_dual(tmp, tmp2);
7472 /* This addition cannot overflow. */
7473 if (insn & (1 << 22)) {
7474 tcg_gen_sub_i32(tmp, tmp, tmp2);
7475 } else {
7476 tcg_gen_add_i32(tmp, tmp, tmp2);
7478 dead_tmp(tmp2);
7479 if (rs != 15)
7481 tmp2 = load_reg(s, rs);
7482 gen_helper_add_setq(tmp, tmp, tmp2);
7483 dead_tmp(tmp2);
7485 break;
7486 case 3: /* 32 * 16 -> 32msb */
7487 if (op)
7488 tcg_gen_sari_i32(tmp2, tmp2, 16);
7489 else
7490 gen_sxth(tmp2);
7491 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7492 tcg_gen_shri_i64(tmp64, tmp64, 16);
7493 tmp = new_tmp();
7494 tcg_gen_trunc_i64_i32(tmp, tmp64);
7495 if (rs != 15)
7497 tmp2 = load_reg(s, rs);
7498 gen_helper_add_setq(tmp, tmp, tmp2);
7499 dead_tmp(tmp2);
7501 break;
7502 case 5: case 6: /* 32 * 32 -> 32msb */
7503 gen_imull(tmp, tmp2);
7504 if (insn & (1 << 5)) {
7505 gen_roundqd(tmp, tmp2);
7506 dead_tmp(tmp2);
7507 } else {
7508 dead_tmp(tmp);
7509 tmp = tmp2;
7511 if (rs != 15) {
7512 tmp2 = load_reg(s, rs);
7513 if (insn & (1 << 21)) {
7514 tcg_gen_add_i32(tmp, tmp, tmp2);
7515 } else {
7516 tcg_gen_sub_i32(tmp, tmp2, tmp);
7518 dead_tmp(tmp2);
7520 break;
7521 case 7: /* Unsigned sum of absolute differences. */
7522 gen_helper_usad8(tmp, tmp, tmp2);
7523 dead_tmp(tmp2);
7524 if (rs != 15) {
7525 tmp2 = load_reg(s, rs);
7526 tcg_gen_add_i32(tmp, tmp, tmp2);
7527 dead_tmp(tmp2);
7529 break;
7531 store_reg(s, rd, tmp);
7532 break;
7533 case 6: case 7: /* 64-bit multiply, Divide. */
7534 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7535 tmp = load_reg(s, rn);
7536 tmp2 = load_reg(s, rm);
7537 if ((op & 0x50) == 0x10) {
7538 /* sdiv, udiv */
7539 if (!arm_feature(env, ARM_FEATURE_DIV))
7540 goto illegal_op;
7541 if (op & 0x20)
7542 gen_helper_udiv(tmp, tmp, tmp2);
7543 else
7544 gen_helper_sdiv(tmp, tmp, tmp2);
7545 dead_tmp(tmp2);
7546 store_reg(s, rd, tmp);
7547 } else if ((op & 0xe) == 0xc) {
7548 /* Dual multiply accumulate long. */
7549 if (op & 1)
7550 gen_swap_half(tmp2);
7551 gen_smul_dual(tmp, tmp2);
7552 if (op & 0x10) {
7553 tcg_gen_sub_i32(tmp, tmp, tmp2);
7554 } else {
7555 tcg_gen_add_i32(tmp, tmp, tmp2);
7557 dead_tmp(tmp2);
7558 /* BUGFIX */
7559 tmp64 = tcg_temp_new_i64();
7560 tcg_gen_ext_i32_i64(tmp64, tmp);
7561 dead_tmp(tmp);
7562 gen_addq(s, tmp64, rs, rd);
7563 gen_storeq_reg(s, rs, rd, tmp64);
7564 } else {
7565 if (op & 0x20) {
7566 /* Unsigned 64-bit multiply */
7567 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7568 } else {
7569 if (op & 8) {
7570 /* smlalxy */
7571 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7572 dead_tmp(tmp2);
7573 tmp64 = tcg_temp_new_i64();
7574 tcg_gen_ext_i32_i64(tmp64, tmp);
7575 dead_tmp(tmp);
7576 } else {
7577 /* Signed 64-bit multiply */
7578 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7581 if (op & 4) {
7582 /* umaal */
7583 gen_addq_lo(s, tmp64, rs);
7584 gen_addq_lo(s, tmp64, rd);
7585 } else if (op & 0x40) {
7586 /* 64-bit accumulate. */
7587 gen_addq(s, tmp64, rs, rd);
7589 gen_storeq_reg(s, rs, rd, tmp64);
7591 break;
7593 break;
7594 case 6: case 7: case 14: case 15:
7595 /* Coprocessor. */
7596 if (((insn >> 24) & 3) == 3) {
7597 /* Translate into the equivalent ARM encoding. */
7598 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7599 if (disas_neon_data_insn(env, s, insn))
7600 goto illegal_op;
7601 } else {
7602 if (insn & (1 << 28))
7603 goto illegal_op;
7604 if (disas_coproc_insn (env, s, insn))
7605 goto illegal_op;
7607 break;
7608 case 8: case 9: case 10: case 11:
7609 if (insn & (1 << 15)) {
7610 /* Branches, misc control. */
7611 if (insn & 0x5000) {
7612 /* Unconditional branch. */
7613 /* signextend(hw1[10:0]) -> offset[:12]. */
7614 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7615 /* hw1[10:0] -> offset[11:1]. */
7616 offset |= (insn & 0x7ff) << 1;
7617 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7618 offset[24:22] already have the same value because of the
7619 sign extension above. */
7620 offset ^= ((~insn) & (1 << 13)) << 10;
7621 offset ^= ((~insn) & (1 << 11)) << 11;
7623 if (insn & (1 << 14)) {
7624 /* Branch and link. */
7625 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7628 offset += s->pc;
7629 if (insn & (1 << 12)) {
7630 /* b/bl */
7631 gen_jmp(s, offset);
7632 } else {
7633 /* blx */
7634 ARCH(5);
7635 offset &= ~(uint32_t)2;
7636 gen_bx_im(s, offset);
7638 } else if (((insn >> 23) & 7) == 7) {
7639 /* Misc control */
7640 if (insn & (1 << 13))
7641 goto illegal_op;
7643 if (insn & (1 << 26)) {
7644 /* Secure monitor call (v6Z) */
7645 goto illegal_op; /* not implemented. */
7646 } else {
7647 op = (insn >> 20) & 7;
7648 switch (op) {
7649 case 0: /* msr cpsr. */
7650 if (IS_M(env)) {
7651 tmp = load_reg(s, rn);
7652 addr = tcg_const_i32(insn & 0xff);
7653 gen_helper_v7m_msr(cpu_env, addr, tmp);
7654 gen_lookup_tb(s);
7655 break;
7657 /* fall through */
7658 case 1: /* msr spsr. */
7659 if (IS_M(env))
7660 goto illegal_op;
7661 tmp = load_reg(s, rn);
7662 if (gen_set_psr(s,
7663 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7664 op == 1, tmp))
7665 goto illegal_op;
7666 break;
7667 case 2: /* cps, nop-hint. */
7668 if (((insn >> 8) & 7) == 0) {
7669 gen_nop_hint(s, insn & 0xff);
7671 /* Implemented as NOP in user mode. */
7672 if (IS_USER(s))
7673 break;
7674 offset = 0;
7675 imm = 0;
7676 if (insn & (1 << 10)) {
7677 if (insn & (1 << 7))
7678 offset |= CPSR_A;
7679 if (insn & (1 << 6))
7680 offset |= CPSR_I;
7681 if (insn & (1 << 5))
7682 offset |= CPSR_F;
7683 if (insn & (1 << 9))
7684 imm = CPSR_A | CPSR_I | CPSR_F;
7686 if (insn & (1 << 8)) {
7687 offset |= 0x1f;
7688 imm |= (insn & 0x1f);
7690 if (offset) {
7691 gen_set_psr_im(s, offset, 0, imm);
7693 break;
7694 case 3: /* Special control operations. */
7695 op = (insn >> 4) & 0xf;
7696 switch (op) {
7697 case 2: /* clrex */
7698 gen_helper_clrex(cpu_env);
7699 break;
7700 case 4: /* dsb */
7701 case 5: /* dmb */
7702 case 6: /* isb */
7703 /* These execute as NOPs. */
7704 ARCH(7);
7705 break;
7706 default:
7707 goto illegal_op;
7709 break;
7710 case 4: /* bxj */
7711 /* Trivial implementation equivalent to bx. */
7712 tmp = load_reg(s, rn);
7713 gen_bx(s, tmp);
7714 break;
7715 case 5: /* Exception return. */
7716 /* Unpredictable in user mode. */
7717 goto illegal_op;
7718 case 6: /* mrs cpsr. */
7719 tmp = new_tmp();
7720 if (IS_M(env)) {
7721 addr = tcg_const_i32(insn & 0xff);
7722 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7723 } else {
7724 gen_helper_cpsr_read(tmp);
7726 store_reg(s, rd, tmp);
7727 break;
7728 case 7: /* mrs spsr. */
7729 /* Not accessible in user mode. */
7730 if (IS_USER(s) || IS_M(env))
7731 goto illegal_op;
7732 tmp = load_cpu_field(spsr);
7733 store_reg(s, rd, tmp);
7734 break;
7737 } else {
7738 /* Conditional branch. */
7739 op = (insn >> 22) & 0xf;
7740 /* Generate a conditional jump to next instruction. */
7741 s->condlabel = gen_new_label();
7742 gen_test_cc(op ^ 1, s->condlabel);
7743 s->condjmp = 1;
7745 /* offset[11:1] = insn[10:0] */
7746 offset = (insn & 0x7ff) << 1;
7747 /* offset[17:12] = insn[21:16]. */
7748 offset |= (insn & 0x003f0000) >> 4;
7749 /* offset[31:20] = insn[26]. */
7750 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7751 /* offset[18] = insn[13]. */
7752 offset |= (insn & (1 << 13)) << 5;
7753 /* offset[19] = insn[11]. */
7754 offset |= (insn & (1 << 11)) << 8;
7756 /* jump to the offset */
7757 gen_jmp(s, s->pc + offset);
7759 } else {
7760 /* Data processing immediate. */
7761 if (insn & (1 << 25)) {
7762 if (insn & (1 << 24)) {
7763 if (insn & (1 << 20))
7764 goto illegal_op;
7765 /* Bitfield/Saturate. */
7766 op = (insn >> 21) & 7;
7767 imm = insn & 0x1f;
7768 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7769 if (rn == 15) {
7770 tmp = new_tmp();
7771 tcg_gen_movi_i32(tmp, 0);
7772 } else {
7773 tmp = load_reg(s, rn);
7775 switch (op) {
7776 case 2: /* Signed bitfield extract. */
7777 imm++;
7778 if (shift + imm > 32)
7779 goto illegal_op;
7780 if (imm < 32)
7781 gen_sbfx(tmp, shift, imm);
7782 break;
7783 case 6: /* Unsigned bitfield extract. */
7784 imm++;
7785 if (shift + imm > 32)
7786 goto illegal_op;
7787 if (imm < 32)
7788 gen_ubfx(tmp, shift, (1u << imm) - 1);
7789 break;
7790 case 3: /* Bitfield insert/clear. */
7791 if (imm < shift)
7792 goto illegal_op;
7793 imm = imm + 1 - shift;
7794 if (imm != 32) {
7795 tmp2 = load_reg(s, rd);
7796 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7797 dead_tmp(tmp2);
7799 break;
7800 case 7:
7801 goto illegal_op;
7802 default: /* Saturate. */
7803 if (shift) {
7804 if (op & 1)
7805 tcg_gen_sari_i32(tmp, tmp, shift);
7806 else
7807 tcg_gen_shli_i32(tmp, tmp, shift);
7809 tmp2 = tcg_const_i32(imm);
7810 if (op & 4) {
7811 /* Unsigned. */
7812 if ((op & 1) && shift == 0)
7813 gen_helper_usat16(tmp, tmp, tmp2);
7814 else
7815 gen_helper_usat(tmp, tmp, tmp2);
7816 } else {
7817 /* Signed. */
7818 if ((op & 1) && shift == 0)
7819 gen_helper_ssat16(tmp, tmp, tmp2);
7820 else
7821 gen_helper_ssat(tmp, tmp, tmp2);
7823 break;
7825 store_reg(s, rd, tmp);
7826 } else {
7827 imm = ((insn & 0x04000000) >> 15)
7828 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7829 if (insn & (1 << 22)) {
7830 /* 16-bit immediate. */
7831 imm |= (insn >> 4) & 0xf000;
7832 if (insn & (1 << 23)) {
7833 /* movt */
7834 tmp = load_reg(s, rd);
7835 tcg_gen_ext16u_i32(tmp, tmp);
7836 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7837 } else {
7838 /* movw */
7839 tmp = new_tmp();
7840 tcg_gen_movi_i32(tmp, imm);
7842 } else {
7843 /* Add/sub 12-bit immediate. */
7844 if (rn == 15) {
7845 offset = s->pc & ~(uint32_t)3;
7846 if (insn & (1 << 23))
7847 offset -= imm;
7848 else
7849 offset += imm;
7850 tmp = new_tmp();
7851 tcg_gen_movi_i32(tmp, offset);
7852 } else {
7853 tmp = load_reg(s, rn);
7854 if (insn & (1 << 23))
7855 tcg_gen_subi_i32(tmp, tmp, imm);
7856 else
7857 tcg_gen_addi_i32(tmp, tmp, imm);
7860 store_reg(s, rd, tmp);
7862 } else {
7863 int shifter_out = 0;
7864 /* modified 12-bit immediate. */
7865 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7866 imm = (insn & 0xff);
7867 switch (shift) {
7868 case 0: /* XY */
7869 /* Nothing to do. */
7870 break;
7871 case 1: /* 00XY00XY */
7872 imm |= imm << 16;
7873 break;
7874 case 2: /* XY00XY00 */
7875 imm |= imm << 16;
7876 imm <<= 8;
7877 break;
7878 case 3: /* XYXYXYXY */
7879 imm |= imm << 16;
7880 imm |= imm << 8;
7881 break;
7882 default: /* Rotated constant. */
7883 shift = (shift << 1) | (imm >> 7);
7884 imm |= 0x80;
7885 imm = imm << (32 - shift);
7886 shifter_out = 1;
7887 break;
7889 tmp2 = new_tmp();
7890 tcg_gen_movi_i32(tmp2, imm);
7891 rn = (insn >> 16) & 0xf;
7892 if (rn == 15) {
7893 tmp = new_tmp();
7894 tcg_gen_movi_i32(tmp, 0);
7895 } else {
7896 tmp = load_reg(s, rn);
7898 op = (insn >> 21) & 0xf;
7899 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7900 shifter_out, tmp, tmp2))
7901 goto illegal_op;
7902 dead_tmp(tmp2);
7903 rd = (insn >> 8) & 0xf;
7904 if (rd != 15) {
7905 store_reg(s, rd, tmp);
7906 } else {
7907 dead_tmp(tmp);
7911 break;
7912 case 12: /* Load/store single data item. */
7914 int postinc = 0;
7915 int writeback = 0;
7916 int user;
7917 if ((insn & 0x01100000) == 0x01000000) {
7918 if (disas_neon_ls_insn(env, s, insn))
7919 goto illegal_op;
7920 break;
7922 user = IS_USER(s);
7923 if (rn == 15) {
7924 addr = new_tmp();
7925 /* PC relative. */
7926 /* s->pc has already been incremented by 4. */
7927 imm = s->pc & 0xfffffffc;
7928 if (insn & (1 << 23))
7929 imm += insn & 0xfff;
7930 else
7931 imm -= insn & 0xfff;
7932 tcg_gen_movi_i32(addr, imm);
7933 } else {
7934 addr = load_reg(s, rn);
7935 if (insn & (1 << 23)) {
7936 /* Positive offset. */
7937 imm = insn & 0xfff;
7938 tcg_gen_addi_i32(addr, addr, imm);
7939 } else {
7940 op = (insn >> 8) & 7;
7941 imm = insn & 0xff;
7942 switch (op) {
7943 case 0: case 8: /* Shifted Register. */
7944 shift = (insn >> 4) & 0xf;
7945 if (shift > 3)
7946 goto illegal_op;
7947 tmp = load_reg(s, rm);
7948 if (shift)
7949 tcg_gen_shli_i32(tmp, tmp, shift);
7950 tcg_gen_add_i32(addr, addr, tmp);
7951 dead_tmp(tmp);
7952 break;
7953 case 4: /* Negative offset. */
7954 tcg_gen_addi_i32(addr, addr, -imm);
7955 break;
7956 case 6: /* User privilege. */
7957 tcg_gen_addi_i32(addr, addr, imm);
7958 user = 1;
7959 break;
7960 case 1: /* Post-decrement. */
7961 imm = -imm;
7962 /* Fall through. */
7963 case 3: /* Post-increment. */
7964 postinc = 1;
7965 writeback = 1;
7966 break;
7967 case 5: /* Pre-decrement. */
7968 imm = -imm;
7969 /* Fall through. */
7970 case 7: /* Pre-increment. */
7971 tcg_gen_addi_i32(addr, addr, imm);
7972 writeback = 1;
7973 break;
7974 default:
7975 goto illegal_op;
7979 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7980 if (insn & (1 << 20)) {
7981 /* Load. */
7982 if (rs == 15 && op != 2) {
7983 if (op & 2)
7984 goto illegal_op;
7985 /* Memory hint. Implemented as NOP. */
7986 } else {
7987 switch (op) {
7988 case 0: tmp = gen_ld8u(addr, user); break;
7989 case 4: tmp = gen_ld8s(addr, user); break;
7990 case 1: tmp = gen_ld16u(addr, user); break;
7991 case 5: tmp = gen_ld16s(addr, user); break;
7992 case 2: tmp = gen_ld32(addr, user); break;
7993 default: goto illegal_op;
7995 if (rs == 15 && ENABLE_ARCH_5) {
7996 gen_bx(s, tmp);
7997 } else {
7998 store_reg(s, rs, tmp);
8001 } else {
8002 /* Store. */
8003 if (rs == 15)
8004 goto illegal_op;
8005 tmp = load_reg(s, rs);
8006 switch (op) {
8007 case 0: gen_st8(tmp, addr, user); break;
8008 case 1: gen_st16(tmp, addr, user); break;
8009 case 2: gen_st32(tmp, addr, user); break;
8010 default: goto illegal_op;
8013 if (postinc)
8014 tcg_gen_addi_i32(addr, addr, imm);
8015 if (writeback) {
8016 store_reg(s, rn, addr);
8017 } else {
8018 dead_tmp(addr);
8021 break;
8022 default:
8023 goto illegal_op;
8025 return 0;
8026 illegal_op:
8027 return 1;
8030 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8032 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8033 int32_t offset;
8034 int i;
8035 TCGv tmp;
8036 TCGv tmp2;
8037 TCGv addr;
8038 int crement;
8040 if (s->condexec_mask) {
8041 cond = s->condexec_cond;
8042 s->condlabel = gen_new_label();
8043 gen_test_cc(cond ^ 1, s->condlabel);
8044 s->condjmp = 1;
8047 insn = lduw_code(s->pc);
8048 s->pc += 2;
8050 switch (insn >> 12) {
8051 case 0: case 1:
8053 rd = insn & 7;
8054 op = (insn >> 11) & 3;
8055 if (op == 3) {
8056 /* add/subtract */
8057 rn = (insn >> 3) & 7;
8058 tmp = load_reg(s, rn);
8059 if (insn & (1 << 10)) {
8060 /* immediate */
8061 tmp2 = new_tmp();
8062 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8063 } else {
8064 /* reg */
8065 rm = (insn >> 6) & 7;
8066 tmp2 = load_reg(s, rm);
8068 if (insn & (1 << 9)) {
8069 if (s->condexec_mask)
8070 tcg_gen_sub_i32(tmp, tmp, tmp2);
8071 else
8072 gen_helper_sub_cc(tmp, tmp, tmp2);
8073 } else {
8074 if (s->condexec_mask)
8075 tcg_gen_add_i32(tmp, tmp, tmp2);
8076 else
8077 gen_helper_add_cc(tmp, tmp, tmp2);
8079 dead_tmp(tmp2);
8080 store_reg(s, rd, tmp);
8081 } else {
8082 /* shift immediate */
8083 rm = (insn >> 3) & 7;
8084 shift = (insn >> 6) & 0x1f;
8085 tmp = load_reg(s, rm);
8086 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8087 if (!s->condexec_mask)
8088 gen_logic_CC(tmp);
8089 store_reg(s, rd, tmp);
8091 break;
8092 case 2: case 3:
8093 /* arithmetic large immediate */
8094 op = (insn >> 11) & 3;
8095 rd = (insn >> 8) & 0x7;
8096 if (op == 0) { /* mov */
8097 tmp = new_tmp();
8098 tcg_gen_movi_i32(tmp, insn & 0xff);
8099 if (!s->condexec_mask)
8100 gen_logic_CC(tmp);
8101 store_reg(s, rd, tmp);
8102 } else {
8103 tmp = load_reg(s, rd);
8104 tmp2 = new_tmp();
8105 tcg_gen_movi_i32(tmp2, insn & 0xff);
8106 switch (op) {
8107 case 1: /* cmp */
8108 gen_helper_sub_cc(tmp, tmp, tmp2);
8109 dead_tmp(tmp);
8110 dead_tmp(tmp2);
8111 break;
8112 case 2: /* add */
8113 if (s->condexec_mask)
8114 tcg_gen_add_i32(tmp, tmp, tmp2);
8115 else
8116 gen_helper_add_cc(tmp, tmp, tmp2);
8117 dead_tmp(tmp2);
8118 store_reg(s, rd, tmp);
8119 break;
8120 case 3: /* sub */
8121 if (s->condexec_mask)
8122 tcg_gen_sub_i32(tmp, tmp, tmp2);
8123 else
8124 gen_helper_sub_cc(tmp, tmp, tmp2);
8125 dead_tmp(tmp2);
8126 store_reg(s, rd, tmp);
8127 break;
8130 break;
8131 case 4:
8132 if (insn & (1 << 11)) {
8133 rd = (insn >> 8) & 7;
8134 /* load pc-relative. Bit 1 of PC is ignored. */
8135 val = s->pc + 2 + ((insn & 0xff) * 4);
8136 val &= ~(uint32_t)2;
8137 addr = new_tmp();
8138 tcg_gen_movi_i32(addr, val);
8139 tmp = gen_ld32(addr, IS_USER(s));
8140 dead_tmp(addr);
8141 store_reg(s, rd, tmp);
8142 break;
8144 if (insn & (1 << 10)) {
8145 /* data processing extended or blx */
8146 rd = (insn & 7) | ((insn >> 4) & 8);
8147 rm = (insn >> 3) & 0xf;
8148 op = (insn >> 8) & 3;
8149 switch (op) {
8150 case 0: /* add */
8151 tmp = load_reg(s, rd);
8152 tmp2 = load_reg(s, rm);
8153 tcg_gen_add_i32(tmp, tmp, tmp2);
8154 dead_tmp(tmp2);
8155 store_reg(s, rd, tmp);
8156 break;
8157 case 1: /* cmp */
8158 tmp = load_reg(s, rd);
8159 tmp2 = load_reg(s, rm);
8160 gen_helper_sub_cc(tmp, tmp, tmp2);
8161 dead_tmp(tmp2);
8162 dead_tmp(tmp);
8163 break;
8164 case 2: /* mov/cpy */
8165 tmp = load_reg(s, rm);
8166 store_reg(s, rd, tmp);
8167 break;
8168 case 3:/* branch [and link] exchange thumb register */
8169 tmp = load_reg(s, rm);
8170 if (insn & (1 << 7)) {
8171 ARCH(5);
8172 val = (uint32_t)s->pc | 1;
8173 tmp2 = new_tmp();
8174 tcg_gen_movi_i32(tmp2, val);
8175 store_reg(s, 14, tmp2);
8177 gen_bx(s, tmp);
8178 break;
8180 break;
8183 /* data processing register */
8184 rd = insn & 7;
8185 rm = (insn >> 3) & 7;
8186 op = (insn >> 6) & 0xf;
8187 if (op == 2 || op == 3 || op == 4 || op == 7) {
8188 /* the shift/rotate ops want the operands backwards */
8189 val = rm;
8190 rm = rd;
8191 rd = val;
8192 val = 1;
8193 } else {
8194 val = 0;
8197 if (op == 9) { /* neg */
8198 tmp = new_tmp();
8199 tcg_gen_movi_i32(tmp, 0);
8200 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8201 tmp = load_reg(s, rd);
8202 } else {
8203 TCGV_UNUSED(tmp);
8206 tmp2 = load_reg(s, rm);
8207 switch (op) {
8208 case 0x0: /* and */
8209 tcg_gen_and_i32(tmp, tmp, tmp2);
8210 if (!s->condexec_mask)
8211 gen_logic_CC(tmp);
8212 break;
8213 case 0x1: /* eor */
8214 tcg_gen_xor_i32(tmp, tmp, tmp2);
8215 if (!s->condexec_mask)
8216 gen_logic_CC(tmp);
8217 break;
8218 case 0x2: /* lsl */
8219 if (s->condexec_mask) {
8220 gen_helper_shl(tmp2, tmp2, tmp);
8221 } else {
8222 gen_helper_shl_cc(tmp2, tmp2, tmp);
8223 gen_logic_CC(tmp2);
8225 break;
8226 case 0x3: /* lsr */
8227 if (s->condexec_mask) {
8228 gen_helper_shr(tmp2, tmp2, tmp);
8229 } else {
8230 gen_helper_shr_cc(tmp2, tmp2, tmp);
8231 gen_logic_CC(tmp2);
8233 break;
8234 case 0x4: /* asr */
8235 if (s->condexec_mask) {
8236 gen_helper_sar(tmp2, tmp2, tmp);
8237 } else {
8238 gen_helper_sar_cc(tmp2, tmp2, tmp);
8239 gen_logic_CC(tmp2);
8241 break;
8242 case 0x5: /* adc */
8243 if (s->condexec_mask)
8244 gen_add_carry(tmp, tmp, tmp2);
8245 else
8246 gen_helper_adc_cc(tmp, tmp, tmp2);
8247 break;
8248 case 0x6: /* sbc */
8249 if (s->condexec_mask)
8250 gen_sub_carry(tmp, tmp, tmp2);
8251 else
8252 gen_helper_sbc_cc(tmp, tmp, tmp2);
8253 break;
8254 case 0x7: /* ror */
8255 if (s->condexec_mask) {
8256 gen_helper_ror(tmp2, tmp2, tmp);
8257 } else {
8258 gen_helper_ror_cc(tmp2, tmp2, tmp);
8259 gen_logic_CC(tmp2);
8261 break;
8262 case 0x8: /* tst */
8263 tcg_gen_and_i32(tmp, tmp, tmp2);
8264 gen_logic_CC(tmp);
8265 rd = 16;
8266 break;
8267 case 0x9: /* neg */
8268 if (s->condexec_mask)
8269 tcg_gen_neg_i32(tmp, tmp2);
8270 else
8271 gen_helper_sub_cc(tmp, tmp, tmp2);
8272 break;
8273 case 0xa: /* cmp */
8274 gen_helper_sub_cc(tmp, tmp, tmp2);
8275 rd = 16;
8276 break;
8277 case 0xb: /* cmn */
8278 gen_helper_add_cc(tmp, tmp, tmp2);
8279 rd = 16;
8280 break;
8281 case 0xc: /* orr */
8282 tcg_gen_or_i32(tmp, tmp, tmp2);
8283 if (!s->condexec_mask)
8284 gen_logic_CC(tmp);
8285 break;
8286 case 0xd: /* mul */
8287 gen_mull(tmp, tmp2);
8288 if (!s->condexec_mask)
8289 gen_logic_CC(tmp);
8290 break;
8291 case 0xe: /* bic */
8292 tcg_gen_bic_i32(tmp, tmp, tmp2);
8293 if (!s->condexec_mask)
8294 gen_logic_CC(tmp);
8295 break;
8296 case 0xf: /* mvn */
8297 tcg_gen_not_i32(tmp2, tmp2);
8298 if (!s->condexec_mask)
8299 gen_logic_CC(tmp2);
8300 val = 1;
8301 rm = rd;
8302 break;
8304 if (rd != 16) {
8305 if (val) {
8306 store_reg(s, rm, tmp2);
8307 if (op != 0xf)
8308 dead_tmp(tmp);
8309 } else {
8310 store_reg(s, rd, tmp);
8311 dead_tmp(tmp2);
8313 } else {
8314 dead_tmp(tmp);
8315 dead_tmp(tmp2);
8317 break;
8319 case 5:
8320 /* load/store register offset. */
8321 rd = insn & 7;
8322 rn = (insn >> 3) & 7;
8323 rm = (insn >> 6) & 7;
8324 op = (insn >> 9) & 7;
8325 addr = load_reg(s, rn);
8326 tmp = load_reg(s, rm);
8327 tcg_gen_add_i32(addr, addr, tmp);
8328 dead_tmp(tmp);
8330 if (op < 3) /* store */
8331 tmp = load_reg(s, rd);
8333 switch (op) {
8334 case 0: /* str */
8335 gen_st32(tmp, addr, IS_USER(s));
8336 break;
8337 case 1: /* strh */
8338 gen_st16(tmp, addr, IS_USER(s));
8339 break;
8340 case 2: /* strb */
8341 gen_st8(tmp, addr, IS_USER(s));
8342 break;
8343 case 3: /* ldrsb */
8344 tmp = gen_ld8s(addr, IS_USER(s));
8345 break;
8346 case 4: /* ldr */
8347 tmp = gen_ld32(addr, IS_USER(s));
8348 break;
8349 case 5: /* ldrh */
8350 tmp = gen_ld16u(addr, IS_USER(s));
8351 break;
8352 case 6: /* ldrb */
8353 tmp = gen_ld8u(addr, IS_USER(s));
8354 break;
8355 case 7: /* ldrsh */
8356 tmp = gen_ld16s(addr, IS_USER(s));
8357 break;
8359 if (op >= 3) /* load */
8360 store_reg(s, rd, tmp);
8361 dead_tmp(addr);
8362 break;
8364 case 6:
8365 /* load/store word immediate offset */
8366 rd = insn & 7;
8367 rn = (insn >> 3) & 7;
8368 addr = load_reg(s, rn);
8369 val = (insn >> 4) & 0x7c;
8370 tcg_gen_addi_i32(addr, addr, val);
8372 if (insn & (1 << 11)) {
8373 /* load */
8374 tmp = gen_ld32(addr, IS_USER(s));
8375 store_reg(s, rd, tmp);
8376 } else {
8377 /* store */
8378 tmp = load_reg(s, rd);
8379 gen_st32(tmp, addr, IS_USER(s));
8381 dead_tmp(addr);
8382 break;
8384 case 7:
8385 /* load/store byte immediate offset */
8386 rd = insn & 7;
8387 rn = (insn >> 3) & 7;
8388 addr = load_reg(s, rn);
8389 val = (insn >> 6) & 0x1f;
8390 tcg_gen_addi_i32(addr, addr, val);
8392 if (insn & (1 << 11)) {
8393 /* load */
8394 tmp = gen_ld8u(addr, IS_USER(s));
8395 store_reg(s, rd, tmp);
8396 } else {
8397 /* store */
8398 tmp = load_reg(s, rd);
8399 gen_st8(tmp, addr, IS_USER(s));
8401 dead_tmp(addr);
8402 break;
8404 case 8:
8405 /* load/store halfword immediate offset */
8406 rd = insn & 7;
8407 rn = (insn >> 3) & 7;
8408 addr = load_reg(s, rn);
8409 val = (insn >> 5) & 0x3e;
8410 tcg_gen_addi_i32(addr, addr, val);
8412 if (insn & (1 << 11)) {
8413 /* load */
8414 tmp = gen_ld16u(addr, IS_USER(s));
8415 store_reg(s, rd, tmp);
8416 } else {
8417 /* store */
8418 tmp = load_reg(s, rd);
8419 gen_st16(tmp, addr, IS_USER(s));
8421 dead_tmp(addr);
8422 break;
8424 case 9:
8425 /* load/store from stack */
8426 rd = (insn >> 8) & 7;
8427 addr = load_reg(s, 13);
8428 val = (insn & 0xff) * 4;
8429 tcg_gen_addi_i32(addr, addr, val);
8431 if (insn & (1 << 11)) {
8432 /* load */
8433 tmp = gen_ld32(addr, IS_USER(s));
8434 store_reg(s, rd, tmp);
8435 } else {
8436 /* store */
8437 tmp = load_reg(s, rd);
8438 gen_st32(tmp, addr, IS_USER(s));
8440 dead_tmp(addr);
8441 break;
8443 case 10:
8444 /* add to high reg */
8445 rd = (insn >> 8) & 7;
8446 if (insn & (1 << 11)) {
8447 /* SP */
8448 tmp = load_reg(s, 13);
8449 } else {
8450 /* PC. bit 1 is ignored. */
8451 tmp = new_tmp();
8452 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8454 val = (insn & 0xff) * 4;
8455 tcg_gen_addi_i32(tmp, tmp, val);
8456 store_reg(s, rd, tmp);
8457 break;
8459 case 11:
8460 /* misc */
8461 op = (insn >> 8) & 0xf;
8462 switch (op) {
8463 case 0:
8464 /* adjust stack pointer */
8465 tmp = load_reg(s, 13);
8466 val = (insn & 0x7f) * 4;
8467 if (insn & (1 << 7))
8468 val = -(int32_t)val;
8469 tcg_gen_addi_i32(tmp, tmp, val);
8470 store_reg(s, 13, tmp);
8471 break;
8473 case 2: /* sign/zero extend. */
8474 ARCH(6);
8475 rd = insn & 7;
8476 rm = (insn >> 3) & 7;
8477 tmp = load_reg(s, rm);
8478 switch ((insn >> 6) & 3) {
8479 case 0: gen_sxth(tmp); break;
8480 case 1: gen_sxtb(tmp); break;
8481 case 2: gen_uxth(tmp); break;
8482 case 3: gen_uxtb(tmp); break;
8484 store_reg(s, rd, tmp);
8485 break;
8486 case 4: case 5: case 0xc: case 0xd:
8487 /* push/pop */
8488 addr = load_reg(s, 13);
8489 if (insn & (1 << 8))
8490 offset = 4;
8491 else
8492 offset = 0;
8493 for (i = 0; i < 8; i++) {
8494 if (insn & (1 << i))
8495 offset += 4;
8497 if ((insn & (1 << 11)) == 0) {
8498 tcg_gen_addi_i32(addr, addr, -offset);
8500 for (i = 0; i < 8; i++) {
8501 if (insn & (1 << i)) {
8502 if (insn & (1 << 11)) {
8503 /* pop */
8504 tmp = gen_ld32(addr, IS_USER(s));
8505 store_reg(s, i, tmp);
8506 } else {
8507 /* push */
8508 tmp = load_reg(s, i);
8509 gen_st32(tmp, addr, IS_USER(s));
8511 /* advance to the next address. */
8512 tcg_gen_addi_i32(addr, addr, 4);
8515 TCGV_UNUSED(tmp);
8516 if (insn & (1 << 8)) {
8517 if (insn & (1 << 11)) {
8518 /* pop pc */
8519 tmp = gen_ld32(addr, IS_USER(s));
8520 /* don't set the pc until the rest of the instruction
8521 has completed */
8522 } else {
8523 /* push lr */
8524 tmp = load_reg(s, 14);
8525 gen_st32(tmp, addr, IS_USER(s));
8527 tcg_gen_addi_i32(addr, addr, 4);
8529 if ((insn & (1 << 11)) == 0) {
8530 tcg_gen_addi_i32(addr, addr, -offset);
8532 /* write back the new stack pointer */
8533 store_reg(s, 13, addr);
8534 /* set the new PC value */
8535 if ((insn & 0x0900) == 0x0900) {
8536 if (ENABLE_ARCH_5) {
8537 gen_bx(s, tmp);
8538 } else {
8539 store_reg(s, 15, tmp);
8542 break;
8544 case 1: case 3: case 9: case 11: /* czb */
8545 rm = insn & 7;
8546 tmp = load_reg(s, rm);
8547 s->condlabel = gen_new_label();
8548 s->condjmp = 1;
8549 if (insn & (1 << 11))
8550 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8551 else
8552 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8553 dead_tmp(tmp);
8554 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8555 val = (uint32_t)s->pc + 2;
8556 val += offset;
8557 gen_jmp(s, val);
8558 break;
8560 case 15: /* IT, nop-hint. */
8561 if ((insn & 0xf) == 0) {
8562 gen_nop_hint(s, (insn >> 4) & 0xf);
8563 break;
8565 /* If Then. */
8566 s->condexec_cond = (insn >> 4) & 0xe;
8567 s->condexec_mask = insn & 0x1f;
8568 /* No actual code generated for this insn, just setup state. */
8569 break;
8571 case 0xe: /* bkpt */
8572 gen_set_condexec(s);
8573 gen_set_pc_im(s->pc - 2);
8574 gen_exception(EXCP_BKPT);
8575 s->is_jmp = DISAS_JUMP;
8576 break;
8578 case 0xa: /* rev */
8579 ARCH(6);
8580 rn = (insn >> 3) & 0x7;
8581 rd = insn & 0x7;
8582 tmp = load_reg(s, rn);
8583 switch ((insn >> 6) & 3) {
8584 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8585 case 1: gen_rev16(tmp); break;
8586 case 3: gen_revsh(tmp); break;
8587 default: goto illegal_op;
8589 store_reg(s, rd, tmp);
8590 break;
8592 case 6: /* cps */
8593 ARCH(6);
8594 if (IS_USER(s))
8595 break;
8596 if (IS_M(env)) {
8597 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8598 /* PRIMASK */
8599 if (insn & 1) {
8600 addr = tcg_const_i32(16);
8601 gen_helper_v7m_msr(cpu_env, addr, tmp);
8603 /* FAULTMASK */
8604 if (insn & 2) {
8605 addr = tcg_const_i32(17);
8606 gen_helper_v7m_msr(cpu_env, addr, tmp);
8608 gen_lookup_tb(s);
8609 } else {
8610 if (insn & (1 << 4))
8611 shift = CPSR_A | CPSR_I | CPSR_F;
8612 else
8613 shift = 0;
8614 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8616 break;
8618 default:
8619 goto undef;
8621 break;
8623 case 12:
8624 /* load/store multiple */
8625 rn = (insn >> 8) & 0x7;
8626 addr = load_reg(s, rn);
8627 if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8628 /* base-updated abort model: update base register
8629 before an abort can happen */
8630 crement = 0;
8631 for (i = 0; i < 8; i++) {
8632 if (insn & (1 << i)) {
8633 crement += 4;
8636 tmp = new_tmp();
8637 tcg_gen_addi_i32(tmp, addr, crement);
8638 store_reg(s, rn, tmp);
8640 for (i = 0; i < 8; i++) {
8641 if (insn & (1 << i)) {
8642 if (insn & (1 << 11)) {
8643 /* load */
8644 tmp = gen_ld32(addr, IS_USER(s));
8645 store_reg(s, i, tmp);
8646 } else {
8647 /* store */
8648 tmp = load_reg(s, i);
8649 gen_st32(tmp, addr, IS_USER(s));
8651 /* advance to the next address */
8652 tcg_gen_addi_i32(addr, addr, 4);
8655 /* Base register writeback. */
8656 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8657 store_reg(s, rn, addr);
8658 } else {
8659 dead_tmp(addr);
8661 break;
8663 case 13:
8664 /* conditional branch or swi */
8665 cond = (insn >> 8) & 0xf;
8666 if (cond == 0xe)
8667 goto undef;
8669 if (cond == 0xf) {
8670 /* swi */
8671 gen_set_condexec(s);
8672 gen_set_pc_im(s->pc);
8673 s->is_jmp = DISAS_SWI;
8674 break;
8676 /* generate a conditional jump to next instruction */
8677 s->condlabel = gen_new_label();
8678 gen_test_cc(cond ^ 1, s->condlabel);
8679 s->condjmp = 1;
8681 /* jump to the offset */
8682 val = (uint32_t)s->pc + 2;
8683 offset = ((int32_t)insn << 24) >> 24;
8684 val += offset << 1;
8685 gen_jmp(s, val);
8686 break;
8688 case 14:
8689 if (insn & (1 << 11)) {
8690 if (disas_thumb2_insn(env, s, insn))
8691 goto undef32;
8692 break;
8694 /* unconditional branch */
8695 val = (uint32_t)s->pc;
8696 offset = ((int32_t)insn << 21) >> 21;
8697 val += (offset << 1) + 2;
8698 gen_jmp(s, val);
8699 break;
8701 case 15:
8702 if (disas_thumb2_insn(env, s, insn))
8703 goto undef32;
8704 break;
8706 return;
8707 undef32:
8708 gen_set_condexec(s);
8709 gen_set_pc_im(s->pc - 4);
8710 gen_exception(EXCP_UDEF);
8711 s->is_jmp = DISAS_JUMP;
8712 return;
8713 illegal_op:
8714 undef:
8715 gen_set_condexec(s);
8716 gen_set_pc_im(s->pc - 2);
8717 gen_exception(EXCP_UDEF);
8718 s->is_jmp = DISAS_JUMP;
8721 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8722 basic block 'tb'. If search_pc is TRUE, also generate PC
8723 information for each intermediate instruction. */
8724 static inline void gen_intermediate_code_internal(CPUState *env,
8725 TranslationBlock *tb,
8726 int search_pc)
8728 DisasContext dc1, *dc = &dc1;
8729 CPUBreakpoint *bp;
8730 uint16_t *gen_opc_end;
8731 int j, lj;
8732 target_ulong pc_start;
8733 uint32_t next_page_start;
8734 int num_insns;
8735 int max_insns;
8737 /* generate intermediate code */
8738 num_temps = 0;
8740 pc_start = tb->pc;
8742 dc->tb = tb;
8744 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8746 dc->is_jmp = DISAS_NEXT;
8747 dc->pc = pc_start;
8748 dc->singlestep_enabled = env->singlestep_enabled;
8749 dc->condjmp = 0;
8750 dc->thumb = env->thumb;
8751 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8752 dc->condexec_cond = env->condexec_bits >> 4;
8753 #if !defined(CONFIG_USER_ONLY)
8754 if (IS_M(env)) {
8755 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8756 } else {
8757 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8759 #endif
8760 cpu_F0s = tcg_temp_new_i32();
8761 cpu_F1s = tcg_temp_new_i32();
8762 cpu_F0d = tcg_temp_new_i64();
8763 cpu_F1d = tcg_temp_new_i64();
8764 cpu_V0 = cpu_F0d;
8765 cpu_V1 = cpu_F1d;
8766 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8767 cpu_M0 = tcg_temp_new_i64();
8768 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8769 lj = -1;
8770 num_insns = 0;
8771 max_insns = tb->cflags & CF_COUNT_MASK;
8772 if (max_insns == 0)
8773 max_insns = CF_COUNT_MASK;
8775 gen_icount_start();
8776 /* Reset the conditional execution bits immediately. This avoids
8777 complications trying to do it at the end of the block. */
8778 if (env->condexec_bits)
8780 TCGv tmp = new_tmp();
8781 tcg_gen_movi_i32(tmp, 0);
8782 store_cpu_field(tmp, condexec_bits);
8784 do {
8785 #ifdef CONFIG_USER_ONLY
8786 /* Intercept jump to the magic kernel page. */
8787 if (dc->pc >= 0xffff0000) {
8788 /* We always get here via a jump, so know we are not in a
8789 conditional execution block. */
8790 gen_exception(EXCP_KERNEL_TRAP);
8791 dc->is_jmp = DISAS_UPDATE;
8792 break;
8794 #else
8795 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8796 /* We always get here via a jump, so know we are not in a
8797 conditional execution block. */
8798 gen_exception(EXCP_EXCEPTION_EXIT);
8799 dc->is_jmp = DISAS_UPDATE;
8800 break;
8802 #endif
8804 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8805 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8806 if (bp->pc == dc->pc) {
8807 gen_set_condexec(dc);
8808 gen_set_pc_im(dc->pc);
8809 gen_exception(EXCP_DEBUG);
8810 dc->is_jmp = DISAS_JUMP;
8811 /* Advance PC so that clearing the breakpoint will
8812 invalidate this TB. */
8813 dc->pc += 2;
8814 goto done_generating;
8815 break;
8819 if (search_pc) {
8820 j = gen_opc_ptr - gen_opc_buf;
8821 if (lj < j) {
8822 lj++;
8823 while (lj < j)
8824 gen_opc_instr_start[lj++] = 0;
8826 gen_opc_pc[lj] = dc->pc;
8827 gen_opc_instr_start[lj] = 1;
8828 gen_opc_icount[lj] = num_insns;
8831 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8832 gen_io_start();
8834 if (env->thumb) {
8835 disas_thumb_insn(env, dc);
8836 if (dc->condexec_mask) {
8837 dc->condexec_cond = (dc->condexec_cond & 0xe)
8838 | ((dc->condexec_mask >> 4) & 1);
8839 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8840 if (dc->condexec_mask == 0) {
8841 dc->condexec_cond = 0;
8844 } else {
8845 disas_arm_insn(env, dc);
8847 if (num_temps) {
8848 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8849 num_temps = 0;
8852 if (dc->condjmp && !dc->is_jmp) {
8853 gen_set_label(dc->condlabel);
8854 dc->condjmp = 0;
8856 /* Translation stops when a conditional branch is encountered.
8857 * Otherwise the subsequent code could get translated several times.
8858 * Also stop translation when a page boundary is reached. This
8859 * ensures prefetch aborts occur at the right place. */
8860 num_insns ++;
8861 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8862 !env->singlestep_enabled &&
8863 !singlestep &&
8864 dc->pc < next_page_start &&
8865 num_insns < max_insns);
8867 if (tb->cflags & CF_LAST_IO) {
8868 if (dc->condjmp) {
8869 /* FIXME: This can theoretically happen with self-modifying
8870 code. */
8871 cpu_abort(env, "IO on conditional branch instruction");
8873 gen_io_end();
8876 /* At this stage dc->condjmp will only be set when the skipped
8877 instruction was a conditional branch or trap, and the PC has
8878 already been written. */
8879 if (unlikely(env->singlestep_enabled)) {
8880 /* Make sure the pc is updated, and raise a debug exception. */
8881 if (dc->condjmp) {
8882 gen_set_condexec(dc);
8883 if (dc->is_jmp == DISAS_SWI) {
8884 gen_exception(EXCP_SWI);
8885 } else {
8886 gen_exception(EXCP_DEBUG);
8888 gen_set_label(dc->condlabel);
8890 if (dc->condjmp || !dc->is_jmp) {
8891 gen_set_pc_im(dc->pc);
8892 dc->condjmp = 0;
8894 gen_set_condexec(dc);
8895 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8896 gen_exception(EXCP_SWI);
8897 } else {
8898 /* FIXME: Single stepping a WFI insn will not halt
8899 the CPU. */
8900 gen_exception(EXCP_DEBUG);
8902 } else {
8903 /* While branches must always occur at the end of an IT block,
8904 there are a few other things that can cause us to terminate
8905 the TB in the middel of an IT block:
8906 - Exception generating instructions (bkpt, swi, undefined).
8907 - Page boundaries.
8908 - Hardware watchpoints.
8909 Hardware breakpoints have already been handled and skip this code.
8911 gen_set_condexec(dc);
8912 switch(dc->is_jmp) {
8913 case DISAS_NEXT:
8914 gen_goto_tb(dc, 1, dc->pc);
8915 break;
8916 default:
8917 case DISAS_JUMP:
8918 case DISAS_UPDATE:
8919 /* indicate that the hash table must be used to find the next TB */
8920 tcg_gen_exit_tb(0);
8921 break;
8922 case DISAS_TB_JUMP:
8923 /* nothing more to generate */
8924 break;
8925 case DISAS_WFI:
8926 gen_helper_wfi();
8927 break;
8928 case DISAS_SWI:
8929 gen_exception(EXCP_SWI);
8930 break;
8932 if (dc->condjmp) {
8933 gen_set_label(dc->condlabel);
8934 gen_set_condexec(dc);
8935 gen_goto_tb(dc, 1, dc->pc);
8936 dc->condjmp = 0;
8940 done_generating:
8941 gen_icount_end(tb, num_insns);
8942 *gen_opc_ptr = INDEX_op_end;
8944 #ifdef DEBUG_DISAS
8945 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8946 qemu_log("----------------\n");
8947 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8948 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8949 qemu_log("\n");
8951 #endif
8952 if (search_pc) {
8953 j = gen_opc_ptr - gen_opc_buf;
8954 lj++;
8955 while (lj <= j)
8956 gen_opc_instr_start[lj++] = 0;
8957 } else {
8958 tb->size = dc->pc - pc_start;
8959 tb->icount = num_insns;
8963 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8965 gen_intermediate_code_internal(env, tb, 0);
8968 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8970 gen_intermediate_code_internal(env, tb, 1);
8973 static const char *cpu_mode_names[16] = {
8974 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8975 "???", "???", "???", "und", "???", "???", "???", "sys"
8978 void cpu_dump_state(CPUState *env, FILE *f,
8979 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8980 int flags)
8982 int i;
8983 #if 0
8984 union {
8985 uint32_t i;
8986 float s;
8987 } s0, s1;
8988 CPU_DoubleU d;
8989 /* ??? This assumes float64 and double have the same layout.
8990 Oh well, it's only debug dumps. */
8991 union {
8992 float64 f64;
8993 double d;
8994 } d0;
8995 #endif
8996 uint32_t psr;
8998 for(i=0;i<16;i++) {
8999 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9000 if ((i % 4) == 3)
9001 cpu_fprintf(f, "\n");
9002 else
9003 cpu_fprintf(f, " ");
9005 psr = cpsr_read(env);
9006 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9007 psr,
9008 psr & (1 << 31) ? 'N' : '-',
9009 psr & (1 << 30) ? 'Z' : '-',
9010 psr & (1 << 29) ? 'C' : '-',
9011 psr & (1 << 28) ? 'V' : '-',
9012 psr & CPSR_T ? 'T' : 'A',
9013 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9015 #if 0
9016 for (i = 0; i < 16; i++) {
9017 d.d = env->vfp.regs[i];
9018 s0.i = d.l.lower;
9019 s1.i = d.l.upper;
9020 d0.f64 = d.d;
9021 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9022 i * 2, (int)s0.i, s0.s,
9023 i * 2 + 1, (int)s1.i, s1.s,
9024 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9025 d0.d);
9027 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9028 #endif
9031 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9032 uintptr_t searched_pc, int pc_pos, void *puc)
9034 env->regs[15] = gen_opc_pc[pc_pos];