target-arm: convert rest of disas_arm_insn / disas_thumb2_insn not to use cpu_T
[qemu/stefanha.git] / target-arm / translate.c
blobf2ec04bbf732ecf636a2daef76f1f822d8930d1c
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 } DisasContext;
64 #if defined(CONFIG_USER_ONLY)
65 #define IS_USER(s) 1
66 #else
67 #define IS_USER(s) (s->user)
68 #endif
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72 #define DISAS_WFI 4
73 #define DISAS_SWI 5
75 static TCGv_ptr cpu_env;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
78 static TCGv_i32 cpu_R[16];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_T[2];
82 static TCGv cpu_F0s, cpu_F1s;
83 static TCGv_i64 cpu_F0d, cpu_F1d;
85 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h"
88 static const char *regnames[] =
89 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
92 /* initialize TCG globals. */
93 void arm_translate_init(void)
95 int i;
97 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
99 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
100 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
102 for (i = 0; i < 16; i++) {
103 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUState, regs[i]),
105 regnames[i]);
108 #define GEN_HELPER 2
109 #include "helpers.h"
112 static int num_temps;
114 /* Allocate a temporary variable. */
115 static TCGv_i32 new_tmp(void)
117 num_temps++;
118 return tcg_temp_new_i32();
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp)
124 tcg_temp_free(tmp);
125 num_temps--;
128 static inline TCGv load_cpu_offset(int offset)
130 TCGv tmp = new_tmp();
131 tcg_gen_ld_i32(tmp, cpu_env, offset);
132 return tmp;
135 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
137 static inline void store_cpu_offset(TCGv var, int offset)
139 tcg_gen_st_i32(var, cpu_env, offset);
140 dead_tmp(var);
143 #define store_cpu_field(var, name) \
144 store_cpu_offset(var, offsetof(CPUState, name))
146 /* Set a variable to the value of a CPU register. */
147 static void load_reg_var(DisasContext *s, TCGv var, int reg)
149 if (reg == 15) {
150 uint32_t addr;
151 /* normaly, since we updated PC, we need only to add one insn */
152 if (s->thumb)
153 addr = (long)s->pc + 2;
154 else
155 addr = (long)s->pc + 4;
156 tcg_gen_movi_i32(var, addr);
157 } else {
158 tcg_gen_mov_i32(var, cpu_R[reg]);
162 /* Create a new temporary and set it to the value of a CPU register. */
163 static inline TCGv load_reg(DisasContext *s, int reg)
165 TCGv tmp = new_tmp();
166 load_reg_var(s, tmp, reg);
167 return tmp;
170 /* Set a CPU register. The source must be a temporary and will be
171 marked as dead. */
172 static void store_reg(DisasContext *s, int reg, TCGv var)
174 if (reg == 15) {
175 tcg_gen_andi_i32(var, var, ~1);
176 s->is_jmp = DISAS_JUMP;
178 tcg_gen_mov_i32(cpu_R[reg], var);
179 dead_tmp(var);
183 /* Basic operations. */
184 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
185 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
188 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
190 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
191 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
193 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
194 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
195 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
196 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
197 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
199 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
200 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
202 /* Value extensions. */
203 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
204 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
205 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
206 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
208 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
209 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
211 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
214 /* Set NZCV flags from the high 4 bits of var. */
215 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
217 static void gen_exception(int excp)
219 TCGv tmp = new_tmp();
220 tcg_gen_movi_i32(tmp, excp);
221 gen_helper_exception(tmp);
222 dead_tmp(tmp);
225 static void gen_smul_dual(TCGv a, TCGv b)
227 TCGv tmp1 = new_tmp();
228 TCGv tmp2 = new_tmp();
229 tcg_gen_ext16s_i32(tmp1, a);
230 tcg_gen_ext16s_i32(tmp2, b);
231 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
232 dead_tmp(tmp2);
233 tcg_gen_sari_i32(a, a, 16);
234 tcg_gen_sari_i32(b, b, 16);
235 tcg_gen_mul_i32(b, b, a);
236 tcg_gen_mov_i32(a, tmp1);
237 dead_tmp(tmp1);
240 /* Byteswap each halfword. */
241 static void gen_rev16(TCGv var)
243 TCGv tmp = new_tmp();
244 tcg_gen_shri_i32(tmp, var, 8);
245 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
246 tcg_gen_shli_i32(var, var, 8);
247 tcg_gen_andi_i32(var, var, 0xff00ff00);
248 tcg_gen_or_i32(var, var, tmp);
249 dead_tmp(tmp);
252 /* Byteswap low halfword and sign extend. */
253 static void gen_revsh(TCGv var)
255 TCGv tmp = new_tmp();
256 tcg_gen_shri_i32(tmp, var, 8);
257 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
258 tcg_gen_shli_i32(var, var, 8);
259 tcg_gen_ext8s_i32(var, var);
260 tcg_gen_or_i32(var, var, tmp);
261 dead_tmp(tmp);
264 /* Unsigned bitfield extract. */
265 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
267 if (shift)
268 tcg_gen_shri_i32(var, var, shift);
269 tcg_gen_andi_i32(var, var, mask);
272 /* Signed bitfield extract. */
273 static void gen_sbfx(TCGv var, int shift, int width)
275 uint32_t signbit;
277 if (shift)
278 tcg_gen_sari_i32(var, var, shift);
279 if (shift + width < 32) {
280 signbit = 1u << (width - 1);
281 tcg_gen_andi_i32(var, var, (1u << width) - 1);
282 tcg_gen_xori_i32(var, var, signbit);
283 tcg_gen_subi_i32(var, var, signbit);
287 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
288 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
290 tcg_gen_andi_i32(val, val, mask);
291 tcg_gen_shli_i32(val, val, shift);
292 tcg_gen_andi_i32(base, base, ~(mask << shift));
293 tcg_gen_or_i32(dest, base, val);
296 /* Round the top 32 bits of a 64-bit value. */
297 static void gen_roundqd(TCGv a, TCGv b)
299 tcg_gen_shri_i32(a, a, 31);
300 tcg_gen_add_i32(a, a, b);
303 /* FIXME: Most targets have native widening multiplication.
304 It would be good to use that instead of a full wide multiply. */
305 /* 32x32->64 multiply. Marks inputs as dead. */
306 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
308 TCGv_i64 tmp1 = tcg_temp_new_i64();
309 TCGv_i64 tmp2 = tcg_temp_new_i64();
311 tcg_gen_extu_i32_i64(tmp1, a);
312 dead_tmp(a);
313 tcg_gen_extu_i32_i64(tmp2, b);
314 dead_tmp(b);
315 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
316 return tmp1;
319 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
321 TCGv_i64 tmp1 = tcg_temp_new_i64();
322 TCGv_i64 tmp2 = tcg_temp_new_i64();
324 tcg_gen_ext_i32_i64(tmp1, a);
325 dead_tmp(a);
326 tcg_gen_ext_i32_i64(tmp2, b);
327 dead_tmp(b);
328 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
329 return tmp1;
332 /* Unsigned 32x32->64 multiply. */
333 static void gen_mull(TCGv a, TCGv b)
335 TCGv_i64 tmp1 = tcg_temp_new_i64();
336 TCGv_i64 tmp2 = tcg_temp_new_i64();
338 tcg_gen_extu_i32_i64(tmp1, a);
339 tcg_gen_extu_i32_i64(tmp2, b);
340 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
341 tcg_gen_trunc_i64_i32(a, tmp1);
342 tcg_gen_shri_i64(tmp1, tmp1, 32);
343 tcg_gen_trunc_i64_i32(b, tmp1);
346 /* Signed 32x32->64 multiply. */
347 static void gen_imull(TCGv a, TCGv b)
349 TCGv_i64 tmp1 = tcg_temp_new_i64();
350 TCGv_i64 tmp2 = tcg_temp_new_i64();
352 tcg_gen_ext_i32_i64(tmp1, a);
353 tcg_gen_ext_i32_i64(tmp2, b);
354 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
355 tcg_gen_trunc_i64_i32(a, tmp1);
356 tcg_gen_shri_i64(tmp1, tmp1, 32);
357 tcg_gen_trunc_i64_i32(b, tmp1);
360 /* Swap low and high halfwords. */
361 static void gen_swap_half(TCGv var)
363 TCGv tmp = new_tmp();
364 tcg_gen_shri_i32(tmp, var, 16);
365 tcg_gen_shli_i32(var, var, 16);
366 tcg_gen_or_i32(var, var, tmp);
367 dead_tmp(tmp);
370 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
371 tmp = (t0 ^ t1) & 0x8000;
372 t0 &= ~0x8000;
373 t1 &= ~0x8000;
374 t0 = (t0 + t1) ^ tmp;
377 static void gen_add16(TCGv t0, TCGv t1)
379 TCGv tmp = new_tmp();
380 tcg_gen_xor_i32(tmp, t0, t1);
381 tcg_gen_andi_i32(tmp, tmp, 0x8000);
382 tcg_gen_andi_i32(t0, t0, ~0x8000);
383 tcg_gen_andi_i32(t1, t1, ~0x8000);
384 tcg_gen_add_i32(t0, t0, t1);
385 tcg_gen_xor_i32(t0, t0, tmp);
386 dead_tmp(tmp);
387 dead_tmp(t1);
390 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
392 /* Set CF to the top bit of var. */
393 static void gen_set_CF_bit31(TCGv var)
395 TCGv tmp = new_tmp();
396 tcg_gen_shri_i32(tmp, var, 31);
397 gen_set_CF(tmp);
398 dead_tmp(tmp);
401 /* Set N and Z flags from var. */
402 static inline void gen_logic_CC(TCGv var)
404 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
405 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
408 /* T0 += T1 + CF. */
409 static void gen_adc(TCGv t0, TCGv t1)
411 TCGv tmp;
412 tcg_gen_add_i32(t0, t0, t1);
413 tmp = load_cpu_field(CF);
414 tcg_gen_add_i32(t0, t0, tmp);
415 dead_tmp(tmp);
418 /* dest = T0 + T1 + CF. */
419 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
421 TCGv tmp;
422 tcg_gen_add_i32(dest, t0, t1);
423 tmp = load_cpu_field(CF);
424 tcg_gen_add_i32(dest, dest, tmp);
425 dead_tmp(tmp);
428 /* dest = T0 - T1 + CF - 1. */
429 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
431 TCGv tmp;
432 tcg_gen_sub_i32(dest, t0, t1);
433 tmp = load_cpu_field(CF);
434 tcg_gen_add_i32(dest, dest, tmp);
435 tcg_gen_subi_i32(dest, dest, 1);
436 dead_tmp(tmp);
439 /* T0 &= ~T1. Clobbers T1. */
440 /* FIXME: Implement bic natively. */
441 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
443 TCGv tmp = new_tmp();
444 tcg_gen_not_i32(tmp, t1);
445 tcg_gen_and_i32(dest, t0, tmp);
446 dead_tmp(tmp);
448 static inline void gen_op_bicl_T0_T1(void)
450 gen_op_notl_T1();
451 gen_op_andl_T0_T1();
454 /* FIXME: Implement this natively. */
455 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
457 /* FIXME: Implement this natively. */
458 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
460 TCGv tmp;
462 if (i == 0)
463 return;
465 tmp = new_tmp();
466 tcg_gen_shri_i32(tmp, t1, i);
467 tcg_gen_shli_i32(t1, t1, 32 - i);
468 tcg_gen_or_i32(t0, t1, tmp);
469 dead_tmp(tmp);
472 static void shifter_out_im(TCGv var, int shift)
474 TCGv tmp = new_tmp();
475 if (shift == 0) {
476 tcg_gen_andi_i32(tmp, var, 1);
477 } else {
478 tcg_gen_shri_i32(tmp, var, shift);
479 if (shift != 31)
480 tcg_gen_andi_i32(tmp, tmp, 1);
482 gen_set_CF(tmp);
483 dead_tmp(tmp);
486 /* Shift by immediate. Includes special handling for shift == 0. */
487 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
489 switch (shiftop) {
490 case 0: /* LSL */
491 if (shift != 0) {
492 if (flags)
493 shifter_out_im(var, 32 - shift);
494 tcg_gen_shli_i32(var, var, shift);
496 break;
497 case 1: /* LSR */
498 if (shift == 0) {
499 if (flags) {
500 tcg_gen_shri_i32(var, var, 31);
501 gen_set_CF(var);
503 tcg_gen_movi_i32(var, 0);
504 } else {
505 if (flags)
506 shifter_out_im(var, shift - 1);
507 tcg_gen_shri_i32(var, var, shift);
509 break;
510 case 2: /* ASR */
511 if (shift == 0)
512 shift = 32;
513 if (flags)
514 shifter_out_im(var, shift - 1);
515 if (shift == 32)
516 shift = 31;
517 tcg_gen_sari_i32(var, var, shift);
518 break;
519 case 3: /* ROR/RRX */
520 if (shift != 0) {
521 if (flags)
522 shifter_out_im(var, shift - 1);
523 tcg_gen_rori_i32(var, var, shift); break;
524 } else {
525 TCGv tmp = load_cpu_field(CF);
526 if (flags)
527 shifter_out_im(var, 0);
528 tcg_gen_shri_i32(var, var, 1);
529 tcg_gen_shli_i32(tmp, tmp, 31);
530 tcg_gen_or_i32(var, var, tmp);
531 dead_tmp(tmp);
536 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
537 TCGv shift, int flags)
539 if (flags) {
540 switch (shiftop) {
541 case 0: gen_helper_shl_cc(var, var, shift); break;
542 case 1: gen_helper_shr_cc(var, var, shift); break;
543 case 2: gen_helper_sar_cc(var, var, shift); break;
544 case 3: gen_helper_ror_cc(var, var, shift); break;
546 } else {
547 switch (shiftop) {
548 case 0: gen_helper_shl(var, var, shift); break;
549 case 1: gen_helper_shr(var, var, shift); break;
550 case 2: gen_helper_sar(var, var, shift); break;
551 case 3: gen_helper_ror(var, var, shift); break;
554 dead_tmp(shift);
557 #define PAS_OP(pfx) \
558 switch (op2) { \
559 case 0: gen_pas_helper(glue(pfx,add16)); break; \
560 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
561 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
562 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
563 case 4: gen_pas_helper(glue(pfx,add8)); break; \
564 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
566 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
568 TCGv_ptr tmp;
570 switch (op1) {
571 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
572 case 1:
573 tmp = tcg_temp_new_ptr();
574 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
575 PAS_OP(s)
576 break;
577 case 5:
578 tmp = tcg_temp_new_ptr();
579 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
580 PAS_OP(u)
581 break;
582 #undef gen_pas_helper
583 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
584 case 2:
585 PAS_OP(q);
586 break;
587 case 3:
588 PAS_OP(sh);
589 break;
590 case 6:
591 PAS_OP(uq);
592 break;
593 case 7:
594 PAS_OP(uh);
595 break;
596 #undef gen_pas_helper
599 #undef PAS_OP
601 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
602 #define PAS_OP(pfx) \
603 switch (op2) { \
604 case 0: gen_pas_helper(glue(pfx,add8)); break; \
605 case 1: gen_pas_helper(glue(pfx,add16)); break; \
606 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
607 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
608 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
609 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
611 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
613 TCGv_ptr tmp;
615 switch (op1) {
616 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
617 case 0:
618 tmp = tcg_temp_new_ptr();
619 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
620 PAS_OP(s)
621 break;
622 case 4:
623 tmp = tcg_temp_new_ptr();
624 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
625 PAS_OP(u)
626 break;
627 #undef gen_pas_helper
628 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
629 case 1:
630 PAS_OP(q);
631 break;
632 case 2:
633 PAS_OP(sh);
634 break;
635 case 5:
636 PAS_OP(uq);
637 break;
638 case 6:
639 PAS_OP(uh);
640 break;
641 #undef gen_pas_helper
644 #undef PAS_OP
646 static void gen_test_cc(int cc, int label)
648 TCGv tmp;
649 TCGv tmp2;
650 int inv;
652 switch (cc) {
653 case 0: /* eq: Z */
654 tmp = load_cpu_field(ZF);
655 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
656 break;
657 case 1: /* ne: !Z */
658 tmp = load_cpu_field(ZF);
659 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
660 break;
661 case 2: /* cs: C */
662 tmp = load_cpu_field(CF);
663 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
664 break;
665 case 3: /* cc: !C */
666 tmp = load_cpu_field(CF);
667 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
668 break;
669 case 4: /* mi: N */
670 tmp = load_cpu_field(NF);
671 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
672 break;
673 case 5: /* pl: !N */
674 tmp = load_cpu_field(NF);
675 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
676 break;
677 case 6: /* vs: V */
678 tmp = load_cpu_field(VF);
679 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
680 break;
681 case 7: /* vc: !V */
682 tmp = load_cpu_field(VF);
683 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
684 break;
685 case 8: /* hi: C && !Z */
686 inv = gen_new_label();
687 tmp = load_cpu_field(CF);
688 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
689 dead_tmp(tmp);
690 tmp = load_cpu_field(ZF);
691 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
692 gen_set_label(inv);
693 break;
694 case 9: /* ls: !C || Z */
695 tmp = load_cpu_field(CF);
696 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
697 dead_tmp(tmp);
698 tmp = load_cpu_field(ZF);
699 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
700 break;
701 case 10: /* ge: N == V -> N ^ V == 0 */
702 tmp = load_cpu_field(VF);
703 tmp2 = load_cpu_field(NF);
704 tcg_gen_xor_i32(tmp, tmp, tmp2);
705 dead_tmp(tmp2);
706 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
707 break;
708 case 11: /* lt: N != V -> N ^ V != 0 */
709 tmp = load_cpu_field(VF);
710 tmp2 = load_cpu_field(NF);
711 tcg_gen_xor_i32(tmp, tmp, tmp2);
712 dead_tmp(tmp2);
713 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
714 break;
715 case 12: /* gt: !Z && N == V */
716 inv = gen_new_label();
717 tmp = load_cpu_field(ZF);
718 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
719 dead_tmp(tmp);
720 tmp = load_cpu_field(VF);
721 tmp2 = load_cpu_field(NF);
722 tcg_gen_xor_i32(tmp, tmp, tmp2);
723 dead_tmp(tmp2);
724 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
725 gen_set_label(inv);
726 break;
727 case 13: /* le: Z || N != V */
728 tmp = load_cpu_field(ZF);
729 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
730 dead_tmp(tmp);
731 tmp = load_cpu_field(VF);
732 tmp2 = load_cpu_field(NF);
733 tcg_gen_xor_i32(tmp, tmp, tmp2);
734 dead_tmp(tmp2);
735 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
736 break;
737 default:
738 fprintf(stderr, "Bad condition code 0x%x\n", cc);
739 abort();
741 dead_tmp(tmp);
744 static const uint8_t table_logic_cc[16] = {
745 1, /* and */
746 1, /* xor */
747 0, /* sub */
748 0, /* rsb */
749 0, /* add */
750 0, /* adc */
751 0, /* sbc */
752 0, /* rsc */
753 1, /* andl */
754 1, /* xorl */
755 0, /* cmp */
756 0, /* cmn */
757 1, /* orr */
758 1, /* mov */
759 1, /* bic */
760 1, /* mvn */
763 /* Set PC and Thumb state from an immediate address. */
764 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
766 TCGv tmp;
768 s->is_jmp = DISAS_UPDATE;
769 if (s->thumb != (addr & 1)) {
770 tmp = new_tmp();
771 tcg_gen_movi_i32(tmp, addr & 1);
772 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
773 dead_tmp(tmp);
775 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
778 /* Set PC and Thumb state from var. var is marked as dead. */
779 static inline void gen_bx(DisasContext *s, TCGv var)
781 s->is_jmp = DISAS_UPDATE;
782 tcg_gen_andi_i32(cpu_R[15], var, ~1);
783 tcg_gen_andi_i32(var, var, 1);
784 store_cpu_field(var, thumb);
787 /* Variant of store_reg which uses branch&exchange logic when storing
788 to r15 in ARM architecture v7 and above. The source must be a temporary
789 and will be marked as dead. */
790 static inline void store_reg_bx(CPUState *env, DisasContext *s,
791 int reg, TCGv var)
793 if (reg == 15 && ENABLE_ARCH_7) {
794 gen_bx(s, var);
795 } else {
796 store_reg(s, reg, var);
800 static inline TCGv gen_ld8s(TCGv addr, int index)
802 TCGv tmp = new_tmp();
803 tcg_gen_qemu_ld8s(tmp, addr, index);
804 return tmp;
806 static inline TCGv gen_ld8u(TCGv addr, int index)
808 TCGv tmp = new_tmp();
809 tcg_gen_qemu_ld8u(tmp, addr, index);
810 return tmp;
812 static inline TCGv gen_ld16s(TCGv addr, int index)
814 TCGv tmp = new_tmp();
815 tcg_gen_qemu_ld16s(tmp, addr, index);
816 return tmp;
818 static inline TCGv gen_ld16u(TCGv addr, int index)
820 TCGv tmp = new_tmp();
821 tcg_gen_qemu_ld16u(tmp, addr, index);
822 return tmp;
824 static inline TCGv gen_ld32(TCGv addr, int index)
826 TCGv tmp = new_tmp();
827 tcg_gen_qemu_ld32u(tmp, addr, index);
828 return tmp;
830 static inline void gen_st8(TCGv val, TCGv addr, int index)
832 tcg_gen_qemu_st8(val, addr, index);
833 dead_tmp(val);
835 static inline void gen_st16(TCGv val, TCGv addr, int index)
837 tcg_gen_qemu_st16(val, addr, index);
838 dead_tmp(val);
840 static inline void gen_st32(TCGv val, TCGv addr, int index)
842 tcg_gen_qemu_st32(val, addr, index);
843 dead_tmp(val);
846 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
848 load_reg_var(s, cpu_T[0], reg);
851 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
853 load_reg_var(s, cpu_T[1], reg);
856 static inline void gen_set_pc_im(uint32_t val)
858 tcg_gen_movi_i32(cpu_R[15], val);
861 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
863 TCGv tmp;
864 if (reg == 15) {
865 tmp = new_tmp();
866 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
867 } else {
868 tmp = cpu_T[t];
870 tcg_gen_mov_i32(cpu_R[reg], tmp);
871 if (reg == 15) {
872 dead_tmp(tmp);
873 s->is_jmp = DISAS_JUMP;
877 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
879 gen_movl_reg_TN(s, reg, 0);
882 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
884 gen_movl_reg_TN(s, reg, 1);
887 /* Force a TB lookup after an instruction that changes the CPU state. */
888 static inline void gen_lookup_tb(DisasContext *s)
890 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
891 s->is_jmp = DISAS_UPDATE;
894 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
895 TCGv var)
897 int val, rm, shift, shiftop;
898 TCGv offset;
900 if (!(insn & (1 << 25))) {
901 /* immediate */
902 val = insn & 0xfff;
903 if (!(insn & (1 << 23)))
904 val = -val;
905 if (val != 0)
906 tcg_gen_addi_i32(var, var, val);
907 } else {
908 /* shift/register */
909 rm = (insn) & 0xf;
910 shift = (insn >> 7) & 0x1f;
911 shiftop = (insn >> 5) & 3;
912 offset = load_reg(s, rm);
913 gen_arm_shift_im(offset, shiftop, shift, 0);
914 if (!(insn & (1 << 23)))
915 tcg_gen_sub_i32(var, var, offset);
916 else
917 tcg_gen_add_i32(var, var, offset);
918 dead_tmp(offset);
922 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
923 int extra, TCGv var)
925 int val, rm;
926 TCGv offset;
928 if (insn & (1 << 22)) {
929 /* immediate */
930 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
931 if (!(insn & (1 << 23)))
932 val = -val;
933 val += extra;
934 if (val != 0)
935 tcg_gen_addi_i32(var, var, val);
936 } else {
937 /* register */
938 if (extra)
939 tcg_gen_addi_i32(var, var, extra);
940 rm = (insn) & 0xf;
941 offset = load_reg(s, rm);
942 if (!(insn & (1 << 23)))
943 tcg_gen_sub_i32(var, var, offset);
944 else
945 tcg_gen_add_i32(var, var, offset);
946 dead_tmp(offset);
950 #define VFP_OP2(name) \
951 static inline void gen_vfp_##name(int dp) \
953 if (dp) \
954 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
955 else \
956 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
959 VFP_OP2(add)
960 VFP_OP2(sub)
961 VFP_OP2(mul)
962 VFP_OP2(div)
964 #undef VFP_OP2
966 static inline void gen_vfp_abs(int dp)
968 if (dp)
969 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
970 else
971 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
974 static inline void gen_vfp_neg(int dp)
976 if (dp)
977 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
978 else
979 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
982 static inline void gen_vfp_sqrt(int dp)
984 if (dp)
985 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
986 else
987 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
990 static inline void gen_vfp_cmp(int dp)
992 if (dp)
993 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
994 else
995 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
998 static inline void gen_vfp_cmpe(int dp)
1000 if (dp)
1001 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1002 else
1003 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1006 static inline void gen_vfp_F1_ld0(int dp)
1008 if (dp)
1009 tcg_gen_movi_i64(cpu_F1d, 0);
1010 else
1011 tcg_gen_movi_i32(cpu_F1s, 0);
1014 static inline void gen_vfp_uito(int dp)
1016 if (dp)
1017 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1018 else
1019 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1022 static inline void gen_vfp_sito(int dp)
1024 if (dp)
1025 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1026 else
1027 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1030 static inline void gen_vfp_toui(int dp)
1032 if (dp)
1033 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1034 else
1035 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1038 static inline void gen_vfp_touiz(int dp)
1040 if (dp)
1041 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1042 else
1043 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1046 static inline void gen_vfp_tosi(int dp)
1048 if (dp)
1049 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1050 else
1051 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1054 static inline void gen_vfp_tosiz(int dp)
1056 if (dp)
1057 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1058 else
1059 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1062 #define VFP_GEN_FIX(name) \
1063 static inline void gen_vfp_##name(int dp, int shift) \
1065 if (dp) \
1066 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1067 else \
1068 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1070 VFP_GEN_FIX(tosh)
1071 VFP_GEN_FIX(tosl)
1072 VFP_GEN_FIX(touh)
1073 VFP_GEN_FIX(toul)
1074 VFP_GEN_FIX(shto)
1075 VFP_GEN_FIX(slto)
1076 VFP_GEN_FIX(uhto)
1077 VFP_GEN_FIX(ulto)
1078 #undef VFP_GEN_FIX
1080 static inline void gen_vfp_ld(DisasContext *s, int dp)
1082 if (dp)
1083 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1084 else
1085 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1088 static inline void gen_vfp_st(DisasContext *s, int dp)
1090 if (dp)
1091 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1092 else
1093 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1096 static inline long
1097 vfp_reg_offset (int dp, int reg)
1099 if (dp)
1100 return offsetof(CPUARMState, vfp.regs[reg]);
1101 else if (reg & 1) {
1102 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1103 + offsetof(CPU_DoubleU, l.upper);
1104 } else {
1105 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1106 + offsetof(CPU_DoubleU, l.lower);
1110 /* Return the offset of a 32-bit piece of a NEON register.
1111 zero is the least significant end of the register. */
1112 static inline long
1113 neon_reg_offset (int reg, int n)
1115 int sreg;
1116 sreg = reg * 2 + n;
1117 return vfp_reg_offset(0, sreg);
1120 /* FIXME: Remove these. */
1121 #define neon_T0 cpu_T[0]
1122 #define neon_T1 cpu_T[1]
1123 #define NEON_GET_REG(T, reg, n) \
1124 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1125 #define NEON_SET_REG(T, reg, n) \
1126 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1128 static TCGv neon_load_reg(int reg, int pass)
1130 TCGv tmp = new_tmp();
1131 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1132 return tmp;
1135 static void neon_store_reg(int reg, int pass, TCGv var)
1137 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1138 dead_tmp(var);
1141 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1143 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1146 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1148 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1151 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1152 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1153 #define tcg_gen_st_f32 tcg_gen_st_i32
1154 #define tcg_gen_st_f64 tcg_gen_st_i64
1156 static inline void gen_mov_F0_vreg(int dp, int reg)
1158 if (dp)
1159 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1160 else
1161 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1164 static inline void gen_mov_F1_vreg(int dp, int reg)
1166 if (dp)
1167 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1168 else
1169 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1172 static inline void gen_mov_vreg_F0(int dp, int reg)
1174 if (dp)
1175 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1176 else
1177 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1180 #define ARM_CP_RW_BIT (1 << 20)
1182 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1184 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1187 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1189 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1192 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1194 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1197 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1199 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1202 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1204 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1207 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1209 iwmmxt_store_reg(cpu_M0, rn);
1212 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1214 iwmmxt_load_reg(cpu_M0, rn);
1217 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1219 iwmmxt_load_reg(cpu_V1, rn);
1220 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1223 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1225 iwmmxt_load_reg(cpu_V1, rn);
1226 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1229 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1231 iwmmxt_load_reg(cpu_V1, rn);
1232 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1235 #define IWMMXT_OP(name) \
1236 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1238 iwmmxt_load_reg(cpu_V1, rn); \
1239 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1242 #define IWMMXT_OP_ENV(name) \
1243 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1245 iwmmxt_load_reg(cpu_V1, rn); \
1246 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1249 #define IWMMXT_OP_ENV_SIZE(name) \
1250 IWMMXT_OP_ENV(name##b) \
1251 IWMMXT_OP_ENV(name##w) \
1252 IWMMXT_OP_ENV(name##l)
1254 #define IWMMXT_OP_ENV1(name) \
1255 static inline void gen_op_iwmmxt_##name##_M0(void) \
1257 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1260 IWMMXT_OP(maddsq)
1261 IWMMXT_OP(madduq)
1262 IWMMXT_OP(sadb)
1263 IWMMXT_OP(sadw)
1264 IWMMXT_OP(mulslw)
1265 IWMMXT_OP(mulshw)
1266 IWMMXT_OP(mululw)
1267 IWMMXT_OP(muluhw)
1268 IWMMXT_OP(macsw)
1269 IWMMXT_OP(macuw)
1271 IWMMXT_OP_ENV_SIZE(unpackl)
1272 IWMMXT_OP_ENV_SIZE(unpackh)
1274 IWMMXT_OP_ENV1(unpacklub)
1275 IWMMXT_OP_ENV1(unpackluw)
1276 IWMMXT_OP_ENV1(unpacklul)
1277 IWMMXT_OP_ENV1(unpackhub)
1278 IWMMXT_OP_ENV1(unpackhuw)
1279 IWMMXT_OP_ENV1(unpackhul)
1280 IWMMXT_OP_ENV1(unpacklsb)
1281 IWMMXT_OP_ENV1(unpacklsw)
1282 IWMMXT_OP_ENV1(unpacklsl)
1283 IWMMXT_OP_ENV1(unpackhsb)
1284 IWMMXT_OP_ENV1(unpackhsw)
1285 IWMMXT_OP_ENV1(unpackhsl)
1287 IWMMXT_OP_ENV_SIZE(cmpeq)
1288 IWMMXT_OP_ENV_SIZE(cmpgtu)
1289 IWMMXT_OP_ENV_SIZE(cmpgts)
1291 IWMMXT_OP_ENV_SIZE(mins)
1292 IWMMXT_OP_ENV_SIZE(minu)
1293 IWMMXT_OP_ENV_SIZE(maxs)
1294 IWMMXT_OP_ENV_SIZE(maxu)
1296 IWMMXT_OP_ENV_SIZE(subn)
1297 IWMMXT_OP_ENV_SIZE(addn)
1298 IWMMXT_OP_ENV_SIZE(subu)
1299 IWMMXT_OP_ENV_SIZE(addu)
1300 IWMMXT_OP_ENV_SIZE(subs)
1301 IWMMXT_OP_ENV_SIZE(adds)
1303 IWMMXT_OP_ENV(avgb0)
1304 IWMMXT_OP_ENV(avgb1)
1305 IWMMXT_OP_ENV(avgw0)
1306 IWMMXT_OP_ENV(avgw1)
1308 IWMMXT_OP(msadb)
1310 IWMMXT_OP_ENV(packuw)
1311 IWMMXT_OP_ENV(packul)
1312 IWMMXT_OP_ENV(packuq)
1313 IWMMXT_OP_ENV(packsw)
1314 IWMMXT_OP_ENV(packsl)
1315 IWMMXT_OP_ENV(packsq)
1317 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1319 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1322 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1324 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1327 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1329 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1332 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1334 iwmmxt_load_reg(cpu_V1, rn);
1335 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1338 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1340 TCGv tmp = tcg_const_i32(shift);
1341 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1344 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1346 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1347 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1348 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1351 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1353 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1354 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1355 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1358 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1360 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1361 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1362 if (mask != ~0u)
1363 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1366 static void gen_op_iwmmxt_set_mup(void)
1368 TCGv tmp;
1369 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1370 tcg_gen_ori_i32(tmp, tmp, 2);
1371 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1374 static void gen_op_iwmmxt_set_cup(void)
1376 TCGv tmp;
1377 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1378 tcg_gen_ori_i32(tmp, tmp, 1);
1379 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1382 static void gen_op_iwmmxt_setpsr_nz(void)
1384 TCGv tmp = new_tmp();
1385 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1386 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1389 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1391 iwmmxt_load_reg(cpu_V1, rn);
1392 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1393 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1397 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1399 iwmmxt_load_reg(cpu_V0, rn);
1400 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1401 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1402 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1405 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1407 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1408 iwmmxt_store_reg(cpu_V0, rn);
1411 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1413 int rd;
1414 uint32_t offset;
1416 rd = (insn >> 16) & 0xf;
1417 gen_movl_T1_reg(s, rd);
1419 offset = (insn & 0xff) << ((insn >> 7) & 2);
1420 if (insn & (1 << 24)) {
1421 /* Pre indexed */
1422 if (insn & (1 << 23))
1423 gen_op_addl_T1_im(offset);
1424 else
1425 gen_op_addl_T1_im(-offset);
1427 if (insn & (1 << 21))
1428 gen_movl_reg_T1(s, rd);
1429 } else if (insn & (1 << 21)) {
1430 /* Post indexed */
1431 if (insn & (1 << 23))
1432 gen_op_movl_T0_im(offset);
1433 else
1434 gen_op_movl_T0_im(- offset);
1435 gen_op_addl_T0_T1();
1436 gen_movl_reg_T0(s, rd);
1437 } else if (!(insn & (1 << 23)))
1438 return 1;
1439 return 0;
1442 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1444 int rd = (insn >> 0) & 0xf;
1446 if (insn & (1 << 8))
1447 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1448 return 1;
1449 else
1450 gen_op_iwmmxt_movl_T0_wCx(rd);
1451 else
1452 gen_iwmmxt_movl_T0_T1_wRn(rd);
1454 gen_op_movl_T1_im(mask);
1455 gen_op_andl_T0_T1();
1456 return 0;
1459 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1460 (ie. an undefined instruction). */
1461 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1463 int rd, wrd;
1464 int rdhi, rdlo, rd0, rd1, i;
1465 TCGv tmp;
1467 if ((insn & 0x0e000e00) == 0x0c000000) {
1468 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1469 wrd = insn & 0xf;
1470 rdlo = (insn >> 12) & 0xf;
1471 rdhi = (insn >> 16) & 0xf;
1472 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1473 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1474 gen_movl_reg_T0(s, rdlo);
1475 gen_movl_reg_T1(s, rdhi);
1476 } else { /* TMCRR */
1477 gen_movl_T0_reg(s, rdlo);
1478 gen_movl_T1_reg(s, rdhi);
1479 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1480 gen_op_iwmmxt_set_mup();
1482 return 0;
1485 wrd = (insn >> 12) & 0xf;
1486 if (gen_iwmmxt_address(s, insn))
1487 return 1;
1488 if (insn & ARM_CP_RW_BIT) {
1489 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1490 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1491 tcg_gen_mov_i32(cpu_T[0], tmp);
1492 dead_tmp(tmp);
1493 gen_op_iwmmxt_movl_wCx_T0(wrd);
1494 } else {
1495 i = 1;
1496 if (insn & (1 << 8)) {
1497 if (insn & (1 << 22)) { /* WLDRD */
1498 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1499 i = 0;
1500 } else { /* WLDRW wRd */
1501 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1503 } else {
1504 if (insn & (1 << 22)) { /* WLDRH */
1505 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1506 } else { /* WLDRB */
1507 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1510 if (i) {
1511 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1512 dead_tmp(tmp);
1514 gen_op_iwmmxt_movq_wRn_M0(wrd);
1516 } else {
1517 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1518 gen_op_iwmmxt_movl_T0_wCx(wrd);
1519 tmp = new_tmp();
1520 tcg_gen_mov_i32(tmp, cpu_T[0]);
1521 gen_st32(tmp, cpu_T[1], IS_USER(s));
1522 } else {
1523 gen_op_iwmmxt_movq_M0_wRn(wrd);
1524 tmp = new_tmp();
1525 if (insn & (1 << 8)) {
1526 if (insn & (1 << 22)) { /* WSTRD */
1527 dead_tmp(tmp);
1528 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1529 } else { /* WSTRW wRd */
1530 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1531 gen_st32(tmp, cpu_T[1], IS_USER(s));
1533 } else {
1534 if (insn & (1 << 22)) { /* WSTRH */
1535 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1536 gen_st16(tmp, cpu_T[1], IS_USER(s));
1537 } else { /* WSTRB */
1538 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1539 gen_st8(tmp, cpu_T[1], IS_USER(s));
1544 return 0;
1547 if ((insn & 0x0f000000) != 0x0e000000)
1548 return 1;
1550 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1551 case 0x000: /* WOR */
1552 wrd = (insn >> 12) & 0xf;
1553 rd0 = (insn >> 0) & 0xf;
1554 rd1 = (insn >> 16) & 0xf;
1555 gen_op_iwmmxt_movq_M0_wRn(rd0);
1556 gen_op_iwmmxt_orq_M0_wRn(rd1);
1557 gen_op_iwmmxt_setpsr_nz();
1558 gen_op_iwmmxt_movq_wRn_M0(wrd);
1559 gen_op_iwmmxt_set_mup();
1560 gen_op_iwmmxt_set_cup();
1561 break;
1562 case 0x011: /* TMCR */
1563 if (insn & 0xf)
1564 return 1;
1565 rd = (insn >> 12) & 0xf;
1566 wrd = (insn >> 16) & 0xf;
1567 switch (wrd) {
1568 case ARM_IWMMXT_wCID:
1569 case ARM_IWMMXT_wCASF:
1570 break;
1571 case ARM_IWMMXT_wCon:
1572 gen_op_iwmmxt_set_cup();
1573 /* Fall through. */
1574 case ARM_IWMMXT_wCSSF:
1575 gen_op_iwmmxt_movl_T0_wCx(wrd);
1576 gen_movl_T1_reg(s, rd);
1577 gen_op_bicl_T0_T1();
1578 gen_op_iwmmxt_movl_wCx_T0(wrd);
1579 break;
1580 case ARM_IWMMXT_wCGR0:
1581 case ARM_IWMMXT_wCGR1:
1582 case ARM_IWMMXT_wCGR2:
1583 case ARM_IWMMXT_wCGR3:
1584 gen_op_iwmmxt_set_cup();
1585 gen_movl_reg_T0(s, rd);
1586 gen_op_iwmmxt_movl_wCx_T0(wrd);
1587 break;
1588 default:
1589 return 1;
1591 break;
1592 case 0x100: /* WXOR */
1593 wrd = (insn >> 12) & 0xf;
1594 rd0 = (insn >> 0) & 0xf;
1595 rd1 = (insn >> 16) & 0xf;
1596 gen_op_iwmmxt_movq_M0_wRn(rd0);
1597 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1598 gen_op_iwmmxt_setpsr_nz();
1599 gen_op_iwmmxt_movq_wRn_M0(wrd);
1600 gen_op_iwmmxt_set_mup();
1601 gen_op_iwmmxt_set_cup();
1602 break;
1603 case 0x111: /* TMRC */
1604 if (insn & 0xf)
1605 return 1;
1606 rd = (insn >> 12) & 0xf;
1607 wrd = (insn >> 16) & 0xf;
1608 gen_op_iwmmxt_movl_T0_wCx(wrd);
1609 gen_movl_reg_T0(s, rd);
1610 break;
1611 case 0x300: /* WANDN */
1612 wrd = (insn >> 12) & 0xf;
1613 rd0 = (insn >> 0) & 0xf;
1614 rd1 = (insn >> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0);
1616 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1617 gen_op_iwmmxt_andq_M0_wRn(rd1);
1618 gen_op_iwmmxt_setpsr_nz();
1619 gen_op_iwmmxt_movq_wRn_M0(wrd);
1620 gen_op_iwmmxt_set_mup();
1621 gen_op_iwmmxt_set_cup();
1622 break;
1623 case 0x200: /* WAND */
1624 wrd = (insn >> 12) & 0xf;
1625 rd0 = (insn >> 0) & 0xf;
1626 rd1 = (insn >> 16) & 0xf;
1627 gen_op_iwmmxt_movq_M0_wRn(rd0);
1628 gen_op_iwmmxt_andq_M0_wRn(rd1);
1629 gen_op_iwmmxt_setpsr_nz();
1630 gen_op_iwmmxt_movq_wRn_M0(wrd);
1631 gen_op_iwmmxt_set_mup();
1632 gen_op_iwmmxt_set_cup();
1633 break;
1634 case 0x810: case 0xa10: /* WMADD */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 0) & 0xf;
1637 rd1 = (insn >> 16) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 if (insn & (1 << 21))
1640 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1641 else
1642 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1643 gen_op_iwmmxt_movq_wRn_M0(wrd);
1644 gen_op_iwmmxt_set_mup();
1645 break;
1646 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1647 wrd = (insn >> 12) & 0xf;
1648 rd0 = (insn >> 16) & 0xf;
1649 rd1 = (insn >> 0) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0);
1651 switch ((insn >> 22) & 3) {
1652 case 0:
1653 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1654 break;
1655 case 1:
1656 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1657 break;
1658 case 2:
1659 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1660 break;
1661 case 3:
1662 return 1;
1664 gen_op_iwmmxt_movq_wRn_M0(wrd);
1665 gen_op_iwmmxt_set_mup();
1666 gen_op_iwmmxt_set_cup();
1667 break;
1668 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1669 wrd = (insn >> 12) & 0xf;
1670 rd0 = (insn >> 16) & 0xf;
1671 rd1 = (insn >> 0) & 0xf;
1672 gen_op_iwmmxt_movq_M0_wRn(rd0);
1673 switch ((insn >> 22) & 3) {
1674 case 0:
1675 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1676 break;
1677 case 1:
1678 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1679 break;
1680 case 2:
1681 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1682 break;
1683 case 3:
1684 return 1;
1686 gen_op_iwmmxt_movq_wRn_M0(wrd);
1687 gen_op_iwmmxt_set_mup();
1688 gen_op_iwmmxt_set_cup();
1689 break;
1690 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1691 wrd = (insn >> 12) & 0xf;
1692 rd0 = (insn >> 16) & 0xf;
1693 rd1 = (insn >> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0);
1695 if (insn & (1 << 22))
1696 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1697 else
1698 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1699 if (!(insn & (1 << 20)))
1700 gen_op_iwmmxt_addl_M0_wRn(wrd);
1701 gen_op_iwmmxt_movq_wRn_M0(wrd);
1702 gen_op_iwmmxt_set_mup();
1703 break;
1704 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1705 wrd = (insn >> 12) & 0xf;
1706 rd0 = (insn >> 16) & 0xf;
1707 rd1 = (insn >> 0) & 0xf;
1708 gen_op_iwmmxt_movq_M0_wRn(rd0);
1709 if (insn & (1 << 21)) {
1710 if (insn & (1 << 20))
1711 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1712 else
1713 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1714 } else {
1715 if (insn & (1 << 20))
1716 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1717 else
1718 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1720 gen_op_iwmmxt_movq_wRn_M0(wrd);
1721 gen_op_iwmmxt_set_mup();
1722 break;
1723 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1724 wrd = (insn >> 12) & 0xf;
1725 rd0 = (insn >> 16) & 0xf;
1726 rd1 = (insn >> 0) & 0xf;
1727 gen_op_iwmmxt_movq_M0_wRn(rd0);
1728 if (insn & (1 << 21))
1729 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1730 else
1731 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1732 if (!(insn & (1 << 20))) {
1733 iwmmxt_load_reg(cpu_V1, wrd);
1734 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1736 gen_op_iwmmxt_movq_wRn_M0(wrd);
1737 gen_op_iwmmxt_set_mup();
1738 break;
1739 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1740 wrd = (insn >> 12) & 0xf;
1741 rd0 = (insn >> 16) & 0xf;
1742 rd1 = (insn >> 0) & 0xf;
1743 gen_op_iwmmxt_movq_M0_wRn(rd0);
1744 switch ((insn >> 22) & 3) {
1745 case 0:
1746 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1747 break;
1748 case 1:
1749 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1750 break;
1751 case 2:
1752 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1753 break;
1754 case 3:
1755 return 1;
1757 gen_op_iwmmxt_movq_wRn_M0(wrd);
1758 gen_op_iwmmxt_set_mup();
1759 gen_op_iwmmxt_set_cup();
1760 break;
1761 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1762 wrd = (insn >> 12) & 0xf;
1763 rd0 = (insn >> 16) & 0xf;
1764 rd1 = (insn >> 0) & 0xf;
1765 gen_op_iwmmxt_movq_M0_wRn(rd0);
1766 if (insn & (1 << 22)) {
1767 if (insn & (1 << 20))
1768 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1769 else
1770 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1771 } else {
1772 if (insn & (1 << 20))
1773 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1774 else
1775 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1777 gen_op_iwmmxt_movq_wRn_M0(wrd);
1778 gen_op_iwmmxt_set_mup();
1779 gen_op_iwmmxt_set_cup();
1780 break;
1781 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1782 wrd = (insn >> 12) & 0xf;
1783 rd0 = (insn >> 16) & 0xf;
1784 rd1 = (insn >> 0) & 0xf;
1785 gen_op_iwmmxt_movq_M0_wRn(rd0);
1786 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1787 gen_op_movl_T1_im(7);
1788 gen_op_andl_T0_T1();
1789 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1790 gen_op_iwmmxt_movq_wRn_M0(wrd);
1791 gen_op_iwmmxt_set_mup();
1792 break;
1793 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1794 rd = (insn >> 12) & 0xf;
1795 wrd = (insn >> 16) & 0xf;
1796 gen_movl_T0_reg(s, rd);
1797 gen_op_iwmmxt_movq_M0_wRn(wrd);
1798 switch ((insn >> 6) & 3) {
1799 case 0:
1800 gen_op_movl_T1_im(0xff);
1801 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1802 break;
1803 case 1:
1804 gen_op_movl_T1_im(0xffff);
1805 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1806 break;
1807 case 2:
1808 gen_op_movl_T1_im(0xffffffff);
1809 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1810 break;
1811 case 3:
1812 return 1;
1814 gen_op_iwmmxt_movq_wRn_M0(wrd);
1815 gen_op_iwmmxt_set_mup();
1816 break;
1817 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1818 rd = (insn >> 12) & 0xf;
1819 wrd = (insn >> 16) & 0xf;
1820 if (rd == 15)
1821 return 1;
1822 gen_op_iwmmxt_movq_M0_wRn(wrd);
1823 switch ((insn >> 22) & 3) {
1824 case 0:
1825 if (insn & 8)
1826 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1827 else {
1828 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1830 break;
1831 case 1:
1832 if (insn & 8)
1833 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1834 else {
1835 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1837 break;
1838 case 2:
1839 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1840 break;
1841 case 3:
1842 return 1;
1844 gen_movl_reg_T0(s, rd);
1845 break;
1846 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1847 if ((insn & 0x000ff008) != 0x0003f000)
1848 return 1;
1849 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1850 switch ((insn >> 22) & 3) {
1851 case 0:
1852 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1853 break;
1854 case 1:
1855 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1856 break;
1857 case 2:
1858 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1859 break;
1860 case 3:
1861 return 1;
1863 gen_op_shll_T1_im(28);
1864 gen_set_nzcv(cpu_T[1]);
1865 break;
1866 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1867 rd = (insn >> 12) & 0xf;
1868 wrd = (insn >> 16) & 0xf;
1869 gen_movl_T0_reg(s, rd);
1870 switch ((insn >> 6) & 3) {
1871 case 0:
1872 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1873 break;
1874 case 1:
1875 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1876 break;
1877 case 2:
1878 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1879 break;
1880 case 3:
1881 return 1;
1883 gen_op_iwmmxt_movq_wRn_M0(wrd);
1884 gen_op_iwmmxt_set_mup();
1885 break;
1886 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1887 if ((insn & 0x000ff00f) != 0x0003f000)
1888 return 1;
1889 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1890 gen_op_movl_T0_T1();
1891 switch ((insn >> 22) & 3) {
1892 case 0:
1893 for (i = 0; i < 7; i ++) {
1894 gen_op_shll_T1_im(4);
1895 gen_op_andl_T0_T1();
1897 break;
1898 case 1:
1899 for (i = 0; i < 3; i ++) {
1900 gen_op_shll_T1_im(8);
1901 gen_op_andl_T0_T1();
1903 break;
1904 case 2:
1905 gen_op_shll_T1_im(16);
1906 gen_op_andl_T0_T1();
1907 break;
1908 case 3:
1909 return 1;
1911 gen_set_nzcv(cpu_T[0]);
1912 break;
1913 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1914 wrd = (insn >> 12) & 0xf;
1915 rd0 = (insn >> 16) & 0xf;
1916 gen_op_iwmmxt_movq_M0_wRn(rd0);
1917 switch ((insn >> 22) & 3) {
1918 case 0:
1919 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1920 break;
1921 case 1:
1922 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1923 break;
1924 case 2:
1925 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1926 break;
1927 case 3:
1928 return 1;
1930 gen_op_iwmmxt_movq_wRn_M0(wrd);
1931 gen_op_iwmmxt_set_mup();
1932 break;
1933 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1934 if ((insn & 0x000ff00f) != 0x0003f000)
1935 return 1;
1936 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1937 gen_op_movl_T0_T1();
1938 switch ((insn >> 22) & 3) {
1939 case 0:
1940 for (i = 0; i < 7; i ++) {
1941 gen_op_shll_T1_im(4);
1942 gen_op_orl_T0_T1();
1944 break;
1945 case 1:
1946 for (i = 0; i < 3; i ++) {
1947 gen_op_shll_T1_im(8);
1948 gen_op_orl_T0_T1();
1950 break;
1951 case 2:
1952 gen_op_shll_T1_im(16);
1953 gen_op_orl_T0_T1();
1954 break;
1955 case 3:
1956 return 1;
1958 gen_set_nzcv(cpu_T[0]);
1959 break;
1960 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1961 rd = (insn >> 12) & 0xf;
1962 rd0 = (insn >> 16) & 0xf;
1963 if ((insn & 0xf) != 0)
1964 return 1;
1965 gen_op_iwmmxt_movq_M0_wRn(rd0);
1966 switch ((insn >> 22) & 3) {
1967 case 0:
1968 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
1969 break;
1970 case 1:
1971 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
1972 break;
1973 case 2:
1974 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
1975 break;
1976 case 3:
1977 return 1;
1979 gen_movl_reg_T0(s, rd);
1980 break;
1981 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1982 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1983 wrd = (insn >> 12) & 0xf;
1984 rd0 = (insn >> 16) & 0xf;
1985 rd1 = (insn >> 0) & 0xf;
1986 gen_op_iwmmxt_movq_M0_wRn(rd0);
1987 switch ((insn >> 22) & 3) {
1988 case 0:
1989 if (insn & (1 << 21))
1990 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1991 else
1992 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1993 break;
1994 case 1:
1995 if (insn & (1 << 21))
1996 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1997 else
1998 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1999 break;
2000 case 2:
2001 if (insn & (1 << 21))
2002 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2003 else
2004 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2005 break;
2006 case 3:
2007 return 1;
2009 gen_op_iwmmxt_movq_wRn_M0(wrd);
2010 gen_op_iwmmxt_set_mup();
2011 gen_op_iwmmxt_set_cup();
2012 break;
2013 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2014 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2015 wrd = (insn >> 12) & 0xf;
2016 rd0 = (insn >> 16) & 0xf;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0);
2018 switch ((insn >> 22) & 3) {
2019 case 0:
2020 if (insn & (1 << 21))
2021 gen_op_iwmmxt_unpacklsb_M0();
2022 else
2023 gen_op_iwmmxt_unpacklub_M0();
2024 break;
2025 case 1:
2026 if (insn & (1 << 21))
2027 gen_op_iwmmxt_unpacklsw_M0();
2028 else
2029 gen_op_iwmmxt_unpackluw_M0();
2030 break;
2031 case 2:
2032 if (insn & (1 << 21))
2033 gen_op_iwmmxt_unpacklsl_M0();
2034 else
2035 gen_op_iwmmxt_unpacklul_M0();
2036 break;
2037 case 3:
2038 return 1;
2040 gen_op_iwmmxt_movq_wRn_M0(wrd);
2041 gen_op_iwmmxt_set_mup();
2042 gen_op_iwmmxt_set_cup();
2043 break;
2044 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2045 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2046 wrd = (insn >> 12) & 0xf;
2047 rd0 = (insn >> 16) & 0xf;
2048 gen_op_iwmmxt_movq_M0_wRn(rd0);
2049 switch ((insn >> 22) & 3) {
2050 case 0:
2051 if (insn & (1 << 21))
2052 gen_op_iwmmxt_unpackhsb_M0();
2053 else
2054 gen_op_iwmmxt_unpackhub_M0();
2055 break;
2056 case 1:
2057 if (insn & (1 << 21))
2058 gen_op_iwmmxt_unpackhsw_M0();
2059 else
2060 gen_op_iwmmxt_unpackhuw_M0();
2061 break;
2062 case 2:
2063 if (insn & (1 << 21))
2064 gen_op_iwmmxt_unpackhsl_M0();
2065 else
2066 gen_op_iwmmxt_unpackhul_M0();
2067 break;
2068 case 3:
2069 return 1;
2071 gen_op_iwmmxt_movq_wRn_M0(wrd);
2072 gen_op_iwmmxt_set_mup();
2073 gen_op_iwmmxt_set_cup();
2074 break;
2075 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2076 case 0x214: case 0x614: case 0xa14: case 0xe14:
2077 wrd = (insn >> 12) & 0xf;
2078 rd0 = (insn >> 16) & 0xf;
2079 gen_op_iwmmxt_movq_M0_wRn(rd0);
2080 if (gen_iwmmxt_shift(insn, 0xff))
2081 return 1;
2082 switch ((insn >> 22) & 3) {
2083 case 0:
2084 return 1;
2085 case 1:
2086 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2087 break;
2088 case 2:
2089 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2090 break;
2091 case 3:
2092 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2093 break;
2095 gen_op_iwmmxt_movq_wRn_M0(wrd);
2096 gen_op_iwmmxt_set_mup();
2097 gen_op_iwmmxt_set_cup();
2098 break;
2099 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2100 case 0x014: case 0x414: case 0x814: case 0xc14:
2101 wrd = (insn >> 12) & 0xf;
2102 rd0 = (insn >> 16) & 0xf;
2103 gen_op_iwmmxt_movq_M0_wRn(rd0);
2104 if (gen_iwmmxt_shift(insn, 0xff))
2105 return 1;
2106 switch ((insn >> 22) & 3) {
2107 case 0:
2108 return 1;
2109 case 1:
2110 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2111 break;
2112 case 2:
2113 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2114 break;
2115 case 3:
2116 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2117 break;
2119 gen_op_iwmmxt_movq_wRn_M0(wrd);
2120 gen_op_iwmmxt_set_mup();
2121 gen_op_iwmmxt_set_cup();
2122 break;
2123 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2124 case 0x114: case 0x514: case 0x914: case 0xd14:
2125 wrd = (insn >> 12) & 0xf;
2126 rd0 = (insn >> 16) & 0xf;
2127 gen_op_iwmmxt_movq_M0_wRn(rd0);
2128 if (gen_iwmmxt_shift(insn, 0xff))
2129 return 1;
2130 switch ((insn >> 22) & 3) {
2131 case 0:
2132 return 1;
2133 case 1:
2134 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2135 break;
2136 case 2:
2137 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2138 break;
2139 case 3:
2140 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2141 break;
2143 gen_op_iwmmxt_movq_wRn_M0(wrd);
2144 gen_op_iwmmxt_set_mup();
2145 gen_op_iwmmxt_set_cup();
2146 break;
2147 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2148 case 0x314: case 0x714: case 0xb14: case 0xf14:
2149 wrd = (insn >> 12) & 0xf;
2150 rd0 = (insn >> 16) & 0xf;
2151 gen_op_iwmmxt_movq_M0_wRn(rd0);
2152 switch ((insn >> 22) & 3) {
2153 case 0:
2154 return 1;
2155 case 1:
2156 if (gen_iwmmxt_shift(insn, 0xf))
2157 return 1;
2158 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2159 break;
2160 case 2:
2161 if (gen_iwmmxt_shift(insn, 0x1f))
2162 return 1;
2163 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2164 break;
2165 case 3:
2166 if (gen_iwmmxt_shift(insn, 0x3f))
2167 return 1;
2168 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2169 break;
2171 gen_op_iwmmxt_movq_wRn_M0(wrd);
2172 gen_op_iwmmxt_set_mup();
2173 gen_op_iwmmxt_set_cup();
2174 break;
2175 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2176 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2177 wrd = (insn >> 12) & 0xf;
2178 rd0 = (insn >> 16) & 0xf;
2179 rd1 = (insn >> 0) & 0xf;
2180 gen_op_iwmmxt_movq_M0_wRn(rd0);
2181 switch ((insn >> 22) & 3) {
2182 case 0:
2183 if (insn & (1 << 21))
2184 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2185 else
2186 gen_op_iwmmxt_minub_M0_wRn(rd1);
2187 break;
2188 case 1:
2189 if (insn & (1 << 21))
2190 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2191 else
2192 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2193 break;
2194 case 2:
2195 if (insn & (1 << 21))
2196 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2197 else
2198 gen_op_iwmmxt_minul_M0_wRn(rd1);
2199 break;
2200 case 3:
2201 return 1;
2203 gen_op_iwmmxt_movq_wRn_M0(wrd);
2204 gen_op_iwmmxt_set_mup();
2205 break;
2206 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2207 case 0x816: case 0xa16: case 0xc16: case 0xe16:
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 0:
2214 if (insn & (1 << 21))
2215 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2216 else
2217 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2218 break;
2219 case 1:
2220 if (insn & (1 << 21))
2221 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2222 else
2223 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2224 break;
2225 case 2:
2226 if (insn & (1 << 21))
2227 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2228 else
2229 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2230 break;
2231 case 3:
2232 return 1;
2234 gen_op_iwmmxt_movq_wRn_M0(wrd);
2235 gen_op_iwmmxt_set_mup();
2236 break;
2237 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2238 case 0x402: case 0x502: case 0x602: case 0x702:
2239 wrd = (insn >> 12) & 0xf;
2240 rd0 = (insn >> 16) & 0xf;
2241 rd1 = (insn >> 0) & 0xf;
2242 gen_op_iwmmxt_movq_M0_wRn(rd0);
2243 gen_op_movl_T0_im((insn >> 20) & 3);
2244 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2245 gen_op_iwmmxt_movq_wRn_M0(wrd);
2246 gen_op_iwmmxt_set_mup();
2247 break;
2248 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2249 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2250 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2251 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2252 wrd = (insn >> 12) & 0xf;
2253 rd0 = (insn >> 16) & 0xf;
2254 rd1 = (insn >> 0) & 0xf;
2255 gen_op_iwmmxt_movq_M0_wRn(rd0);
2256 switch ((insn >> 20) & 0xf) {
2257 case 0x0:
2258 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2259 break;
2260 case 0x1:
2261 gen_op_iwmmxt_subub_M0_wRn(rd1);
2262 break;
2263 case 0x3:
2264 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2265 break;
2266 case 0x4:
2267 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2268 break;
2269 case 0x5:
2270 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2271 break;
2272 case 0x7:
2273 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2274 break;
2275 case 0x8:
2276 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2277 break;
2278 case 0x9:
2279 gen_op_iwmmxt_subul_M0_wRn(rd1);
2280 break;
2281 case 0xb:
2282 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2283 break;
2284 default:
2285 return 1;
2287 gen_op_iwmmxt_movq_wRn_M0(wrd);
2288 gen_op_iwmmxt_set_mup();
2289 gen_op_iwmmxt_set_cup();
2290 break;
2291 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2292 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2293 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2294 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2295 wrd = (insn >> 12) & 0xf;
2296 rd0 = (insn >> 16) & 0xf;
2297 gen_op_iwmmxt_movq_M0_wRn(rd0);
2298 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2299 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2300 gen_op_iwmmxt_movq_wRn_M0(wrd);
2301 gen_op_iwmmxt_set_mup();
2302 gen_op_iwmmxt_set_cup();
2303 break;
2304 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2305 case 0x418: case 0x518: case 0x618: case 0x718:
2306 case 0x818: case 0x918: case 0xa18: case 0xb18:
2307 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2308 wrd = (insn >> 12) & 0xf;
2309 rd0 = (insn >> 16) & 0xf;
2310 rd1 = (insn >> 0) & 0xf;
2311 gen_op_iwmmxt_movq_M0_wRn(rd0);
2312 switch ((insn >> 20) & 0xf) {
2313 case 0x0:
2314 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2315 break;
2316 case 0x1:
2317 gen_op_iwmmxt_addub_M0_wRn(rd1);
2318 break;
2319 case 0x3:
2320 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2321 break;
2322 case 0x4:
2323 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2324 break;
2325 case 0x5:
2326 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2327 break;
2328 case 0x7:
2329 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2330 break;
2331 case 0x8:
2332 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2333 break;
2334 case 0x9:
2335 gen_op_iwmmxt_addul_M0_wRn(rd1);
2336 break;
2337 case 0xb:
2338 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2339 break;
2340 default:
2341 return 1;
2343 gen_op_iwmmxt_movq_wRn_M0(wrd);
2344 gen_op_iwmmxt_set_mup();
2345 gen_op_iwmmxt_set_cup();
2346 break;
2347 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2348 case 0x408: case 0x508: case 0x608: case 0x708:
2349 case 0x808: case 0x908: case 0xa08: case 0xb08:
2350 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2351 wrd = (insn >> 12) & 0xf;
2352 rd0 = (insn >> 16) & 0xf;
2353 rd1 = (insn >> 0) & 0xf;
2354 gen_op_iwmmxt_movq_M0_wRn(rd0);
2355 if (!(insn & (1 << 20)))
2356 return 1;
2357 switch ((insn >> 22) & 3) {
2358 case 0:
2359 return 1;
2360 case 1:
2361 if (insn & (1 << 21))
2362 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2363 else
2364 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2365 break;
2366 case 2:
2367 if (insn & (1 << 21))
2368 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2369 else
2370 gen_op_iwmmxt_packul_M0_wRn(rd1);
2371 break;
2372 case 3:
2373 if (insn & (1 << 21))
2374 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2375 else
2376 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2377 break;
2379 gen_op_iwmmxt_movq_wRn_M0(wrd);
2380 gen_op_iwmmxt_set_mup();
2381 gen_op_iwmmxt_set_cup();
2382 break;
2383 case 0x201: case 0x203: case 0x205: case 0x207:
2384 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2385 case 0x211: case 0x213: case 0x215: case 0x217:
2386 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2387 wrd = (insn >> 5) & 0xf;
2388 rd0 = (insn >> 12) & 0xf;
2389 rd1 = (insn >> 0) & 0xf;
2390 if (rd0 == 0xf || rd1 == 0xf)
2391 return 1;
2392 gen_op_iwmmxt_movq_M0_wRn(wrd);
2393 switch ((insn >> 16) & 0xf) {
2394 case 0x0: /* TMIA */
2395 gen_movl_T0_reg(s, rd0);
2396 gen_movl_T1_reg(s, rd1);
2397 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2398 break;
2399 case 0x8: /* TMIAPH */
2400 gen_movl_T0_reg(s, rd0);
2401 gen_movl_T1_reg(s, rd1);
2402 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2403 break;
2404 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2405 gen_movl_T1_reg(s, rd0);
2406 if (insn & (1 << 16))
2407 gen_op_shrl_T1_im(16);
2408 gen_op_movl_T0_T1();
2409 gen_movl_T1_reg(s, rd1);
2410 if (insn & (1 << 17))
2411 gen_op_shrl_T1_im(16);
2412 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2413 break;
2414 default:
2415 return 1;
2417 gen_op_iwmmxt_movq_wRn_M0(wrd);
2418 gen_op_iwmmxt_set_mup();
2419 break;
2420 default:
2421 return 1;
2424 return 0;
2427 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2428 (ie. an undefined instruction). */
2429 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2431 int acc, rd0, rd1, rdhi, rdlo;
2433 if ((insn & 0x0ff00f10) == 0x0e200010) {
2434 /* Multiply with Internal Accumulate Format */
2435 rd0 = (insn >> 12) & 0xf;
2436 rd1 = insn & 0xf;
2437 acc = (insn >> 5) & 7;
2439 if (acc != 0)
2440 return 1;
2442 switch ((insn >> 16) & 0xf) {
2443 case 0x0: /* MIA */
2444 gen_movl_T0_reg(s, rd0);
2445 gen_movl_T1_reg(s, rd1);
2446 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2447 break;
2448 case 0x8: /* MIAPH */
2449 gen_movl_T0_reg(s, rd0);
2450 gen_movl_T1_reg(s, rd1);
2451 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2452 break;
2453 case 0xc: /* MIABB */
2454 case 0xd: /* MIABT */
2455 case 0xe: /* MIATB */
2456 case 0xf: /* MIATT */
2457 gen_movl_T1_reg(s, rd0);
2458 if (insn & (1 << 16))
2459 gen_op_shrl_T1_im(16);
2460 gen_op_movl_T0_T1();
2461 gen_movl_T1_reg(s, rd1);
2462 if (insn & (1 << 17))
2463 gen_op_shrl_T1_im(16);
2464 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2465 break;
2466 default:
2467 return 1;
2470 gen_op_iwmmxt_movq_wRn_M0(acc);
2471 return 0;
2474 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2475 /* Internal Accumulator Access Format */
2476 rdhi = (insn >> 16) & 0xf;
2477 rdlo = (insn >> 12) & 0xf;
2478 acc = insn & 7;
2480 if (acc != 0)
2481 return 1;
2483 if (insn & ARM_CP_RW_BIT) { /* MRA */
2484 gen_iwmmxt_movl_T0_T1_wRn(acc);
2485 gen_movl_reg_T0(s, rdlo);
2486 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2487 gen_op_andl_T0_T1();
2488 gen_movl_reg_T0(s, rdhi);
2489 } else { /* MAR */
2490 gen_movl_T0_reg(s, rdlo);
2491 gen_movl_T1_reg(s, rdhi);
2492 gen_iwmmxt_movl_wRn_T0_T1(acc);
2494 return 0;
2497 return 1;
2500 /* Disassemble system coprocessor instruction. Return nonzero if
2501 instruction is not defined. */
2502 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2504 TCGv tmp;
2505 uint32_t rd = (insn >> 12) & 0xf;
2506 uint32_t cp = (insn >> 8) & 0xf;
2507 if (IS_USER(s)) {
2508 return 1;
2511 if (insn & ARM_CP_RW_BIT) {
2512 if (!env->cp[cp].cp_read)
2513 return 1;
2514 gen_set_pc_im(s->pc);
2515 tmp = new_tmp();
2516 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2517 store_reg(s, rd, tmp);
2518 } else {
2519 if (!env->cp[cp].cp_write)
2520 return 1;
2521 gen_set_pc_im(s->pc);
2522 tmp = load_reg(s, rd);
2523 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2524 dead_tmp(tmp);
2526 return 0;
2529 static int cp15_user_ok(uint32_t insn)
2531 int cpn = (insn >> 16) & 0xf;
2532 int cpm = insn & 0xf;
2533 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2535 if (cpn == 13 && cpm == 0) {
2536 /* TLS register. */
2537 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2538 return 1;
2540 if (cpn == 7) {
2541 /* ISB, DSB, DMB. */
2542 if ((cpm == 5 && op == 4)
2543 || (cpm == 10 && (op == 4 || op == 5)))
2544 return 1;
2546 return 0;
2549 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2550 instruction is not defined. */
2551 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2553 uint32_t rd;
2554 TCGv tmp;
2556 /* M profile cores use memory mapped registers instead of cp15. */
2557 if (arm_feature(env, ARM_FEATURE_M))
2558 return 1;
2560 if ((insn & (1 << 25)) == 0) {
2561 if (insn & (1 << 20)) {
2562 /* mrrc */
2563 return 1;
2565 /* mcrr. Used for block cache operations, so implement as no-op. */
2566 return 0;
2568 if ((insn & (1 << 4)) == 0) {
2569 /* cdp */
2570 return 1;
2572 if (IS_USER(s) && !cp15_user_ok(insn)) {
2573 return 1;
2575 if ((insn & 0x0fff0fff) == 0x0e070f90
2576 || (insn & 0x0fff0fff) == 0x0e070f58) {
2577 /* Wait for interrupt. */
2578 gen_set_pc_im(s->pc);
2579 s->is_jmp = DISAS_WFI;
2580 return 0;
2582 rd = (insn >> 12) & 0xf;
2583 if (insn & ARM_CP_RW_BIT) {
2584 tmp = new_tmp();
2585 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2586 /* If the destination register is r15 then sets condition codes. */
2587 if (rd != 15)
2588 store_reg(s, rd, tmp);
2589 else
2590 dead_tmp(tmp);
2591 } else {
2592 tmp = load_reg(s, rd);
2593 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2594 dead_tmp(tmp);
2595 /* Normally we would always end the TB here, but Linux
2596 * arch/arm/mach-pxa/sleep.S expects two instructions following
2597 * an MMU enable to execute from cache. Imitate this behaviour. */
2598 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2599 (insn & 0x0fff0fff) != 0x0e010f10)
2600 gen_lookup_tb(s);
2602 return 0;
2605 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2606 #define VFP_SREG(insn, bigbit, smallbit) \
2607 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2608 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2609 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2610 reg = (((insn) >> (bigbit)) & 0x0f) \
2611 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2612 } else { \
2613 if (insn & (1 << (smallbit))) \
2614 return 1; \
2615 reg = ((insn) >> (bigbit)) & 0x0f; \
2616 }} while (0)
2618 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2619 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2620 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2621 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2622 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2623 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2625 /* Move between integer and VFP cores. */
2626 static TCGv gen_vfp_mrs(void)
2628 TCGv tmp = new_tmp();
2629 tcg_gen_mov_i32(tmp, cpu_F0s);
2630 return tmp;
2633 static void gen_vfp_msr(TCGv tmp)
2635 tcg_gen_mov_i32(cpu_F0s, tmp);
2636 dead_tmp(tmp);
2639 static inline int
2640 vfp_enabled(CPUState * env)
2642 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2645 static void gen_neon_dup_u8(TCGv var, int shift)
2647 TCGv tmp = new_tmp();
2648 if (shift)
2649 tcg_gen_shri_i32(var, var, shift);
2650 tcg_gen_ext8u_i32(var, var);
2651 tcg_gen_shli_i32(tmp, var, 8);
2652 tcg_gen_or_i32(var, var, tmp);
2653 tcg_gen_shli_i32(tmp, var, 16);
2654 tcg_gen_or_i32(var, var, tmp);
2655 dead_tmp(tmp);
2658 static void gen_neon_dup_low16(TCGv var)
2660 TCGv tmp = new_tmp();
2661 tcg_gen_ext16u_i32(var, var);
2662 tcg_gen_shli_i32(tmp, var, 16);
2663 tcg_gen_or_i32(var, var, tmp);
2664 dead_tmp(tmp);
2667 static void gen_neon_dup_high16(TCGv var)
2669 TCGv tmp = new_tmp();
2670 tcg_gen_andi_i32(var, var, 0xffff0000);
2671 tcg_gen_shri_i32(tmp, var, 16);
2672 tcg_gen_or_i32(var, var, tmp);
2673 dead_tmp(tmp);
2676 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2677 (ie. an undefined instruction). */
2678 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2680 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2681 int dp, veclen;
2682 TCGv tmp;
2683 TCGv tmp2;
2685 if (!arm_feature(env, ARM_FEATURE_VFP))
2686 return 1;
2688 if (!vfp_enabled(env)) {
2689 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2690 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2691 return 1;
2692 rn = (insn >> 16) & 0xf;
2693 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2694 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2695 return 1;
2697 dp = ((insn & 0xf00) == 0xb00);
2698 switch ((insn >> 24) & 0xf) {
2699 case 0xe:
2700 if (insn & (1 << 4)) {
2701 /* single register transfer */
2702 rd = (insn >> 12) & 0xf;
2703 if (dp) {
2704 int size;
2705 int pass;
2707 VFP_DREG_N(rn, insn);
2708 if (insn & 0xf)
2709 return 1;
2710 if (insn & 0x00c00060
2711 && !arm_feature(env, ARM_FEATURE_NEON))
2712 return 1;
2714 pass = (insn >> 21) & 1;
2715 if (insn & (1 << 22)) {
2716 size = 0;
2717 offset = ((insn >> 5) & 3) * 8;
2718 } else if (insn & (1 << 5)) {
2719 size = 1;
2720 offset = (insn & (1 << 6)) ? 16 : 0;
2721 } else {
2722 size = 2;
2723 offset = 0;
2725 if (insn & ARM_CP_RW_BIT) {
2726 /* vfp->arm */
2727 tmp = neon_load_reg(rn, pass);
2728 switch (size) {
2729 case 0:
2730 if (offset)
2731 tcg_gen_shri_i32(tmp, tmp, offset);
2732 if (insn & (1 << 23))
2733 gen_uxtb(tmp);
2734 else
2735 gen_sxtb(tmp);
2736 break;
2737 case 1:
2738 if (insn & (1 << 23)) {
2739 if (offset) {
2740 tcg_gen_shri_i32(tmp, tmp, 16);
2741 } else {
2742 gen_uxth(tmp);
2744 } else {
2745 if (offset) {
2746 tcg_gen_sari_i32(tmp, tmp, 16);
2747 } else {
2748 gen_sxth(tmp);
2751 break;
2752 case 2:
2753 break;
2755 store_reg(s, rd, tmp);
2756 } else {
2757 /* arm->vfp */
2758 tmp = load_reg(s, rd);
2759 if (insn & (1 << 23)) {
2760 /* VDUP */
2761 if (size == 0) {
2762 gen_neon_dup_u8(tmp, 0);
2763 } else if (size == 1) {
2764 gen_neon_dup_low16(tmp);
2766 for (n = 0; n <= pass * 2; n++) {
2767 tmp2 = new_tmp();
2768 tcg_gen_mov_i32(tmp2, tmp);
2769 neon_store_reg(rn, n, tmp2);
2771 neon_store_reg(rn, n, tmp);
2772 } else {
2773 /* VMOV */
2774 switch (size) {
2775 case 0:
2776 tmp2 = neon_load_reg(rn, pass);
2777 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2778 dead_tmp(tmp2);
2779 break;
2780 case 1:
2781 tmp2 = neon_load_reg(rn, pass);
2782 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2783 dead_tmp(tmp2);
2784 break;
2785 case 2:
2786 break;
2788 neon_store_reg(rn, pass, tmp);
2791 } else { /* !dp */
2792 if ((insn & 0x6f) != 0x00)
2793 return 1;
2794 rn = VFP_SREG_N(insn);
2795 if (insn & ARM_CP_RW_BIT) {
2796 /* vfp->arm */
2797 if (insn & (1 << 21)) {
2798 /* system register */
2799 rn >>= 1;
2801 switch (rn) {
2802 case ARM_VFP_FPSID:
2803 /* VFP2 allows access to FSID from userspace.
2804 VFP3 restricts all id registers to privileged
2805 accesses. */
2806 if (IS_USER(s)
2807 && arm_feature(env, ARM_FEATURE_VFP3))
2808 return 1;
2809 tmp = load_cpu_field(vfp.xregs[rn]);
2810 break;
2811 case ARM_VFP_FPEXC:
2812 if (IS_USER(s))
2813 return 1;
2814 tmp = load_cpu_field(vfp.xregs[rn]);
2815 break;
2816 case ARM_VFP_FPINST:
2817 case ARM_VFP_FPINST2:
2818 /* Not present in VFP3. */
2819 if (IS_USER(s)
2820 || arm_feature(env, ARM_FEATURE_VFP3))
2821 return 1;
2822 tmp = load_cpu_field(vfp.xregs[rn]);
2823 break;
2824 case ARM_VFP_FPSCR:
2825 if (rd == 15) {
2826 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2827 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2828 } else {
2829 tmp = new_tmp();
2830 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2832 break;
2833 case ARM_VFP_MVFR0:
2834 case ARM_VFP_MVFR1:
2835 if (IS_USER(s)
2836 || !arm_feature(env, ARM_FEATURE_VFP3))
2837 return 1;
2838 tmp = load_cpu_field(vfp.xregs[rn]);
2839 break;
2840 default:
2841 return 1;
2843 } else {
2844 gen_mov_F0_vreg(0, rn);
2845 tmp = gen_vfp_mrs();
2847 if (rd == 15) {
2848 /* Set the 4 flag bits in the CPSR. */
2849 gen_set_nzcv(tmp);
2850 dead_tmp(tmp);
2851 } else {
2852 store_reg(s, rd, tmp);
2854 } else {
2855 /* arm->vfp */
2856 tmp = load_reg(s, rd);
2857 if (insn & (1 << 21)) {
2858 rn >>= 1;
2859 /* system register */
2860 switch (rn) {
2861 case ARM_VFP_FPSID:
2862 case ARM_VFP_MVFR0:
2863 case ARM_VFP_MVFR1:
2864 /* Writes are ignored. */
2865 break;
2866 case ARM_VFP_FPSCR:
2867 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2868 dead_tmp(tmp);
2869 gen_lookup_tb(s);
2870 break;
2871 case ARM_VFP_FPEXC:
2872 if (IS_USER(s))
2873 return 1;
2874 store_cpu_field(tmp, vfp.xregs[rn]);
2875 gen_lookup_tb(s);
2876 break;
2877 case ARM_VFP_FPINST:
2878 case ARM_VFP_FPINST2:
2879 store_cpu_field(tmp, vfp.xregs[rn]);
2880 break;
2881 default:
2882 return 1;
2884 } else {
2885 gen_vfp_msr(tmp);
2886 gen_mov_vreg_F0(0, rn);
2890 } else {
2891 /* data processing */
2892 /* The opcode is in bits 23, 21, 20 and 6. */
2893 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2894 if (dp) {
2895 if (op == 15) {
2896 /* rn is opcode */
2897 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2898 } else {
2899 /* rn is register number */
2900 VFP_DREG_N(rn, insn);
2903 if (op == 15 && (rn == 15 || rn > 17)) {
2904 /* Integer or single precision destination. */
2905 rd = VFP_SREG_D(insn);
2906 } else {
2907 VFP_DREG_D(rd, insn);
2910 if (op == 15 && (rn == 16 || rn == 17)) {
2911 /* Integer source. */
2912 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2913 } else {
2914 VFP_DREG_M(rm, insn);
2916 } else {
2917 rn = VFP_SREG_N(insn);
2918 if (op == 15 && rn == 15) {
2919 /* Double precision destination. */
2920 VFP_DREG_D(rd, insn);
2921 } else {
2922 rd = VFP_SREG_D(insn);
2924 rm = VFP_SREG_M(insn);
2927 veclen = env->vfp.vec_len;
2928 if (op == 15 && rn > 3)
2929 veclen = 0;
2931 /* Shut up compiler warnings. */
2932 delta_m = 0;
2933 delta_d = 0;
2934 bank_mask = 0;
2936 if (veclen > 0) {
2937 if (dp)
2938 bank_mask = 0xc;
2939 else
2940 bank_mask = 0x18;
2942 /* Figure out what type of vector operation this is. */
2943 if ((rd & bank_mask) == 0) {
2944 /* scalar */
2945 veclen = 0;
2946 } else {
2947 if (dp)
2948 delta_d = (env->vfp.vec_stride >> 1) + 1;
2949 else
2950 delta_d = env->vfp.vec_stride + 1;
2952 if ((rm & bank_mask) == 0) {
2953 /* mixed scalar/vector */
2954 delta_m = 0;
2955 } else {
2956 /* vector */
2957 delta_m = delta_d;
2962 /* Load the initial operands. */
2963 if (op == 15) {
2964 switch (rn) {
2965 case 16:
2966 case 17:
2967 /* Integer source */
2968 gen_mov_F0_vreg(0, rm);
2969 break;
2970 case 8:
2971 case 9:
2972 /* Compare */
2973 gen_mov_F0_vreg(dp, rd);
2974 gen_mov_F1_vreg(dp, rm);
2975 break;
2976 case 10:
2977 case 11:
2978 /* Compare with zero */
2979 gen_mov_F0_vreg(dp, rd);
2980 gen_vfp_F1_ld0(dp);
2981 break;
2982 case 20:
2983 case 21:
2984 case 22:
2985 case 23:
2986 case 28:
2987 case 29:
2988 case 30:
2989 case 31:
2990 /* Source and destination the same. */
2991 gen_mov_F0_vreg(dp, rd);
2992 break;
2993 default:
2994 /* One source operand. */
2995 gen_mov_F0_vreg(dp, rm);
2996 break;
2998 } else {
2999 /* Two source operands. */
3000 gen_mov_F0_vreg(dp, rn);
3001 gen_mov_F1_vreg(dp, rm);
3004 for (;;) {
3005 /* Perform the calculation. */
3006 switch (op) {
3007 case 0: /* mac: fd + (fn * fm) */
3008 gen_vfp_mul(dp);
3009 gen_mov_F1_vreg(dp, rd);
3010 gen_vfp_add(dp);
3011 break;
3012 case 1: /* nmac: fd - (fn * fm) */
3013 gen_vfp_mul(dp);
3014 gen_vfp_neg(dp);
3015 gen_mov_F1_vreg(dp, rd);
3016 gen_vfp_add(dp);
3017 break;
3018 case 2: /* msc: -fd + (fn * fm) */
3019 gen_vfp_mul(dp);
3020 gen_mov_F1_vreg(dp, rd);
3021 gen_vfp_sub(dp);
3022 break;
3023 case 3: /* nmsc: -fd - (fn * fm) */
3024 gen_vfp_mul(dp);
3025 gen_vfp_neg(dp);
3026 gen_mov_F1_vreg(dp, rd);
3027 gen_vfp_sub(dp);
3028 break;
3029 case 4: /* mul: fn * fm */
3030 gen_vfp_mul(dp);
3031 break;
3032 case 5: /* nmul: -(fn * fm) */
3033 gen_vfp_mul(dp);
3034 gen_vfp_neg(dp);
3035 break;
3036 case 6: /* add: fn + fm */
3037 gen_vfp_add(dp);
3038 break;
3039 case 7: /* sub: fn - fm */
3040 gen_vfp_sub(dp);
3041 break;
3042 case 8: /* div: fn / fm */
3043 gen_vfp_div(dp);
3044 break;
3045 case 14: /* fconst */
3046 if (!arm_feature(env, ARM_FEATURE_VFP3))
3047 return 1;
3049 n = (insn << 12) & 0x80000000;
3050 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3051 if (dp) {
3052 if (i & 0x40)
3053 i |= 0x3f80;
3054 else
3055 i |= 0x4000;
3056 n |= i << 16;
3057 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3058 } else {
3059 if (i & 0x40)
3060 i |= 0x780;
3061 else
3062 i |= 0x800;
3063 n |= i << 19;
3064 tcg_gen_movi_i32(cpu_F0s, n);
3066 break;
3067 case 15: /* extension space */
3068 switch (rn) {
3069 case 0: /* cpy */
3070 /* no-op */
3071 break;
3072 case 1: /* abs */
3073 gen_vfp_abs(dp);
3074 break;
3075 case 2: /* neg */
3076 gen_vfp_neg(dp);
3077 break;
3078 case 3: /* sqrt */
3079 gen_vfp_sqrt(dp);
3080 break;
3081 case 8: /* cmp */
3082 gen_vfp_cmp(dp);
3083 break;
3084 case 9: /* cmpe */
3085 gen_vfp_cmpe(dp);
3086 break;
3087 case 10: /* cmpz */
3088 gen_vfp_cmp(dp);
3089 break;
3090 case 11: /* cmpez */
3091 gen_vfp_F1_ld0(dp);
3092 gen_vfp_cmpe(dp);
3093 break;
3094 case 15: /* single<->double conversion */
3095 if (dp)
3096 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3097 else
3098 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3099 break;
3100 case 16: /* fuito */
3101 gen_vfp_uito(dp);
3102 break;
3103 case 17: /* fsito */
3104 gen_vfp_sito(dp);
3105 break;
3106 case 20: /* fshto */
3107 if (!arm_feature(env, ARM_FEATURE_VFP3))
3108 return 1;
3109 gen_vfp_shto(dp, 16 - rm);
3110 break;
3111 case 21: /* fslto */
3112 if (!arm_feature(env, ARM_FEATURE_VFP3))
3113 return 1;
3114 gen_vfp_slto(dp, 32 - rm);
3115 break;
3116 case 22: /* fuhto */
3117 if (!arm_feature(env, ARM_FEATURE_VFP3))
3118 return 1;
3119 gen_vfp_uhto(dp, 16 - rm);
3120 break;
3121 case 23: /* fulto */
3122 if (!arm_feature(env, ARM_FEATURE_VFP3))
3123 return 1;
3124 gen_vfp_ulto(dp, 32 - rm);
3125 break;
3126 case 24: /* ftoui */
3127 gen_vfp_toui(dp);
3128 break;
3129 case 25: /* ftouiz */
3130 gen_vfp_touiz(dp);
3131 break;
3132 case 26: /* ftosi */
3133 gen_vfp_tosi(dp);
3134 break;
3135 case 27: /* ftosiz */
3136 gen_vfp_tosiz(dp);
3137 break;
3138 case 28: /* ftosh */
3139 if (!arm_feature(env, ARM_FEATURE_VFP3))
3140 return 1;
3141 gen_vfp_tosh(dp, 16 - rm);
3142 break;
3143 case 29: /* ftosl */
3144 if (!arm_feature(env, ARM_FEATURE_VFP3))
3145 return 1;
3146 gen_vfp_tosl(dp, 32 - rm);
3147 break;
3148 case 30: /* ftouh */
3149 if (!arm_feature(env, ARM_FEATURE_VFP3))
3150 return 1;
3151 gen_vfp_touh(dp, 16 - rm);
3152 break;
3153 case 31: /* ftoul */
3154 if (!arm_feature(env, ARM_FEATURE_VFP3))
3155 return 1;
3156 gen_vfp_toul(dp, 32 - rm);
3157 break;
3158 default: /* undefined */
3159 printf ("rn:%d\n", rn);
3160 return 1;
3162 break;
3163 default: /* undefined */
3164 printf ("op:%d\n", op);
3165 return 1;
3168 /* Write back the result. */
3169 if (op == 15 && (rn >= 8 && rn <= 11))
3170 ; /* Comparison, do nothing. */
3171 else if (op == 15 && rn > 17)
3172 /* Integer result. */
3173 gen_mov_vreg_F0(0, rd);
3174 else if (op == 15 && rn == 15)
3175 /* conversion */
3176 gen_mov_vreg_F0(!dp, rd);
3177 else
3178 gen_mov_vreg_F0(dp, rd);
3180 /* break out of the loop if we have finished */
3181 if (veclen == 0)
3182 break;
3184 if (op == 15 && delta_m == 0) {
3185 /* single source one-many */
3186 while (veclen--) {
3187 rd = ((rd + delta_d) & (bank_mask - 1))
3188 | (rd & bank_mask);
3189 gen_mov_vreg_F0(dp, rd);
3191 break;
3193 /* Setup the next operands. */
3194 veclen--;
3195 rd = ((rd + delta_d) & (bank_mask - 1))
3196 | (rd & bank_mask);
3198 if (op == 15) {
3199 /* One source operand. */
3200 rm = ((rm + delta_m) & (bank_mask - 1))
3201 | (rm & bank_mask);
3202 gen_mov_F0_vreg(dp, rm);
3203 } else {
3204 /* Two source operands. */
3205 rn = ((rn + delta_d) & (bank_mask - 1))
3206 | (rn & bank_mask);
3207 gen_mov_F0_vreg(dp, rn);
3208 if (delta_m) {
3209 rm = ((rm + delta_m) & (bank_mask - 1))
3210 | (rm & bank_mask);
3211 gen_mov_F1_vreg(dp, rm);
3216 break;
3217 case 0xc:
3218 case 0xd:
3219 if (dp && (insn & 0x03e00000) == 0x00400000) {
3220 /* two-register transfer */
3221 rn = (insn >> 16) & 0xf;
3222 rd = (insn >> 12) & 0xf;
3223 if (dp) {
3224 VFP_DREG_M(rm, insn);
3225 } else {
3226 rm = VFP_SREG_M(insn);
3229 if (insn & ARM_CP_RW_BIT) {
3230 /* vfp->arm */
3231 if (dp) {
3232 gen_mov_F0_vreg(0, rm * 2);
3233 tmp = gen_vfp_mrs();
3234 store_reg(s, rd, tmp);
3235 gen_mov_F0_vreg(0, rm * 2 + 1);
3236 tmp = gen_vfp_mrs();
3237 store_reg(s, rn, tmp);
3238 } else {
3239 gen_mov_F0_vreg(0, rm);
3240 tmp = gen_vfp_mrs();
3241 store_reg(s, rn, tmp);
3242 gen_mov_F0_vreg(0, rm + 1);
3243 tmp = gen_vfp_mrs();
3244 store_reg(s, rd, tmp);
3246 } else {
3247 /* arm->vfp */
3248 if (dp) {
3249 tmp = load_reg(s, rd);
3250 gen_vfp_msr(tmp);
3251 gen_mov_vreg_F0(0, rm * 2);
3252 tmp = load_reg(s, rn);
3253 gen_vfp_msr(tmp);
3254 gen_mov_vreg_F0(0, rm * 2 + 1);
3255 } else {
3256 tmp = load_reg(s, rn);
3257 gen_vfp_msr(tmp);
3258 gen_mov_vreg_F0(0, rm);
3259 tmp = load_reg(s, rd);
3260 gen_vfp_msr(tmp);
3261 gen_mov_vreg_F0(0, rm + 1);
3264 } else {
3265 /* Load/store */
3266 rn = (insn >> 16) & 0xf;
3267 if (dp)
3268 VFP_DREG_D(rd, insn);
3269 else
3270 rd = VFP_SREG_D(insn);
3271 if (s->thumb && rn == 15) {
3272 gen_op_movl_T1_im(s->pc & ~2);
3273 } else {
3274 gen_movl_T1_reg(s, rn);
3276 if ((insn & 0x01200000) == 0x01000000) {
3277 /* Single load/store */
3278 offset = (insn & 0xff) << 2;
3279 if ((insn & (1 << 23)) == 0)
3280 offset = -offset;
3281 gen_op_addl_T1_im(offset);
3282 if (insn & (1 << 20)) {
3283 gen_vfp_ld(s, dp);
3284 gen_mov_vreg_F0(dp, rd);
3285 } else {
3286 gen_mov_F0_vreg(dp, rd);
3287 gen_vfp_st(s, dp);
3289 } else {
3290 /* load/store multiple */
3291 if (dp)
3292 n = (insn >> 1) & 0x7f;
3293 else
3294 n = insn & 0xff;
3296 if (insn & (1 << 24)) /* pre-decrement */
3297 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3299 if (dp)
3300 offset = 8;
3301 else
3302 offset = 4;
3303 for (i = 0; i < n; i++) {
3304 if (insn & ARM_CP_RW_BIT) {
3305 /* load */
3306 gen_vfp_ld(s, dp);
3307 gen_mov_vreg_F0(dp, rd + i);
3308 } else {
3309 /* store */
3310 gen_mov_F0_vreg(dp, rd + i);
3311 gen_vfp_st(s, dp);
3313 gen_op_addl_T1_im(offset);
3315 if (insn & (1 << 21)) {
3316 /* writeback */
3317 if (insn & (1 << 24))
3318 offset = -offset * n;
3319 else if (dp && (insn & 1))
3320 offset = 4;
3321 else
3322 offset = 0;
3324 if (offset != 0)
3325 gen_op_addl_T1_im(offset);
3326 gen_movl_reg_T1(s, rn);
3330 break;
3331 default:
3332 /* Should never happen. */
3333 return 1;
3335 return 0;
3338 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3340 TranslationBlock *tb;
3342 tb = s->tb;
3343 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3344 tcg_gen_goto_tb(n);
3345 gen_set_pc_im(dest);
3346 tcg_gen_exit_tb((long)tb + n);
3347 } else {
3348 gen_set_pc_im(dest);
3349 tcg_gen_exit_tb(0);
3353 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3355 if (unlikely(s->singlestep_enabled)) {
3356 /* An indirect jump so that we still trigger the debug exception. */
3357 if (s->thumb)
3358 dest |= 1;
3359 gen_bx_im(s, dest);
3360 } else {
3361 gen_goto_tb(s, 0, dest);
3362 s->is_jmp = DISAS_TB_JUMP;
3366 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3368 if (x)
3369 tcg_gen_sari_i32(t0, t0, 16);
3370 else
3371 gen_sxth(t0);
3372 if (y)
3373 tcg_gen_sari_i32(t1, t1, 16);
3374 else
3375 gen_sxth(t1);
3376 tcg_gen_mul_i32(t0, t0, t1);
3379 /* Return the mask of PSR bits set by a MSR instruction. */
3380 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3381 uint32_t mask;
3383 mask = 0;
3384 if (flags & (1 << 0))
3385 mask |= 0xff;
3386 if (flags & (1 << 1))
3387 mask |= 0xff00;
3388 if (flags & (1 << 2))
3389 mask |= 0xff0000;
3390 if (flags & (1 << 3))
3391 mask |= 0xff000000;
3393 /* Mask out undefined bits. */
3394 mask &= ~CPSR_RESERVED;
3395 if (!arm_feature(env, ARM_FEATURE_V6))
3396 mask &= ~(CPSR_E | CPSR_GE);
3397 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3398 mask &= ~CPSR_IT;
3399 /* Mask out execution state bits. */
3400 if (!spsr)
3401 mask &= ~CPSR_EXEC;
3402 /* Mask out privileged bits. */
3403 if (IS_USER(s))
3404 mask &= CPSR_USER;
3405 return mask;
3408 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3409 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3411 TCGv tmp;
3412 if (spsr) {
3413 /* ??? This is also undefined in system mode. */
3414 if (IS_USER(s))
3415 return 1;
3417 tmp = load_cpu_field(spsr);
3418 tcg_gen_andi_i32(tmp, tmp, ~mask);
3419 tcg_gen_andi_i32(t0, t0, mask);
3420 tcg_gen_or_i32(tmp, tmp, t0);
3421 store_cpu_field(tmp, spsr);
3422 } else {
3423 gen_set_cpsr(t0, mask);
3425 dead_tmp(t0);
3426 gen_lookup_tb(s);
3427 return 0;
3430 /* Returns nonzero if access to the PSR is not permitted. */
3431 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3433 TCGv tmp;
3434 tmp = new_tmp();
3435 tcg_gen_movi_i32(tmp, val);
3436 return gen_set_psr(s, mask, spsr, tmp);
3439 /* Generate an old-style exception return. Marks pc as dead. */
3440 static void gen_exception_return(DisasContext *s, TCGv pc)
3442 TCGv tmp;
3443 store_reg(s, 15, pc);
3444 tmp = load_cpu_field(spsr);
3445 gen_set_cpsr(tmp, 0xffffffff);
3446 dead_tmp(tmp);
3447 s->is_jmp = DISAS_UPDATE;
3450 /* Generate a v6 exception return. Marks both values as dead. */
3451 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3453 gen_set_cpsr(cpsr, 0xffffffff);
3454 dead_tmp(cpsr);
3455 store_reg(s, 15, pc);
3456 s->is_jmp = DISAS_UPDATE;
3459 static inline void
3460 gen_set_condexec (DisasContext *s)
3462 if (s->condexec_mask) {
3463 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3464 TCGv tmp = new_tmp();
3465 tcg_gen_movi_i32(tmp, val);
3466 store_cpu_field(tmp, condexec_bits);
3470 static void gen_nop_hint(DisasContext *s, int val)
3472 switch (val) {
3473 case 3: /* wfi */
3474 gen_set_pc_im(s->pc);
3475 s->is_jmp = DISAS_WFI;
3476 break;
3477 case 2: /* wfe */
3478 case 4: /* sev */
3479 /* TODO: Implement SEV and WFE. May help SMP performance. */
3480 default: /* nop */
3481 break;
3485 /* These macros help make the code more readable when migrating from the
3486 old dyngen helpers. They should probably be removed when
3487 T0/T1 are removed. */
3488 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3489 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3491 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3493 static inline int gen_neon_add(int size)
3495 switch (size) {
3496 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3497 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3498 case 2: gen_op_addl_T0_T1(); break;
3499 default: return 1;
3501 return 0;
3504 static inline void gen_neon_rsb(int size)
3506 switch (size) {
3507 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3508 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3509 case 2: gen_op_rsbl_T0_T1(); break;
3510 default: return;
3514 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3515 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3516 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3517 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3518 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3520 /* FIXME: This is wrong. They set the wrong overflow bit. */
3521 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3522 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3523 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3524 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3526 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3527 switch ((size << 1) | u) { \
3528 case 0: \
3529 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3530 break; \
3531 case 1: \
3532 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3533 break; \
3534 case 2: \
3535 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3536 break; \
3537 case 3: \
3538 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3539 break; \
3540 case 4: \
3541 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3542 break; \
3543 case 5: \
3544 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3545 break; \
3546 default: return 1; \
3547 }} while (0)
3549 #define GEN_NEON_INTEGER_OP(name) do { \
3550 switch ((size << 1) | u) { \
3551 case 0: \
3552 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3553 break; \
3554 case 1: \
3555 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3556 break; \
3557 case 2: \
3558 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3559 break; \
3560 case 3: \
3561 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3562 break; \
3563 case 4: \
3564 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3565 break; \
3566 case 5: \
3567 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3568 break; \
3569 default: return 1; \
3570 }} while (0)
3572 static inline void
3573 gen_neon_movl_scratch_T0(int scratch)
3575 uint32_t offset;
3577 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3578 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3581 static inline void
3582 gen_neon_movl_scratch_T1(int scratch)
3584 uint32_t offset;
3586 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3587 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3590 static inline void
3591 gen_neon_movl_T0_scratch(int scratch)
3593 uint32_t offset;
3595 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3596 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3599 static inline void
3600 gen_neon_movl_T1_scratch(int scratch)
3602 uint32_t offset;
3604 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3605 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3608 static inline void gen_neon_get_scalar(int size, int reg)
3610 if (size == 1) {
3611 NEON_GET_REG(T0, reg >> 1, reg & 1);
3612 } else {
3613 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3614 if (reg & 1)
3615 gen_neon_dup_low16(cpu_T[0]);
3616 else
3617 gen_neon_dup_high16(cpu_T[0]);
3621 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3623 TCGv rd, rm, tmp;
3625 rd = new_tmp();
3626 rm = new_tmp();
3627 tmp = new_tmp();
3629 tcg_gen_andi_i32(rd, t0, 0xff);
3630 tcg_gen_shri_i32(tmp, t0, 8);
3631 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3632 tcg_gen_or_i32(rd, rd, tmp);
3633 tcg_gen_shli_i32(tmp, t1, 16);
3634 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3635 tcg_gen_or_i32(rd, rd, tmp);
3636 tcg_gen_shli_i32(tmp, t1, 8);
3637 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3638 tcg_gen_or_i32(rd, rd, tmp);
3640 tcg_gen_shri_i32(rm, t0, 8);
3641 tcg_gen_andi_i32(rm, rm, 0xff);
3642 tcg_gen_shri_i32(tmp, t0, 16);
3643 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3644 tcg_gen_or_i32(rm, rm, tmp);
3645 tcg_gen_shli_i32(tmp, t1, 8);
3646 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3647 tcg_gen_or_i32(rm, rm, tmp);
3648 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3649 tcg_gen_or_i32(t1, rm, tmp);
3650 tcg_gen_mov_i32(t0, rd);
3652 dead_tmp(tmp);
3653 dead_tmp(rm);
3654 dead_tmp(rd);
3657 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3659 TCGv rd, rm, tmp;
3661 rd = new_tmp();
3662 rm = new_tmp();
3663 tmp = new_tmp();
3665 tcg_gen_andi_i32(rd, t0, 0xff);
3666 tcg_gen_shli_i32(tmp, t1, 8);
3667 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3668 tcg_gen_or_i32(rd, rd, tmp);
3669 tcg_gen_shli_i32(tmp, t0, 16);
3670 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3671 tcg_gen_or_i32(rd, rd, tmp);
3672 tcg_gen_shli_i32(tmp, t1, 24);
3673 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3674 tcg_gen_or_i32(rd, rd, tmp);
3676 tcg_gen_andi_i32(rm, t1, 0xff000000);
3677 tcg_gen_shri_i32(tmp, t0, 8);
3678 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3679 tcg_gen_or_i32(rm, rm, tmp);
3680 tcg_gen_shri_i32(tmp, t1, 8);
3681 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3682 tcg_gen_or_i32(rm, rm, tmp);
3683 tcg_gen_shri_i32(tmp, t0, 16);
3684 tcg_gen_andi_i32(tmp, tmp, 0xff);
3685 tcg_gen_or_i32(t1, rm, tmp);
3686 tcg_gen_mov_i32(t0, rd);
3688 dead_tmp(tmp);
3689 dead_tmp(rm);
3690 dead_tmp(rd);
3693 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3695 TCGv tmp, tmp2;
3697 tmp = new_tmp();
3698 tmp2 = new_tmp();
3700 tcg_gen_andi_i32(tmp, t0, 0xffff);
3701 tcg_gen_shli_i32(tmp2, t1, 16);
3702 tcg_gen_or_i32(tmp, tmp, tmp2);
3703 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3704 tcg_gen_shri_i32(tmp2, t0, 16);
3705 tcg_gen_or_i32(t1, t1, tmp2);
3706 tcg_gen_mov_i32(t0, tmp);
3708 dead_tmp(tmp2);
3709 dead_tmp(tmp);
3712 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3714 int n;
3716 for (n = 0; n < q + 1; n += 2) {
3717 NEON_GET_REG(T0, reg, n);
3718 NEON_GET_REG(T1, reg, n + 1);
3719 switch (size) {
3720 case 0: gen_neon_unzip_u8(cpu_T[0], cpu_T[1]); break;
3721 case 1: gen_neon_zip_u16(cpu_T[0], cpu_T[1]); break; /* zip and unzip are the same. */
3722 case 2: /* no-op */; break;
3723 default: abort();
3725 gen_neon_movl_T0_scratch(tmp + n);
3726 gen_neon_movl_T1_scratch(tmp + n + 1);
3730 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3732 TCGv rd, tmp;
3734 rd = new_tmp();
3735 tmp = new_tmp();
3737 tcg_gen_shli_i32(rd, t0, 8);
3738 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3739 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3740 tcg_gen_or_i32(rd, rd, tmp);
3742 tcg_gen_shri_i32(t1, t1, 8);
3743 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3744 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3745 tcg_gen_or_i32(t1, t1, tmp);
3746 tcg_gen_mov_i32(t0, rd);
3748 dead_tmp(tmp);
3749 dead_tmp(rd);
3752 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3754 TCGv rd, tmp;
3756 rd = new_tmp();
3757 tmp = new_tmp();
3759 tcg_gen_shli_i32(rd, t0, 16);
3760 tcg_gen_andi_i32(tmp, t1, 0xffff);
3761 tcg_gen_or_i32(rd, rd, tmp);
3762 tcg_gen_shri_i32(t1, t1, 16);
3763 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3764 tcg_gen_or_i32(t1, t1, tmp);
3765 tcg_gen_mov_i32(t0, rd);
3767 dead_tmp(tmp);
3768 dead_tmp(rd);
3772 static struct {
3773 int nregs;
3774 int interleave;
3775 int spacing;
3776 } neon_ls_element_type[11] = {
3777 {4, 4, 1},
3778 {4, 4, 2},
3779 {4, 1, 1},
3780 {4, 2, 1},
3781 {3, 3, 1},
3782 {3, 3, 2},
3783 {3, 1, 1},
3784 {1, 1, 1},
3785 {2, 2, 1},
3786 {2, 2, 2},
3787 {2, 1, 1}
3790 /* Translate a NEON load/store element instruction. Return nonzero if the
3791 instruction is invalid. */
3792 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3794 int rd, rn, rm;
3795 int op;
3796 int nregs;
3797 int interleave;
3798 int stride;
3799 int size;
3800 int reg;
3801 int pass;
3802 int load;
3803 int shift;
3804 int n;
3805 TCGv tmp;
3806 TCGv tmp2;
3808 if (!vfp_enabled(env))
3809 return 1;
3810 VFP_DREG_D(rd, insn);
3811 rn = (insn >> 16) & 0xf;
3812 rm = insn & 0xf;
3813 load = (insn & (1 << 21)) != 0;
3814 if ((insn & (1 << 23)) == 0) {
3815 /* Load store all elements. */
3816 op = (insn >> 8) & 0xf;
3817 size = (insn >> 6) & 3;
3818 if (op > 10 || size == 3)
3819 return 1;
3820 nregs = neon_ls_element_type[op].nregs;
3821 interleave = neon_ls_element_type[op].interleave;
3822 gen_movl_T1_reg(s, rn);
3823 stride = (1 << size) * interleave;
3824 for (reg = 0; reg < nregs; reg++) {
3825 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3826 gen_movl_T1_reg(s, rn);
3827 gen_op_addl_T1_im((1 << size) * reg);
3828 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3829 gen_movl_T1_reg(s, rn);
3830 gen_op_addl_T1_im(1 << size);
3832 for (pass = 0; pass < 2; pass++) {
3833 if (size == 2) {
3834 if (load) {
3835 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3836 neon_store_reg(rd, pass, tmp);
3837 } else {
3838 tmp = neon_load_reg(rd, pass);
3839 gen_st32(tmp, cpu_T[1], IS_USER(s));
3841 gen_op_addl_T1_im(stride);
3842 } else if (size == 1) {
3843 if (load) {
3844 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3845 gen_op_addl_T1_im(stride);
3846 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3847 gen_op_addl_T1_im(stride);
3848 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3849 dead_tmp(tmp2);
3850 neon_store_reg(rd, pass, tmp);
3851 } else {
3852 tmp = neon_load_reg(rd, pass);
3853 tmp2 = new_tmp();
3854 tcg_gen_shri_i32(tmp2, tmp, 16);
3855 gen_st16(tmp, cpu_T[1], IS_USER(s));
3856 gen_op_addl_T1_im(stride);
3857 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3858 gen_op_addl_T1_im(stride);
3860 } else /* size == 0 */ {
3861 if (load) {
3862 TCGV_UNUSED(tmp2);
3863 for (n = 0; n < 4; n++) {
3864 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3865 gen_op_addl_T1_im(stride);
3866 if (n == 0) {
3867 tmp2 = tmp;
3868 } else {
3869 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3870 dead_tmp(tmp);
3873 neon_store_reg(rd, pass, tmp2);
3874 } else {
3875 tmp2 = neon_load_reg(rd, pass);
3876 for (n = 0; n < 4; n++) {
3877 tmp = new_tmp();
3878 if (n == 0) {
3879 tcg_gen_mov_i32(tmp, tmp2);
3880 } else {
3881 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3883 gen_st8(tmp, cpu_T[1], IS_USER(s));
3884 gen_op_addl_T1_im(stride);
3886 dead_tmp(tmp2);
3890 rd += neon_ls_element_type[op].spacing;
3892 stride = nregs * 8;
3893 } else {
3894 size = (insn >> 10) & 3;
3895 if (size == 3) {
3896 /* Load single element to all lanes. */
3897 if (!load)
3898 return 1;
3899 size = (insn >> 6) & 3;
3900 nregs = ((insn >> 8) & 3) + 1;
3901 stride = (insn & (1 << 5)) ? 2 : 1;
3902 gen_movl_T1_reg(s, rn);
3903 for (reg = 0; reg < nregs; reg++) {
3904 switch (size) {
3905 case 0:
3906 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3907 gen_neon_dup_u8(tmp, 0);
3908 break;
3909 case 1:
3910 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3911 gen_neon_dup_low16(tmp);
3912 break;
3913 case 2:
3914 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3915 break;
3916 case 3:
3917 return 1;
3918 default: /* Avoid compiler warnings. */
3919 abort();
3921 gen_op_addl_T1_im(1 << size);
3922 tmp2 = new_tmp();
3923 tcg_gen_mov_i32(tmp2, tmp);
3924 neon_store_reg(rd, 0, tmp2);
3925 neon_store_reg(rd, 1, tmp);
3926 rd += stride;
3928 stride = (1 << size) * nregs;
3929 } else {
3930 /* Single element. */
3931 pass = (insn >> 7) & 1;
3932 switch (size) {
3933 case 0:
3934 shift = ((insn >> 5) & 3) * 8;
3935 stride = 1;
3936 break;
3937 case 1:
3938 shift = ((insn >> 6) & 1) * 16;
3939 stride = (insn & (1 << 5)) ? 2 : 1;
3940 break;
3941 case 2:
3942 shift = 0;
3943 stride = (insn & (1 << 6)) ? 2 : 1;
3944 break;
3945 default:
3946 abort();
3948 nregs = ((insn >> 8) & 3) + 1;
3949 gen_movl_T1_reg(s, rn);
3950 for (reg = 0; reg < nregs; reg++) {
3951 if (load) {
3952 switch (size) {
3953 case 0:
3954 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3955 break;
3956 case 1:
3957 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3958 break;
3959 case 2:
3960 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3961 break;
3962 default: /* Avoid compiler warnings. */
3963 abort();
3965 if (size != 2) {
3966 tmp2 = neon_load_reg(rd, pass);
3967 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3968 dead_tmp(tmp2);
3970 neon_store_reg(rd, pass, tmp);
3971 } else { /* Store */
3972 tmp = neon_load_reg(rd, pass);
3973 if (shift)
3974 tcg_gen_shri_i32(tmp, tmp, shift);
3975 switch (size) {
3976 case 0:
3977 gen_st8(tmp, cpu_T[1], IS_USER(s));
3978 break;
3979 case 1:
3980 gen_st16(tmp, cpu_T[1], IS_USER(s));
3981 break;
3982 case 2:
3983 gen_st32(tmp, cpu_T[1], IS_USER(s));
3984 break;
3987 rd += stride;
3988 gen_op_addl_T1_im(1 << size);
3990 stride = nregs * (1 << size);
3993 if (rm != 15) {
3994 TCGv base;
3996 base = load_reg(s, rn);
3997 if (rm == 13) {
3998 tcg_gen_addi_i32(base, base, stride);
3999 } else {
4000 TCGv index;
4001 index = load_reg(s, rm);
4002 tcg_gen_add_i32(base, base, index);
4003 dead_tmp(index);
4005 store_reg(s, rn, base);
4007 return 0;
4010 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4011 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4013 tcg_gen_and_i32(t, t, c);
4014 tcg_gen_bic_i32(f, f, c);
4015 tcg_gen_or_i32(dest, t, f);
4018 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4020 switch (size) {
4021 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4022 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4023 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4024 default: abort();
4028 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4030 switch (size) {
4031 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4032 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4033 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4034 default: abort();
4038 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4040 switch (size) {
4041 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4042 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4043 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4044 default: abort();
4048 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4049 int q, int u)
4051 if (q) {
4052 if (u) {
4053 switch (size) {
4054 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4055 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4056 default: abort();
4058 } else {
4059 switch (size) {
4060 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4061 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4062 default: abort();
4065 } else {
4066 if (u) {
4067 switch (size) {
4068 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4069 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4070 default: abort();
4072 } else {
4073 switch (size) {
4074 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4075 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4076 default: abort();
4082 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4084 if (u) {
4085 switch (size) {
4086 case 0: gen_helper_neon_widen_u8(dest, src); break;
4087 case 1: gen_helper_neon_widen_u16(dest, src); break;
4088 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4089 default: abort();
4091 } else {
4092 switch (size) {
4093 case 0: gen_helper_neon_widen_s8(dest, src); break;
4094 case 1: gen_helper_neon_widen_s16(dest, src); break;
4095 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4096 default: abort();
4099 dead_tmp(src);
4102 static inline void gen_neon_addl(int size)
4104 switch (size) {
4105 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4106 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4107 case 2: tcg_gen_add_i64(CPU_V001); break;
4108 default: abort();
4112 static inline void gen_neon_subl(int size)
4114 switch (size) {
4115 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4116 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4117 case 2: tcg_gen_sub_i64(CPU_V001); break;
4118 default: abort();
4122 static inline void gen_neon_negl(TCGv_i64 var, int size)
4124 switch (size) {
4125 case 0: gen_helper_neon_negl_u16(var, var); break;
4126 case 1: gen_helper_neon_negl_u32(var, var); break;
4127 case 2: gen_helper_neon_negl_u64(var, var); break;
4128 default: abort();
4132 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4134 switch (size) {
4135 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4136 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4137 default: abort();
4141 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4143 TCGv_i64 tmp;
4145 switch ((size << 1) | u) {
4146 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4147 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4148 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4149 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4150 case 4:
4151 tmp = gen_muls_i64_i32(a, b);
4152 tcg_gen_mov_i64(dest, tmp);
4153 break;
4154 case 5:
4155 tmp = gen_mulu_i64_i32(a, b);
4156 tcg_gen_mov_i64(dest, tmp);
4157 break;
4158 default: abort();
4160 if (size < 2) {
4161 dead_tmp(b);
4162 dead_tmp(a);
4166 /* Translate a NEON data processing instruction. Return nonzero if the
4167 instruction is invalid.
4168 We process data in a mixture of 32-bit and 64-bit chunks.
4169 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4171 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4173 int op;
4174 int q;
4175 int rd, rn, rm;
4176 int size;
4177 int shift;
4178 int pass;
4179 int count;
4180 int pairwise;
4181 int u;
4182 int n;
4183 uint32_t imm;
4184 TCGv tmp;
4185 TCGv tmp2;
4186 TCGv tmp3;
4187 TCGv_i64 tmp64;
4189 if (!vfp_enabled(env))
4190 return 1;
4191 q = (insn & (1 << 6)) != 0;
4192 u = (insn >> 24) & 1;
4193 VFP_DREG_D(rd, insn);
4194 VFP_DREG_N(rn, insn);
4195 VFP_DREG_M(rm, insn);
4196 size = (insn >> 20) & 3;
4197 if ((insn & (1 << 23)) == 0) {
4198 /* Three register same length. */
4199 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4200 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4201 || op == 10 || op == 11 || op == 16)) {
4202 /* 64-bit element instructions. */
4203 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4204 neon_load_reg64(cpu_V0, rn + pass);
4205 neon_load_reg64(cpu_V1, rm + pass);
4206 switch (op) {
4207 case 1: /* VQADD */
4208 if (u) {
4209 gen_helper_neon_add_saturate_u64(CPU_V001);
4210 } else {
4211 gen_helper_neon_add_saturate_s64(CPU_V001);
4213 break;
4214 case 5: /* VQSUB */
4215 if (u) {
4216 gen_helper_neon_sub_saturate_u64(CPU_V001);
4217 } else {
4218 gen_helper_neon_sub_saturate_s64(CPU_V001);
4220 break;
4221 case 8: /* VSHL */
4222 if (u) {
4223 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4224 } else {
4225 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4227 break;
4228 case 9: /* VQSHL */
4229 if (u) {
4230 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4231 cpu_V0, cpu_V0);
4232 } else {
4233 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4234 cpu_V1, cpu_V0);
4236 break;
4237 case 10: /* VRSHL */
4238 if (u) {
4239 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4240 } else {
4241 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4243 break;
4244 case 11: /* VQRSHL */
4245 if (u) {
4246 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4247 cpu_V1, cpu_V0);
4248 } else {
4249 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4250 cpu_V1, cpu_V0);
4252 break;
4253 case 16:
4254 if (u) {
4255 tcg_gen_sub_i64(CPU_V001);
4256 } else {
4257 tcg_gen_add_i64(CPU_V001);
4259 break;
4260 default:
4261 abort();
4263 neon_store_reg64(cpu_V0, rd + pass);
4265 return 0;
4267 switch (op) {
4268 case 8: /* VSHL */
4269 case 9: /* VQSHL */
4270 case 10: /* VRSHL */
4271 case 11: /* VQRSHL */
4273 int rtmp;
4274 /* Shift instruction operands are reversed. */
4275 rtmp = rn;
4276 rn = rm;
4277 rm = rtmp;
4278 pairwise = 0;
4280 break;
4281 case 20: /* VPMAX */
4282 case 21: /* VPMIN */
4283 case 23: /* VPADD */
4284 pairwise = 1;
4285 break;
4286 case 26: /* VPADD (float) */
4287 pairwise = (u && size < 2);
4288 break;
4289 case 30: /* VPMIN/VPMAX (float) */
4290 pairwise = u;
4291 break;
4292 default:
4293 pairwise = 0;
4294 break;
4296 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4298 if (pairwise) {
4299 /* Pairwise. */
4300 if (q)
4301 n = (pass & 1) * 2;
4302 else
4303 n = 0;
4304 if (pass < q + 1) {
4305 NEON_GET_REG(T0, rn, n);
4306 NEON_GET_REG(T1, rn, n + 1);
4307 } else {
4308 NEON_GET_REG(T0, rm, n);
4309 NEON_GET_REG(T1, rm, n + 1);
4311 } else {
4312 /* Elementwise. */
4313 NEON_GET_REG(T0, rn, pass);
4314 NEON_GET_REG(T1, rm, pass);
4316 switch (op) {
4317 case 0: /* VHADD */
4318 GEN_NEON_INTEGER_OP(hadd);
4319 break;
4320 case 1: /* VQADD */
4321 GEN_NEON_INTEGER_OP_ENV(qadd);
4322 break;
4323 case 2: /* VRHADD */
4324 GEN_NEON_INTEGER_OP(rhadd);
4325 break;
4326 case 3: /* Logic ops. */
4327 switch ((u << 2) | size) {
4328 case 0: /* VAND */
4329 gen_op_andl_T0_T1();
4330 break;
4331 case 1: /* BIC */
4332 gen_op_bicl_T0_T1();
4333 break;
4334 case 2: /* VORR */
4335 gen_op_orl_T0_T1();
4336 break;
4337 case 3: /* VORN */
4338 gen_op_notl_T1();
4339 gen_op_orl_T0_T1();
4340 break;
4341 case 4: /* VEOR */
4342 gen_op_xorl_T0_T1();
4343 break;
4344 case 5: /* VBSL */
4345 tmp = neon_load_reg(rd, pass);
4346 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4347 dead_tmp(tmp);
4348 break;
4349 case 6: /* VBIT */
4350 tmp = neon_load_reg(rd, pass);
4351 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4352 dead_tmp(tmp);
4353 break;
4354 case 7: /* VBIF */
4355 tmp = neon_load_reg(rd, pass);
4356 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4357 dead_tmp(tmp);
4358 break;
4360 break;
4361 case 4: /* VHSUB */
4362 GEN_NEON_INTEGER_OP(hsub);
4363 break;
4364 case 5: /* VQSUB */
4365 GEN_NEON_INTEGER_OP_ENV(qsub);
4366 break;
4367 case 6: /* VCGT */
4368 GEN_NEON_INTEGER_OP(cgt);
4369 break;
4370 case 7: /* VCGE */
4371 GEN_NEON_INTEGER_OP(cge);
4372 break;
4373 case 8: /* VSHL */
4374 GEN_NEON_INTEGER_OP(shl);
4375 break;
4376 case 9: /* VQSHL */
4377 GEN_NEON_INTEGER_OP_ENV(qshl);
4378 break;
4379 case 10: /* VRSHL */
4380 GEN_NEON_INTEGER_OP(rshl);
4381 break;
4382 case 11: /* VQRSHL */
4383 GEN_NEON_INTEGER_OP_ENV(qrshl);
4384 break;
4385 case 12: /* VMAX */
4386 GEN_NEON_INTEGER_OP(max);
4387 break;
4388 case 13: /* VMIN */
4389 GEN_NEON_INTEGER_OP(min);
4390 break;
4391 case 14: /* VABD */
4392 GEN_NEON_INTEGER_OP(abd);
4393 break;
4394 case 15: /* VABA */
4395 GEN_NEON_INTEGER_OP(abd);
4396 NEON_GET_REG(T1, rd, pass);
4397 gen_neon_add(size);
4398 break;
4399 case 16:
4400 if (!u) { /* VADD */
4401 if (gen_neon_add(size))
4402 return 1;
4403 } else { /* VSUB */
4404 switch (size) {
4405 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4406 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4407 case 2: gen_op_subl_T0_T1(); break;
4408 default: return 1;
4411 break;
4412 case 17:
4413 if (!u) { /* VTST */
4414 switch (size) {
4415 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4416 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4417 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4418 default: return 1;
4420 } else { /* VCEQ */
4421 switch (size) {
4422 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4423 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4424 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4425 default: return 1;
4428 break;
4429 case 18: /* Multiply. */
4430 switch (size) {
4431 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4432 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4433 case 2: gen_op_mul_T0_T1(); break;
4434 default: return 1;
4436 NEON_GET_REG(T1, rd, pass);
4437 if (u) { /* VMLS */
4438 gen_neon_rsb(size);
4439 } else { /* VMLA */
4440 gen_neon_add(size);
4442 break;
4443 case 19: /* VMUL */
4444 if (u) { /* polynomial */
4445 gen_helper_neon_mul_p8(CPU_T001);
4446 } else { /* Integer */
4447 switch (size) {
4448 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4449 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4450 case 2: gen_op_mul_T0_T1(); break;
4451 default: return 1;
4454 break;
4455 case 20: /* VPMAX */
4456 GEN_NEON_INTEGER_OP(pmax);
4457 break;
4458 case 21: /* VPMIN */
4459 GEN_NEON_INTEGER_OP(pmin);
4460 break;
4461 case 22: /* Hultiply high. */
4462 if (!u) { /* VQDMULH */
4463 switch (size) {
4464 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4465 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4466 default: return 1;
4468 } else { /* VQRDHMUL */
4469 switch (size) {
4470 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4471 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4472 default: return 1;
4475 break;
4476 case 23: /* VPADD */
4477 if (u)
4478 return 1;
4479 switch (size) {
4480 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4481 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4482 case 2: gen_op_addl_T0_T1(); break;
4483 default: return 1;
4485 break;
4486 case 26: /* Floating point arithnetic. */
4487 switch ((u << 2) | size) {
4488 case 0: /* VADD */
4489 gen_helper_neon_add_f32(CPU_T001);
4490 break;
4491 case 2: /* VSUB */
4492 gen_helper_neon_sub_f32(CPU_T001);
4493 break;
4494 case 4: /* VPADD */
4495 gen_helper_neon_add_f32(CPU_T001);
4496 break;
4497 case 6: /* VABD */
4498 gen_helper_neon_abd_f32(CPU_T001);
4499 break;
4500 default:
4501 return 1;
4503 break;
4504 case 27: /* Float multiply. */
4505 gen_helper_neon_mul_f32(CPU_T001);
4506 if (!u) {
4507 NEON_GET_REG(T1, rd, pass);
4508 if (size == 0) {
4509 gen_helper_neon_add_f32(CPU_T001);
4510 } else {
4511 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4514 break;
4515 case 28: /* Float compare. */
4516 if (!u) {
4517 gen_helper_neon_ceq_f32(CPU_T001);
4518 } else {
4519 if (size == 0)
4520 gen_helper_neon_cge_f32(CPU_T001);
4521 else
4522 gen_helper_neon_cgt_f32(CPU_T001);
4524 break;
4525 case 29: /* Float compare absolute. */
4526 if (!u)
4527 return 1;
4528 if (size == 0)
4529 gen_helper_neon_acge_f32(CPU_T001);
4530 else
4531 gen_helper_neon_acgt_f32(CPU_T001);
4532 break;
4533 case 30: /* Float min/max. */
4534 if (size == 0)
4535 gen_helper_neon_max_f32(CPU_T001);
4536 else
4537 gen_helper_neon_min_f32(CPU_T001);
4538 break;
4539 case 31:
4540 if (size == 0)
4541 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4542 else
4543 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4544 break;
4545 default:
4546 abort();
4548 /* Save the result. For elementwise operations we can put it
4549 straight into the destination register. For pairwise operations
4550 we have to be careful to avoid clobbering the source operands. */
4551 if (pairwise && rd == rm) {
4552 gen_neon_movl_scratch_T0(pass);
4553 } else {
4554 NEON_SET_REG(T0, rd, pass);
4557 } /* for pass */
4558 if (pairwise && rd == rm) {
4559 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4560 gen_neon_movl_T0_scratch(pass);
4561 NEON_SET_REG(T0, rd, pass);
4564 /* End of 3 register same size operations. */
4565 } else if (insn & (1 << 4)) {
4566 if ((insn & 0x00380080) != 0) {
4567 /* Two registers and shift. */
4568 op = (insn >> 8) & 0xf;
4569 if (insn & (1 << 7)) {
4570 /* 64-bit shift. */
4571 size = 3;
4572 } else {
4573 size = 2;
4574 while ((insn & (1 << (size + 19))) == 0)
4575 size--;
4577 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4578 /* To avoid excessive dumplication of ops we implement shift
4579 by immediate using the variable shift operations. */
4580 if (op < 8) {
4581 /* Shift by immediate:
4582 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4583 /* Right shifts are encoded as N - shift, where N is the
4584 element size in bits. */
4585 if (op <= 4)
4586 shift = shift - (1 << (size + 3));
4587 if (size == 3) {
4588 count = q + 1;
4589 } else {
4590 count = q ? 4: 2;
4592 switch (size) {
4593 case 0:
4594 imm = (uint8_t) shift;
4595 imm |= imm << 8;
4596 imm |= imm << 16;
4597 break;
4598 case 1:
4599 imm = (uint16_t) shift;
4600 imm |= imm << 16;
4601 break;
4602 case 2:
4603 case 3:
4604 imm = shift;
4605 break;
4606 default:
4607 abort();
4610 for (pass = 0; pass < count; pass++) {
4611 if (size == 3) {
4612 neon_load_reg64(cpu_V0, rm + pass);
4613 tcg_gen_movi_i64(cpu_V1, imm);
4614 switch (op) {
4615 case 0: /* VSHR */
4616 case 1: /* VSRA */
4617 if (u)
4618 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4619 else
4620 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4621 break;
4622 case 2: /* VRSHR */
4623 case 3: /* VRSRA */
4624 if (u)
4625 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4626 else
4627 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4628 break;
4629 case 4: /* VSRI */
4630 if (!u)
4631 return 1;
4632 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4633 break;
4634 case 5: /* VSHL, VSLI */
4635 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4636 break;
4637 case 6: /* VQSHL */
4638 if (u)
4639 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4640 else
4641 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4642 break;
4643 case 7: /* VQSHLU */
4644 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4645 break;
4647 if (op == 1 || op == 3) {
4648 /* Accumulate. */
4649 neon_load_reg64(cpu_V0, rd + pass);
4650 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4651 } else if (op == 4 || (op == 5 && u)) {
4652 /* Insert */
4653 cpu_abort(env, "VS[LR]I.64 not implemented");
4655 neon_store_reg64(cpu_V0, rd + pass);
4656 } else { /* size < 3 */
4657 /* Operands in T0 and T1. */
4658 gen_op_movl_T1_im(imm);
4659 NEON_GET_REG(T0, rm, pass);
4660 switch (op) {
4661 case 0: /* VSHR */
4662 case 1: /* VSRA */
4663 GEN_NEON_INTEGER_OP(shl);
4664 break;
4665 case 2: /* VRSHR */
4666 case 3: /* VRSRA */
4667 GEN_NEON_INTEGER_OP(rshl);
4668 break;
4669 case 4: /* VSRI */
4670 if (!u)
4671 return 1;
4672 GEN_NEON_INTEGER_OP(shl);
4673 break;
4674 case 5: /* VSHL, VSLI */
4675 switch (size) {
4676 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4677 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4678 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4679 default: return 1;
4681 break;
4682 case 6: /* VQSHL */
4683 GEN_NEON_INTEGER_OP_ENV(qshl);
4684 break;
4685 case 7: /* VQSHLU */
4686 switch (size) {
4687 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4688 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4689 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4690 default: return 1;
4692 break;
4695 if (op == 1 || op == 3) {
4696 /* Accumulate. */
4697 NEON_GET_REG(T1, rd, pass);
4698 gen_neon_add(size);
4699 } else if (op == 4 || (op == 5 && u)) {
4700 /* Insert */
4701 switch (size) {
4702 case 0:
4703 if (op == 4)
4704 imm = 0xff >> -shift;
4705 else
4706 imm = (uint8_t)(0xff << shift);
4707 imm |= imm << 8;
4708 imm |= imm << 16;
4709 break;
4710 case 1:
4711 if (op == 4)
4712 imm = 0xffff >> -shift;
4713 else
4714 imm = (uint16_t)(0xffff << shift);
4715 imm |= imm << 16;
4716 break;
4717 case 2:
4718 if (op == 4)
4719 imm = 0xffffffffu >> -shift;
4720 else
4721 imm = 0xffffffffu << shift;
4722 break;
4723 default:
4724 abort();
4726 tmp = neon_load_reg(rd, pass);
4727 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4728 tcg_gen_andi_i32(tmp, tmp, ~imm);
4729 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4731 NEON_SET_REG(T0, rd, pass);
4733 } /* for pass */
4734 } else if (op < 10) {
4735 /* Shift by immediate and narrow:
4736 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4737 shift = shift - (1 << (size + 3));
4738 size++;
4739 switch (size) {
4740 case 1:
4741 imm = (uint16_t)shift;
4742 imm |= imm << 16;
4743 tmp2 = tcg_const_i32(imm);
4744 TCGV_UNUSED_I64(tmp64);
4745 break;
4746 case 2:
4747 imm = (uint32_t)shift;
4748 tmp2 = tcg_const_i32(imm);
4749 TCGV_UNUSED_I64(tmp64);
4750 break;
4751 case 3:
4752 tmp64 = tcg_const_i64(shift);
4753 TCGV_UNUSED(tmp2);
4754 break;
4755 default:
4756 abort();
4759 for (pass = 0; pass < 2; pass++) {
4760 if (size == 3) {
4761 neon_load_reg64(cpu_V0, rm + pass);
4762 if (q) {
4763 if (u)
4764 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4765 else
4766 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4767 } else {
4768 if (u)
4769 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4770 else
4771 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4773 } else {
4774 tmp = neon_load_reg(rm + pass, 0);
4775 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4776 tmp3 = neon_load_reg(rm + pass, 1);
4777 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4778 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4779 dead_tmp(tmp);
4780 dead_tmp(tmp3);
4782 tmp = new_tmp();
4783 if (op == 8 && !u) {
4784 gen_neon_narrow(size - 1, tmp, cpu_V0);
4785 } else {
4786 if (op == 8)
4787 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4788 else
4789 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4791 if (pass == 0) {
4792 tmp2 = tmp;
4793 } else {
4794 neon_store_reg(rd, 0, tmp2);
4795 neon_store_reg(rd, 1, tmp);
4797 } /* for pass */
4798 } else if (op == 10) {
4799 /* VSHLL */
4800 if (q || size == 3)
4801 return 1;
4802 tmp = neon_load_reg(rm, 0);
4803 tmp2 = neon_load_reg(rm, 1);
4804 for (pass = 0; pass < 2; pass++) {
4805 if (pass == 1)
4806 tmp = tmp2;
4808 gen_neon_widen(cpu_V0, tmp, size, u);
4810 if (shift != 0) {
4811 /* The shift is less than the width of the source
4812 type, so we can just shift the whole register. */
4813 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4814 if (size < 2 || !u) {
4815 uint64_t imm64;
4816 if (size == 0) {
4817 imm = (0xffu >> (8 - shift));
4818 imm |= imm << 16;
4819 } else {
4820 imm = 0xffff >> (16 - shift);
4822 imm64 = imm | (((uint64_t)imm) << 32);
4823 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4826 neon_store_reg64(cpu_V0, rd + pass);
4828 } else if (op == 15 || op == 16) {
4829 /* VCVT fixed-point. */
4830 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4831 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4832 if (op & 1) {
4833 if (u)
4834 gen_vfp_ulto(0, shift);
4835 else
4836 gen_vfp_slto(0, shift);
4837 } else {
4838 if (u)
4839 gen_vfp_toul(0, shift);
4840 else
4841 gen_vfp_tosl(0, shift);
4843 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4845 } else {
4846 return 1;
4848 } else { /* (insn & 0x00380080) == 0 */
4849 int invert;
4851 op = (insn >> 8) & 0xf;
4852 /* One register and immediate. */
4853 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4854 invert = (insn & (1 << 5)) != 0;
4855 switch (op) {
4856 case 0: case 1:
4857 /* no-op */
4858 break;
4859 case 2: case 3:
4860 imm <<= 8;
4861 break;
4862 case 4: case 5:
4863 imm <<= 16;
4864 break;
4865 case 6: case 7:
4866 imm <<= 24;
4867 break;
4868 case 8: case 9:
4869 imm |= imm << 16;
4870 break;
4871 case 10: case 11:
4872 imm = (imm << 8) | (imm << 24);
4873 break;
4874 case 12:
4875 imm = (imm < 8) | 0xff;
4876 break;
4877 case 13:
4878 imm = (imm << 16) | 0xffff;
4879 break;
4880 case 14:
4881 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4882 if (invert)
4883 imm = ~imm;
4884 break;
4885 case 15:
4886 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4887 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4888 break;
4890 if (invert)
4891 imm = ~imm;
4893 if (op != 14 || !invert)
4894 gen_op_movl_T1_im(imm);
4896 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4897 if (op & 1 && op < 12) {
4898 tmp = neon_load_reg(rd, pass);
4899 if (invert) {
4900 /* The immediate value has already been inverted, so
4901 BIC becomes AND. */
4902 tcg_gen_andi_i32(tmp, tmp, imm);
4903 } else {
4904 tcg_gen_ori_i32(tmp, tmp, imm);
4906 } else {
4907 /* VMOV, VMVN. */
4908 tmp = new_tmp();
4909 if (op == 14 && invert) {
4910 uint32_t val;
4911 val = 0;
4912 for (n = 0; n < 4; n++) {
4913 if (imm & (1 << (n + (pass & 1) * 4)))
4914 val |= 0xff << (n * 8);
4916 tcg_gen_movi_i32(tmp, val);
4917 } else {
4918 tcg_gen_movi_i32(tmp, imm);
4921 neon_store_reg(rd, pass, tmp);
4924 } else { /* (insn & 0x00800010 == 0x00800000) */
4925 if (size != 3) {
4926 op = (insn >> 8) & 0xf;
4927 if ((insn & (1 << 6)) == 0) {
4928 /* Three registers of different lengths. */
4929 int src1_wide;
4930 int src2_wide;
4931 int prewiden;
4932 /* prewiden, src1_wide, src2_wide */
4933 static const int neon_3reg_wide[16][3] = {
4934 {1, 0, 0}, /* VADDL */
4935 {1, 1, 0}, /* VADDW */
4936 {1, 0, 0}, /* VSUBL */
4937 {1, 1, 0}, /* VSUBW */
4938 {0, 1, 1}, /* VADDHN */
4939 {0, 0, 0}, /* VABAL */
4940 {0, 1, 1}, /* VSUBHN */
4941 {0, 0, 0}, /* VABDL */
4942 {0, 0, 0}, /* VMLAL */
4943 {0, 0, 0}, /* VQDMLAL */
4944 {0, 0, 0}, /* VMLSL */
4945 {0, 0, 0}, /* VQDMLSL */
4946 {0, 0, 0}, /* Integer VMULL */
4947 {0, 0, 0}, /* VQDMULL */
4948 {0, 0, 0} /* Polynomial VMULL */
4951 prewiden = neon_3reg_wide[op][0];
4952 src1_wide = neon_3reg_wide[op][1];
4953 src2_wide = neon_3reg_wide[op][2];
4955 if (size == 0 && (op == 9 || op == 11 || op == 13))
4956 return 1;
4958 /* Avoid overlapping operands. Wide source operands are
4959 always aligned so will never overlap with wide
4960 destinations in problematic ways. */
4961 if (rd == rm && !src2_wide) {
4962 NEON_GET_REG(T0, rm, 1);
4963 gen_neon_movl_scratch_T0(2);
4964 } else if (rd == rn && !src1_wide) {
4965 NEON_GET_REG(T0, rn, 1);
4966 gen_neon_movl_scratch_T0(2);
4968 TCGV_UNUSED(tmp3);
4969 for (pass = 0; pass < 2; pass++) {
4970 if (src1_wide) {
4971 neon_load_reg64(cpu_V0, rn + pass);
4972 TCGV_UNUSED(tmp);
4973 } else {
4974 if (pass == 1 && rd == rn) {
4975 gen_neon_movl_T0_scratch(2);
4976 tmp = new_tmp();
4977 tcg_gen_mov_i32(tmp, cpu_T[0]);
4978 } else {
4979 tmp = neon_load_reg(rn, pass);
4981 if (prewiden) {
4982 gen_neon_widen(cpu_V0, tmp, size, u);
4985 if (src2_wide) {
4986 neon_load_reg64(cpu_V1, rm + pass);
4987 TCGV_UNUSED(tmp2);
4988 } else {
4989 if (pass == 1 && rd == rm) {
4990 gen_neon_movl_T0_scratch(2);
4991 tmp2 = new_tmp();
4992 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4993 } else {
4994 tmp2 = neon_load_reg(rm, pass);
4996 if (prewiden) {
4997 gen_neon_widen(cpu_V1, tmp2, size, u);
5000 switch (op) {
5001 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5002 gen_neon_addl(size);
5003 break;
5004 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
5005 gen_neon_subl(size);
5006 break;
5007 case 5: case 7: /* VABAL, VABDL */
5008 switch ((size << 1) | u) {
5009 case 0:
5010 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5011 break;
5012 case 1:
5013 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5014 break;
5015 case 2:
5016 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5017 break;
5018 case 3:
5019 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5020 break;
5021 case 4:
5022 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5023 break;
5024 case 5:
5025 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5026 break;
5027 default: abort();
5029 dead_tmp(tmp2);
5030 dead_tmp(tmp);
5031 break;
5032 case 8: case 9: case 10: case 11: case 12: case 13:
5033 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5034 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5035 break;
5036 case 14: /* Polynomial VMULL */
5037 cpu_abort(env, "Polynomial VMULL not implemented");
5039 default: /* 15 is RESERVED. */
5040 return 1;
5042 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
5043 /* Accumulate. */
5044 if (op == 10 || op == 11) {
5045 gen_neon_negl(cpu_V0, size);
5048 if (op != 13) {
5049 neon_load_reg64(cpu_V1, rd + pass);
5052 switch (op) {
5053 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5054 gen_neon_addl(size);
5055 break;
5056 case 9: case 11: /* VQDMLAL, VQDMLSL */
5057 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5058 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5059 break;
5060 /* Fall through. */
5061 case 13: /* VQDMULL */
5062 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5063 break;
5064 default:
5065 abort();
5067 neon_store_reg64(cpu_V0, rd + pass);
5068 } else if (op == 4 || op == 6) {
5069 /* Narrowing operation. */
5070 tmp = new_tmp();
5071 if (u) {
5072 switch (size) {
5073 case 0:
5074 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5075 break;
5076 case 1:
5077 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5078 break;
5079 case 2:
5080 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5081 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5082 break;
5083 default: abort();
5085 } else {
5086 switch (size) {
5087 case 0:
5088 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5089 break;
5090 case 1:
5091 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5092 break;
5093 case 2:
5094 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5095 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5096 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5097 break;
5098 default: abort();
5101 if (pass == 0) {
5102 tmp3 = tmp;
5103 } else {
5104 neon_store_reg(rd, 0, tmp3);
5105 neon_store_reg(rd, 1, tmp);
5107 } else {
5108 /* Write back the result. */
5109 neon_store_reg64(cpu_V0, rd + pass);
5112 } else {
5113 /* Two registers and a scalar. */
5114 switch (op) {
5115 case 0: /* Integer VMLA scalar */
5116 case 1: /* Float VMLA scalar */
5117 case 4: /* Integer VMLS scalar */
5118 case 5: /* Floating point VMLS scalar */
5119 case 8: /* Integer VMUL scalar */
5120 case 9: /* Floating point VMUL scalar */
5121 case 12: /* VQDMULH scalar */
5122 case 13: /* VQRDMULH scalar */
5123 gen_neon_get_scalar(size, rm);
5124 gen_neon_movl_scratch_T0(0);
5125 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5126 if (pass != 0)
5127 gen_neon_movl_T0_scratch(0);
5128 NEON_GET_REG(T1, rn, pass);
5129 if (op == 12) {
5130 if (size == 1) {
5131 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5132 } else {
5133 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5135 } else if (op == 13) {
5136 if (size == 1) {
5137 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5138 } else {
5139 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5141 } else if (op & 1) {
5142 gen_helper_neon_mul_f32(CPU_T001);
5143 } else {
5144 switch (size) {
5145 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5146 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5147 case 2: gen_op_mul_T0_T1(); break;
5148 default: return 1;
5151 if (op < 8) {
5152 /* Accumulate. */
5153 NEON_GET_REG(T1, rd, pass);
5154 switch (op) {
5155 case 0:
5156 gen_neon_add(size);
5157 break;
5158 case 1:
5159 gen_helper_neon_add_f32(CPU_T001);
5160 break;
5161 case 4:
5162 gen_neon_rsb(size);
5163 break;
5164 case 5:
5165 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5166 break;
5167 default:
5168 abort();
5171 NEON_SET_REG(T0, rd, pass);
5173 break;
5174 case 2: /* VMLAL sclar */
5175 case 3: /* VQDMLAL scalar */
5176 case 6: /* VMLSL scalar */
5177 case 7: /* VQDMLSL scalar */
5178 case 10: /* VMULL scalar */
5179 case 11: /* VQDMULL scalar */
5180 if (size == 0 && (op == 3 || op == 7 || op == 11))
5181 return 1;
5183 gen_neon_get_scalar(size, rm);
5184 NEON_GET_REG(T1, rn, 1);
5186 for (pass = 0; pass < 2; pass++) {
5187 if (pass == 0) {
5188 tmp = neon_load_reg(rn, 0);
5189 } else {
5190 tmp = new_tmp();
5191 tcg_gen_mov_i32(tmp, cpu_T[1]);
5193 tmp2 = new_tmp();
5194 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5195 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5196 if (op == 6 || op == 7) {
5197 gen_neon_negl(cpu_V0, size);
5199 if (op != 11) {
5200 neon_load_reg64(cpu_V1, rd + pass);
5202 switch (op) {
5203 case 2: case 6:
5204 gen_neon_addl(size);
5205 break;
5206 case 3: case 7:
5207 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5208 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5209 break;
5210 case 10:
5211 /* no-op */
5212 break;
5213 case 11:
5214 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5215 break;
5216 default:
5217 abort();
5219 neon_store_reg64(cpu_V0, rd + pass);
5221 break;
5222 default: /* 14 and 15 are RESERVED */
5223 return 1;
5226 } else { /* size == 3 */
5227 if (!u) {
5228 /* Extract. */
5229 imm = (insn >> 8) & 0xf;
5230 count = q + 1;
5232 if (imm > 7 && !q)
5233 return 1;
5235 if (imm == 0) {
5236 neon_load_reg64(cpu_V0, rn);
5237 if (q) {
5238 neon_load_reg64(cpu_V1, rn + 1);
5240 } else if (imm == 8) {
5241 neon_load_reg64(cpu_V0, rn + 1);
5242 if (q) {
5243 neon_load_reg64(cpu_V1, rm);
5245 } else if (q) {
5246 tmp64 = tcg_temp_new_i64();
5247 if (imm < 8) {
5248 neon_load_reg64(cpu_V0, rn);
5249 neon_load_reg64(tmp64, rn + 1);
5250 } else {
5251 neon_load_reg64(cpu_V0, rn + 1);
5252 neon_load_reg64(tmp64, rm);
5254 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5255 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5256 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5257 if (imm < 8) {
5258 neon_load_reg64(cpu_V1, rm);
5259 } else {
5260 neon_load_reg64(cpu_V1, rm + 1);
5261 imm -= 8;
5263 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5264 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5265 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5266 } else {
5267 /* BUGFIX */
5268 neon_load_reg64(cpu_V0, rn);
5269 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5270 neon_load_reg64(cpu_V1, rm);
5271 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5272 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5274 neon_store_reg64(cpu_V0, rd);
5275 if (q) {
5276 neon_store_reg64(cpu_V1, rd + 1);
5278 } else if ((insn & (1 << 11)) == 0) {
5279 /* Two register misc. */
5280 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5281 size = (insn >> 18) & 3;
5282 switch (op) {
5283 case 0: /* VREV64 */
5284 if (size == 3)
5285 return 1;
5286 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5287 NEON_GET_REG(T0, rm, pass * 2);
5288 NEON_GET_REG(T1, rm, pass * 2 + 1);
5289 switch (size) {
5290 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5291 case 1: gen_swap_half(cpu_T[0]); break;
5292 case 2: /* no-op */ break;
5293 default: abort();
5295 NEON_SET_REG(T0, rd, pass * 2 + 1);
5296 if (size == 2) {
5297 NEON_SET_REG(T1, rd, pass * 2);
5298 } else {
5299 gen_op_movl_T0_T1();
5300 switch (size) {
5301 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5302 case 1: gen_swap_half(cpu_T[0]); break;
5303 default: abort();
5305 NEON_SET_REG(T0, rd, pass * 2);
5308 break;
5309 case 4: case 5: /* VPADDL */
5310 case 12: case 13: /* VPADAL */
5311 if (size == 3)
5312 return 1;
5313 for (pass = 0; pass < q + 1; pass++) {
5314 tmp = neon_load_reg(rm, pass * 2);
5315 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5316 tmp = neon_load_reg(rm, pass * 2 + 1);
5317 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5318 switch (size) {
5319 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5320 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5321 case 2: tcg_gen_add_i64(CPU_V001); break;
5322 default: abort();
5324 if (op >= 12) {
5325 /* Accumulate. */
5326 neon_load_reg64(cpu_V1, rd + pass);
5327 gen_neon_addl(size);
5329 neon_store_reg64(cpu_V0, rd + pass);
5331 break;
5332 case 33: /* VTRN */
5333 if (size == 2) {
5334 for (n = 0; n < (q ? 4 : 2); n += 2) {
5335 NEON_GET_REG(T0, rm, n);
5336 NEON_GET_REG(T1, rd, n + 1);
5337 NEON_SET_REG(T1, rm, n);
5338 NEON_SET_REG(T0, rd, n + 1);
5340 } else {
5341 goto elementwise;
5343 break;
5344 case 34: /* VUZP */
5345 /* Reg Before After
5346 Rd A3 A2 A1 A0 B2 B0 A2 A0
5347 Rm B3 B2 B1 B0 B3 B1 A3 A1
5349 if (size == 3)
5350 return 1;
5351 gen_neon_unzip(rd, q, 0, size);
5352 gen_neon_unzip(rm, q, 4, size);
5353 if (q) {
5354 static int unzip_order_q[8] =
5355 {0, 2, 4, 6, 1, 3, 5, 7};
5356 for (n = 0; n < 8; n++) {
5357 int reg = (n < 4) ? rd : rm;
5358 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5359 NEON_SET_REG(T0, reg, n % 4);
5361 } else {
5362 static int unzip_order[4] =
5363 {0, 4, 1, 5};
5364 for (n = 0; n < 4; n++) {
5365 int reg = (n < 2) ? rd : rm;
5366 gen_neon_movl_T0_scratch(unzip_order[n]);
5367 NEON_SET_REG(T0, reg, n % 2);
5370 break;
5371 case 35: /* VZIP */
5372 /* Reg Before After
5373 Rd A3 A2 A1 A0 B1 A1 B0 A0
5374 Rm B3 B2 B1 B0 B3 A3 B2 A2
5376 if (size == 3)
5377 return 1;
5378 count = (q ? 4 : 2);
5379 for (n = 0; n < count; n++) {
5380 NEON_GET_REG(T0, rd, n);
5381 NEON_GET_REG(T1, rd, n);
5382 switch (size) {
5383 case 0: gen_neon_zip_u8(cpu_T[0], cpu_T[1]); break;
5384 case 1: gen_neon_zip_u16(cpu_T[0], cpu_T[1]); break;
5385 case 2: /* no-op */; break;
5386 default: abort();
5388 gen_neon_movl_scratch_T0(n * 2);
5389 gen_neon_movl_scratch_T1(n * 2 + 1);
5391 for (n = 0; n < count * 2; n++) {
5392 int reg = (n < count) ? rd : rm;
5393 gen_neon_movl_T0_scratch(n);
5394 NEON_SET_REG(T0, reg, n % count);
5396 break;
5397 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5398 if (size == 3)
5399 return 1;
5400 TCGV_UNUSED(tmp2);
5401 for (pass = 0; pass < 2; pass++) {
5402 neon_load_reg64(cpu_V0, rm + pass);
5403 tmp = new_tmp();
5404 if (op == 36 && q == 0) {
5405 gen_neon_narrow(size, tmp, cpu_V0);
5406 } else if (q) {
5407 gen_neon_narrow_satu(size, tmp, cpu_V0);
5408 } else {
5409 gen_neon_narrow_sats(size, tmp, cpu_V0);
5411 if (pass == 0) {
5412 tmp2 = tmp;
5413 } else {
5414 neon_store_reg(rd, 0, tmp2);
5415 neon_store_reg(rd, 1, tmp);
5418 break;
5419 case 38: /* VSHLL */
5420 if (q || size == 3)
5421 return 1;
5422 tmp = neon_load_reg(rm, 0);
5423 tmp2 = neon_load_reg(rm, 1);
5424 for (pass = 0; pass < 2; pass++) {
5425 if (pass == 1)
5426 tmp = tmp2;
5427 gen_neon_widen(cpu_V0, tmp, size, 1);
5428 neon_store_reg64(cpu_V0, rd + pass);
5430 break;
5431 default:
5432 elementwise:
5433 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5434 if (op == 30 || op == 31 || op >= 58) {
5435 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5436 neon_reg_offset(rm, pass));
5437 } else {
5438 NEON_GET_REG(T0, rm, pass);
5440 switch (op) {
5441 case 1: /* VREV32 */
5442 switch (size) {
5443 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5444 case 1: gen_swap_half(cpu_T[0]); break;
5445 default: return 1;
5447 break;
5448 case 2: /* VREV16 */
5449 if (size != 0)
5450 return 1;
5451 gen_rev16(cpu_T[0]);
5452 break;
5453 case 8: /* CLS */
5454 switch (size) {
5455 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5456 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5457 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5458 default: return 1;
5460 break;
5461 case 9: /* CLZ */
5462 switch (size) {
5463 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5464 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5465 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5466 default: return 1;
5468 break;
5469 case 10: /* CNT */
5470 if (size != 0)
5471 return 1;
5472 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5473 break;
5474 case 11: /* VNOT */
5475 if (size != 0)
5476 return 1;
5477 gen_op_notl_T0();
5478 break;
5479 case 14: /* VQABS */
5480 switch (size) {
5481 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5482 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5483 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5484 default: return 1;
5486 break;
5487 case 15: /* VQNEG */
5488 switch (size) {
5489 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5490 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5491 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5492 default: return 1;
5494 break;
5495 case 16: case 19: /* VCGT #0, VCLE #0 */
5496 gen_op_movl_T1_im(0);
5497 switch(size) {
5498 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5499 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5500 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5501 default: return 1;
5503 if (op == 19)
5504 gen_op_notl_T0();
5505 break;
5506 case 17: case 20: /* VCGE #0, VCLT #0 */
5507 gen_op_movl_T1_im(0);
5508 switch(size) {
5509 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5510 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5511 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5512 default: return 1;
5514 if (op == 20)
5515 gen_op_notl_T0();
5516 break;
5517 case 18: /* VCEQ #0 */
5518 gen_op_movl_T1_im(0);
5519 switch(size) {
5520 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5521 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5522 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5523 default: return 1;
5525 break;
5526 case 22: /* VABS */
5527 switch(size) {
5528 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5529 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5530 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5531 default: return 1;
5533 break;
5534 case 23: /* VNEG */
5535 gen_op_movl_T1_im(0);
5536 if (size == 3)
5537 return 1;
5538 gen_neon_rsb(size);
5539 break;
5540 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5541 gen_op_movl_T1_im(0);
5542 gen_helper_neon_cgt_f32(CPU_T001);
5543 if (op == 27)
5544 gen_op_notl_T0();
5545 break;
5546 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5547 gen_op_movl_T1_im(0);
5548 gen_helper_neon_cge_f32(CPU_T001);
5549 if (op == 28)
5550 gen_op_notl_T0();
5551 break;
5552 case 26: /* Float VCEQ #0 */
5553 gen_op_movl_T1_im(0);
5554 gen_helper_neon_ceq_f32(CPU_T001);
5555 break;
5556 case 30: /* Float VABS */
5557 gen_vfp_abs(0);
5558 break;
5559 case 31: /* Float VNEG */
5560 gen_vfp_neg(0);
5561 break;
5562 case 32: /* VSWP */
5563 NEON_GET_REG(T1, rd, pass);
5564 NEON_SET_REG(T1, rm, pass);
5565 break;
5566 case 33: /* VTRN */
5567 NEON_GET_REG(T1, rd, pass);
5568 switch (size) {
5569 case 0: gen_neon_trn_u8(cpu_T[0], cpu_T[1]); break;
5570 case 1: gen_neon_trn_u16(cpu_T[0], cpu_T[1]); break;
5571 case 2: abort();
5572 default: return 1;
5574 NEON_SET_REG(T1, rm, pass);
5575 break;
5576 case 56: /* Integer VRECPE */
5577 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5578 break;
5579 case 57: /* Integer VRSQRTE */
5580 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5581 break;
5582 case 58: /* Float VRECPE */
5583 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5584 break;
5585 case 59: /* Float VRSQRTE */
5586 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5587 break;
5588 case 60: /* VCVT.F32.S32 */
5589 gen_vfp_tosiz(0);
5590 break;
5591 case 61: /* VCVT.F32.U32 */
5592 gen_vfp_touiz(0);
5593 break;
5594 case 62: /* VCVT.S32.F32 */
5595 gen_vfp_sito(0);
5596 break;
5597 case 63: /* VCVT.U32.F32 */
5598 gen_vfp_uito(0);
5599 break;
5600 default:
5601 /* Reserved: 21, 29, 39-56 */
5602 return 1;
5604 if (op == 30 || op == 31 || op >= 58) {
5605 tcg_gen_st_f32(cpu_F0s, cpu_env,
5606 neon_reg_offset(rd, pass));
5607 } else {
5608 NEON_SET_REG(T0, rd, pass);
5611 break;
5613 } else if ((insn & (1 << 10)) == 0) {
5614 /* VTBL, VTBX. */
5615 n = ((insn >> 5) & 0x18) + 8;
5616 if (insn & (1 << 6)) {
5617 tmp = neon_load_reg(rd, 0);
5618 } else {
5619 tmp = new_tmp();
5620 tcg_gen_movi_i32(tmp, 0);
5622 tmp2 = neon_load_reg(rm, 0);
5623 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5624 tcg_const_i32(n));
5625 dead_tmp(tmp);
5626 if (insn & (1 << 6)) {
5627 tmp = neon_load_reg(rd, 1);
5628 } else {
5629 tmp = new_tmp();
5630 tcg_gen_movi_i32(tmp, 0);
5632 tmp3 = neon_load_reg(rm, 1);
5633 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5634 tcg_const_i32(n));
5635 neon_store_reg(rd, 0, tmp2);
5636 neon_store_reg(rd, 1, tmp3);
5637 dead_tmp(tmp);
5638 } else if ((insn & 0x380) == 0) {
5639 /* VDUP */
5640 if (insn & (1 << 19)) {
5641 NEON_SET_REG(T0, rm, 1);
5642 } else {
5643 NEON_SET_REG(T0, rm, 0);
5645 if (insn & (1 << 16)) {
5646 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5647 } else if (insn & (1 << 17)) {
5648 if ((insn >> 18) & 1)
5649 gen_neon_dup_high16(cpu_T[0]);
5650 else
5651 gen_neon_dup_low16(cpu_T[0]);
5653 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5654 NEON_SET_REG(T0, rd, pass);
5656 } else {
5657 return 1;
5661 return 0;
5664 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5666 int crn = (insn >> 16) & 0xf;
5667 int crm = insn & 0xf;
5668 int op1 = (insn >> 21) & 7;
5669 int op2 = (insn >> 5) & 7;
5670 int rt = (insn >> 12) & 0xf;
5671 TCGv tmp;
5673 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5674 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5675 /* TEECR */
5676 if (IS_USER(s))
5677 return 1;
5678 tmp = load_cpu_field(teecr);
5679 store_reg(s, rt, tmp);
5680 return 0;
5682 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5683 /* TEEHBR */
5684 if (IS_USER(s) && (env->teecr & 1))
5685 return 1;
5686 tmp = load_cpu_field(teehbr);
5687 store_reg(s, rt, tmp);
5688 return 0;
5691 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5692 op1, crn, crm, op2);
5693 return 1;
5696 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5698 int crn = (insn >> 16) & 0xf;
5699 int crm = insn & 0xf;
5700 int op1 = (insn >> 21) & 7;
5701 int op2 = (insn >> 5) & 7;
5702 int rt = (insn >> 12) & 0xf;
5703 TCGv tmp;
5705 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5706 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5707 /* TEECR */
5708 if (IS_USER(s))
5709 return 1;
5710 tmp = load_reg(s, rt);
5711 gen_helper_set_teecr(cpu_env, tmp);
5712 dead_tmp(tmp);
5713 return 0;
5715 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5716 /* TEEHBR */
5717 if (IS_USER(s) && (env->teecr & 1))
5718 return 1;
5719 tmp = load_reg(s, rt);
5720 store_cpu_field(tmp, teehbr);
5721 return 0;
5724 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5725 op1, crn, crm, op2);
5726 return 1;
5729 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5731 int cpnum;
5733 cpnum = (insn >> 8) & 0xf;
5734 if (arm_feature(env, ARM_FEATURE_XSCALE)
5735 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5736 return 1;
5738 switch (cpnum) {
5739 case 0:
5740 case 1:
5741 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5742 return disas_iwmmxt_insn(env, s, insn);
5743 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5744 return disas_dsp_insn(env, s, insn);
5746 return 1;
5747 case 10:
5748 case 11:
5749 return disas_vfp_insn (env, s, insn);
5750 case 14:
5751 /* Coprocessors 7-15 are architecturally reserved by ARM.
5752 Unfortunately Intel decided to ignore this. */
5753 if (arm_feature(env, ARM_FEATURE_XSCALE))
5754 goto board;
5755 if (insn & (1 << 20))
5756 return disas_cp14_read(env, s, insn);
5757 else
5758 return disas_cp14_write(env, s, insn);
5759 case 15:
5760 return disas_cp15_insn (env, s, insn);
5761 default:
5762 board:
5763 /* Unknown coprocessor. See if the board has hooked it. */
5764 return disas_cp_insn (env, s, insn);
5769 /* Store a 64-bit value to a register pair. Clobbers val. */
5770 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5772 TCGv tmp;
5773 tmp = new_tmp();
5774 tcg_gen_trunc_i64_i32(tmp, val);
5775 store_reg(s, rlow, tmp);
5776 tmp = new_tmp();
5777 tcg_gen_shri_i64(val, val, 32);
5778 tcg_gen_trunc_i64_i32(tmp, val);
5779 store_reg(s, rhigh, tmp);
5782 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5783 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5785 TCGv_i64 tmp;
5786 TCGv tmp2;
5788 /* Load value and extend to 64 bits. */
5789 tmp = tcg_temp_new_i64();
5790 tmp2 = load_reg(s, rlow);
5791 tcg_gen_extu_i32_i64(tmp, tmp2);
5792 dead_tmp(tmp2);
5793 tcg_gen_add_i64(val, val, tmp);
5796 /* load and add a 64-bit value from a register pair. */
5797 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5799 TCGv_i64 tmp;
5800 TCGv tmpl;
5801 TCGv tmph;
5803 /* Load 64-bit value rd:rn. */
5804 tmpl = load_reg(s, rlow);
5805 tmph = load_reg(s, rhigh);
5806 tmp = tcg_temp_new_i64();
5807 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5808 dead_tmp(tmpl);
5809 dead_tmp(tmph);
5810 tcg_gen_add_i64(val, val, tmp);
5813 /* Set N and Z flags from a 64-bit value. */
5814 static void gen_logicq_cc(TCGv_i64 val)
5816 TCGv tmp = new_tmp();
5817 gen_helper_logicq_cc(tmp, val);
5818 gen_logic_CC(tmp);
5819 dead_tmp(tmp);
5822 static void disas_arm_insn(CPUState * env, DisasContext *s)
5824 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5825 TCGv tmp;
5826 TCGv tmp2;
5827 TCGv tmp3;
5828 TCGv addr;
5829 TCGv_i64 tmp64;
5831 insn = ldl_code(s->pc);
5832 s->pc += 4;
5834 /* M variants do not implement ARM mode. */
5835 if (IS_M(env))
5836 goto illegal_op;
5837 cond = insn >> 28;
5838 if (cond == 0xf){
5839 /* Unconditional instructions. */
5840 if (((insn >> 25) & 7) == 1) {
5841 /* NEON Data processing. */
5842 if (!arm_feature(env, ARM_FEATURE_NEON))
5843 goto illegal_op;
5845 if (disas_neon_data_insn(env, s, insn))
5846 goto illegal_op;
5847 return;
5849 if ((insn & 0x0f100000) == 0x04000000) {
5850 /* NEON load/store. */
5851 if (!arm_feature(env, ARM_FEATURE_NEON))
5852 goto illegal_op;
5854 if (disas_neon_ls_insn(env, s, insn))
5855 goto illegal_op;
5856 return;
5858 if ((insn & 0x0d70f000) == 0x0550f000)
5859 return; /* PLD */
5860 else if ((insn & 0x0ffffdff) == 0x01010000) {
5861 ARCH(6);
5862 /* setend */
5863 if (insn & (1 << 9)) {
5864 /* BE8 mode not implemented. */
5865 goto illegal_op;
5867 return;
5868 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5869 switch ((insn >> 4) & 0xf) {
5870 case 1: /* clrex */
5871 ARCH(6K);
5872 gen_helper_clrex(cpu_env);
5873 return;
5874 case 4: /* dsb */
5875 case 5: /* dmb */
5876 case 6: /* isb */
5877 ARCH(7);
5878 /* We don't emulate caches so these are a no-op. */
5879 return;
5880 default:
5881 goto illegal_op;
5883 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5884 /* srs */
5885 int32_t offset;
5886 if (IS_USER(s))
5887 goto illegal_op;
5888 ARCH(6);
5889 op1 = (insn & 0x1f);
5890 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5891 addr = load_reg(s, 13);
5892 } else {
5893 addr = new_tmp();
5894 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5896 i = (insn >> 23) & 3;
5897 switch (i) {
5898 case 0: offset = -4; break; /* DA */
5899 case 1: offset = 0; break; /* IA */
5900 case 2: offset = -8; break; /* DB */
5901 case 3: offset = 4; break; /* IB */
5902 default: abort();
5904 if (offset)
5905 tcg_gen_addi_i32(addr, addr, offset);
5906 tmp = load_reg(s, 14);
5907 gen_st32(tmp, addr, 0);
5908 tmp = load_cpu_field(spsr);
5909 tcg_gen_addi_i32(addr, addr, 4);
5910 gen_st32(tmp, addr, 0);
5911 if (insn & (1 << 21)) {
5912 /* Base writeback. */
5913 switch (i) {
5914 case 0: offset = -8; break;
5915 case 1: offset = 4; break;
5916 case 2: offset = -4; break;
5917 case 3: offset = 0; break;
5918 default: abort();
5920 if (offset)
5921 tcg_gen_addi_i32(addr, addr, offset);
5922 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5923 store_reg(s, 13, addr);
5924 } else {
5925 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5926 dead_tmp(addr);
5928 } else {
5929 dead_tmp(addr);
5931 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5932 /* rfe */
5933 int32_t offset;
5934 if (IS_USER(s))
5935 goto illegal_op;
5936 ARCH(6);
5937 rn = (insn >> 16) & 0xf;
5938 addr = load_reg(s, rn);
5939 i = (insn >> 23) & 3;
5940 switch (i) {
5941 case 0: offset = -4; break; /* DA */
5942 case 1: offset = 0; break; /* IA */
5943 case 2: offset = -8; break; /* DB */
5944 case 3: offset = 4; break; /* IB */
5945 default: abort();
5947 if (offset)
5948 tcg_gen_addi_i32(addr, addr, offset);
5949 /* Load PC into tmp and CPSR into tmp2. */
5950 tmp = gen_ld32(addr, 0);
5951 tcg_gen_addi_i32(addr, addr, 4);
5952 tmp2 = gen_ld32(addr, 0);
5953 if (insn & (1 << 21)) {
5954 /* Base writeback. */
5955 switch (i) {
5956 case 0: offset = -8; break;
5957 case 1: offset = 4; break;
5958 case 2: offset = -4; break;
5959 case 3: offset = 0; break;
5960 default: abort();
5962 if (offset)
5963 tcg_gen_addi_i32(addr, addr, offset);
5964 store_reg(s, rn, addr);
5965 } else {
5966 dead_tmp(addr);
5968 gen_rfe(s, tmp, tmp2);
5969 return;
5970 } else if ((insn & 0x0e000000) == 0x0a000000) {
5971 /* branch link and change to thumb (blx <offset>) */
5972 int32_t offset;
5974 val = (uint32_t)s->pc;
5975 tmp = new_tmp();
5976 tcg_gen_movi_i32(tmp, val);
5977 store_reg(s, 14, tmp);
5978 /* Sign-extend the 24-bit offset */
5979 offset = (((int32_t)insn) << 8) >> 8;
5980 /* offset * 4 + bit24 * 2 + (thumb bit) */
5981 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5982 /* pipeline offset */
5983 val += 4;
5984 gen_bx_im(s, val);
5985 return;
5986 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5987 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5988 /* iWMMXt register transfer. */
5989 if (env->cp15.c15_cpar & (1 << 1))
5990 if (!disas_iwmmxt_insn(env, s, insn))
5991 return;
5993 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5994 /* Coprocessor double register transfer. */
5995 } else if ((insn & 0x0f000010) == 0x0e000010) {
5996 /* Additional coprocessor register transfer. */
5997 } else if ((insn & 0x0ff10020) == 0x01000000) {
5998 uint32_t mask;
5999 uint32_t val;
6000 /* cps (privileged) */
6001 if (IS_USER(s))
6002 return;
6003 mask = val = 0;
6004 if (insn & (1 << 19)) {
6005 if (insn & (1 << 8))
6006 mask |= CPSR_A;
6007 if (insn & (1 << 7))
6008 mask |= CPSR_I;
6009 if (insn & (1 << 6))
6010 mask |= CPSR_F;
6011 if (insn & (1 << 18))
6012 val |= mask;
6014 if (insn & (1 << 17)) {
6015 mask |= CPSR_M;
6016 val |= (insn & 0x1f);
6018 if (mask) {
6019 gen_set_psr_im(s, mask, 0, val);
6021 return;
6023 goto illegal_op;
6025 if (cond != 0xe) {
6026 /* if not always execute, we generate a conditional jump to
6027 next instruction */
6028 s->condlabel = gen_new_label();
6029 gen_test_cc(cond ^ 1, s->condlabel);
6030 s->condjmp = 1;
6032 if ((insn & 0x0f900000) == 0x03000000) {
6033 if ((insn & (1 << 21)) == 0) {
6034 ARCH(6T2);
6035 rd = (insn >> 12) & 0xf;
6036 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6037 if ((insn & (1 << 22)) == 0) {
6038 /* MOVW */
6039 tmp = new_tmp();
6040 tcg_gen_movi_i32(tmp, val);
6041 } else {
6042 /* MOVT */
6043 tmp = load_reg(s, rd);
6044 tcg_gen_ext16u_i32(tmp, tmp);
6045 tcg_gen_ori_i32(tmp, tmp, val << 16);
6047 store_reg(s, rd, tmp);
6048 } else {
6049 if (((insn >> 12) & 0xf) != 0xf)
6050 goto illegal_op;
6051 if (((insn >> 16) & 0xf) == 0) {
6052 gen_nop_hint(s, insn & 0xff);
6053 } else {
6054 /* CPSR = immediate */
6055 val = insn & 0xff;
6056 shift = ((insn >> 8) & 0xf) * 2;
6057 if (shift)
6058 val = (val >> shift) | (val << (32 - shift));
6059 i = ((insn & (1 << 22)) != 0);
6060 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6061 goto illegal_op;
6064 } else if ((insn & 0x0f900000) == 0x01000000
6065 && (insn & 0x00000090) != 0x00000090) {
6066 /* miscellaneous instructions */
6067 op1 = (insn >> 21) & 3;
6068 sh = (insn >> 4) & 0xf;
6069 rm = insn & 0xf;
6070 switch (sh) {
6071 case 0x0: /* move program status register */
6072 if (op1 & 1) {
6073 /* PSR = reg */
6074 tmp = load_reg(s, rm);
6075 i = ((op1 & 2) != 0);
6076 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6077 goto illegal_op;
6078 } else {
6079 /* reg = PSR */
6080 rd = (insn >> 12) & 0xf;
6081 if (op1 & 2) {
6082 if (IS_USER(s))
6083 goto illegal_op;
6084 tmp = load_cpu_field(spsr);
6085 } else {
6086 tmp = new_tmp();
6087 gen_helper_cpsr_read(tmp);
6089 store_reg(s, rd, tmp);
6091 break;
6092 case 0x1:
6093 if (op1 == 1) {
6094 /* branch/exchange thumb (bx). */
6095 tmp = load_reg(s, rm);
6096 gen_bx(s, tmp);
6097 } else if (op1 == 3) {
6098 /* clz */
6099 rd = (insn >> 12) & 0xf;
6100 tmp = load_reg(s, rm);
6101 gen_helper_clz(tmp, tmp);
6102 store_reg(s, rd, tmp);
6103 } else {
6104 goto illegal_op;
6106 break;
6107 case 0x2:
6108 if (op1 == 1) {
6109 ARCH(5J); /* bxj */
6110 /* Trivial implementation equivalent to bx. */
6111 tmp = load_reg(s, rm);
6112 gen_bx(s, tmp);
6113 } else {
6114 goto illegal_op;
6116 break;
6117 case 0x3:
6118 if (op1 != 1)
6119 goto illegal_op;
6121 /* branch link/exchange thumb (blx) */
6122 tmp = load_reg(s, rm);
6123 tmp2 = new_tmp();
6124 tcg_gen_movi_i32(tmp2, s->pc);
6125 store_reg(s, 14, tmp2);
6126 gen_bx(s, tmp);
6127 break;
6128 case 0x5: /* saturating add/subtract */
6129 rd = (insn >> 12) & 0xf;
6130 rn = (insn >> 16) & 0xf;
6131 tmp = load_reg(s, rm);
6132 tmp2 = load_reg(s, rn);
6133 if (op1 & 2)
6134 gen_helper_double_saturate(tmp2, tmp2);
6135 if (op1 & 1)
6136 gen_helper_sub_saturate(tmp, tmp, tmp2);
6137 else
6138 gen_helper_add_saturate(tmp, tmp, tmp2);
6139 dead_tmp(tmp2);
6140 store_reg(s, rd, tmp);
6141 break;
6142 case 7: /* bkpt */
6143 gen_set_condexec(s);
6144 gen_set_pc_im(s->pc - 4);
6145 gen_exception(EXCP_BKPT);
6146 s->is_jmp = DISAS_JUMP;
6147 break;
6148 case 0x8: /* signed multiply */
6149 case 0xa:
6150 case 0xc:
6151 case 0xe:
6152 rs = (insn >> 8) & 0xf;
6153 rn = (insn >> 12) & 0xf;
6154 rd = (insn >> 16) & 0xf;
6155 if (op1 == 1) {
6156 /* (32 * 16) >> 16 */
6157 tmp = load_reg(s, rm);
6158 tmp2 = load_reg(s, rs);
6159 if (sh & 4)
6160 tcg_gen_sari_i32(tmp2, tmp2, 16);
6161 else
6162 gen_sxth(tmp2);
6163 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6164 tcg_gen_shri_i64(tmp64, tmp64, 16);
6165 tmp = new_tmp();
6166 tcg_gen_trunc_i64_i32(tmp, tmp64);
6167 if ((sh & 2) == 0) {
6168 tmp2 = load_reg(s, rn);
6169 gen_helper_add_setq(tmp, tmp, tmp2);
6170 dead_tmp(tmp2);
6172 store_reg(s, rd, tmp);
6173 } else {
6174 /* 16 * 16 */
6175 tmp = load_reg(s, rm);
6176 tmp2 = load_reg(s, rs);
6177 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6178 dead_tmp(tmp2);
6179 if (op1 == 2) {
6180 tmp64 = tcg_temp_new_i64();
6181 tcg_gen_ext_i32_i64(tmp64, tmp);
6182 dead_tmp(tmp);
6183 gen_addq(s, tmp64, rn, rd);
6184 gen_storeq_reg(s, rn, rd, tmp64);
6185 } else {
6186 if (op1 == 0) {
6187 tmp2 = load_reg(s, rn);
6188 gen_helper_add_setq(tmp, tmp, tmp2);
6189 dead_tmp(tmp2);
6191 store_reg(s, rd, tmp);
6194 break;
6195 default:
6196 goto illegal_op;
6198 } else if (((insn & 0x0e000000) == 0 &&
6199 (insn & 0x00000090) != 0x90) ||
6200 ((insn & 0x0e000000) == (1 << 25))) {
6201 int set_cc, logic_cc, shiftop;
6203 op1 = (insn >> 21) & 0xf;
6204 set_cc = (insn >> 20) & 1;
6205 logic_cc = table_logic_cc[op1] & set_cc;
6207 /* data processing instruction */
6208 if (insn & (1 << 25)) {
6209 /* immediate operand */
6210 val = insn & 0xff;
6211 shift = ((insn >> 8) & 0xf) * 2;
6212 if (shift) {
6213 val = (val >> shift) | (val << (32 - shift));
6215 tmp2 = new_tmp();
6216 tcg_gen_movi_i32(tmp2, val);
6217 if (logic_cc && shift) {
6218 gen_set_CF_bit31(tmp2);
6220 } else {
6221 /* register */
6222 rm = (insn) & 0xf;
6223 tmp2 = load_reg(s, rm);
6224 shiftop = (insn >> 5) & 3;
6225 if (!(insn & (1 << 4))) {
6226 shift = (insn >> 7) & 0x1f;
6227 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6228 } else {
6229 rs = (insn >> 8) & 0xf;
6230 tmp = load_reg(s, rs);
6231 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6234 if (op1 != 0x0f && op1 != 0x0d) {
6235 rn = (insn >> 16) & 0xf;
6236 tmp = load_reg(s, rn);
6237 } else {
6238 TCGV_UNUSED(tmp);
6240 rd = (insn >> 12) & 0xf;
6241 switch(op1) {
6242 case 0x00:
6243 tcg_gen_and_i32(tmp, tmp, tmp2);
6244 if (logic_cc) {
6245 gen_logic_CC(tmp);
6247 store_reg_bx(env, s, rd, tmp);
6248 break;
6249 case 0x01:
6250 tcg_gen_xor_i32(tmp, tmp, tmp2);
6251 if (logic_cc) {
6252 gen_logic_CC(tmp);
6254 store_reg_bx(env, s, rd, tmp);
6255 break;
6256 case 0x02:
6257 if (set_cc && rd == 15) {
6258 /* SUBS r15, ... is used for exception return. */
6259 if (IS_USER(s)) {
6260 goto illegal_op;
6262 gen_helper_sub_cc(tmp, tmp, tmp2);
6263 gen_exception_return(s, tmp);
6264 } else {
6265 if (set_cc) {
6266 gen_helper_sub_cc(tmp, tmp, tmp2);
6267 } else {
6268 tcg_gen_sub_i32(tmp, tmp, tmp2);
6270 store_reg_bx(env, s, rd, tmp);
6272 break;
6273 case 0x03:
6274 if (set_cc) {
6275 gen_helper_sub_cc(tmp, tmp2, tmp);
6276 } else {
6277 tcg_gen_sub_i32(tmp, tmp2, tmp);
6279 store_reg_bx(env, s, rd, tmp);
6280 break;
6281 case 0x04:
6282 if (set_cc) {
6283 gen_helper_add_cc(tmp, tmp, tmp2);
6284 } else {
6285 tcg_gen_add_i32(tmp, tmp, tmp2);
6287 store_reg_bx(env, s, rd, tmp);
6288 break;
6289 case 0x05:
6290 if (set_cc) {
6291 gen_helper_adc_cc(tmp, tmp, tmp2);
6292 } else {
6293 gen_add_carry(tmp, tmp, tmp2);
6295 store_reg_bx(env, s, rd, tmp);
6296 break;
6297 case 0x06:
6298 if (set_cc) {
6299 gen_helper_sbc_cc(tmp, tmp, tmp2);
6300 } else {
6301 gen_sub_carry(tmp, tmp, tmp2);
6303 store_reg_bx(env, s, rd, tmp);
6304 break;
6305 case 0x07:
6306 if (set_cc) {
6307 gen_helper_sbc_cc(tmp, tmp2, tmp);
6308 } else {
6309 gen_sub_carry(tmp, tmp2, tmp);
6311 store_reg_bx(env, s, rd, tmp);
6312 break;
6313 case 0x08:
6314 if (set_cc) {
6315 tcg_gen_and_i32(tmp, tmp, tmp2);
6316 gen_logic_CC(tmp);
6318 dead_tmp(tmp);
6319 break;
6320 case 0x09:
6321 if (set_cc) {
6322 tcg_gen_xor_i32(tmp, tmp, tmp2);
6323 gen_logic_CC(tmp);
6325 dead_tmp(tmp);
6326 break;
6327 case 0x0a:
6328 if (set_cc) {
6329 gen_helper_sub_cc(tmp, tmp, tmp2);
6331 dead_tmp(tmp);
6332 break;
6333 case 0x0b:
6334 if (set_cc) {
6335 gen_helper_add_cc(tmp, tmp, tmp2);
6337 dead_tmp(tmp);
6338 break;
6339 case 0x0c:
6340 tcg_gen_or_i32(tmp, tmp, tmp2);
6341 if (logic_cc) {
6342 gen_logic_CC(tmp);
6344 store_reg_bx(env, s, rd, tmp);
6345 break;
6346 case 0x0d:
6347 if (logic_cc && rd == 15) {
6348 /* MOVS r15, ... is used for exception return. */
6349 if (IS_USER(s)) {
6350 goto illegal_op;
6352 gen_exception_return(s, tmp2);
6353 } else {
6354 if (logic_cc) {
6355 gen_logic_CC(tmp2);
6357 store_reg_bx(env, s, rd, tmp2);
6359 break;
6360 case 0x0e:
6361 tcg_gen_bic_i32(tmp, tmp, tmp2);
6362 if (logic_cc) {
6363 gen_logic_CC(tmp);
6365 store_reg_bx(env, s, rd, tmp);
6366 break;
6367 default:
6368 case 0x0f:
6369 tcg_gen_not_i32(tmp2, tmp2);
6370 if (logic_cc) {
6371 gen_logic_CC(tmp2);
6373 store_reg_bx(env, s, rd, tmp2);
6374 break;
6376 if (op1 != 0x0f && op1 != 0x0d) {
6377 dead_tmp(tmp2);
6379 } else {
6380 /* other instructions */
6381 op1 = (insn >> 24) & 0xf;
6382 switch(op1) {
6383 case 0x0:
6384 case 0x1:
6385 /* multiplies, extra load/stores */
6386 sh = (insn >> 5) & 3;
6387 if (sh == 0) {
6388 if (op1 == 0x0) {
6389 rd = (insn >> 16) & 0xf;
6390 rn = (insn >> 12) & 0xf;
6391 rs = (insn >> 8) & 0xf;
6392 rm = (insn) & 0xf;
6393 op1 = (insn >> 20) & 0xf;
6394 switch (op1) {
6395 case 0: case 1: case 2: case 3: case 6:
6396 /* 32 bit mul */
6397 tmp = load_reg(s, rs);
6398 tmp2 = load_reg(s, rm);
6399 tcg_gen_mul_i32(tmp, tmp, tmp2);
6400 dead_tmp(tmp2);
6401 if (insn & (1 << 22)) {
6402 /* Subtract (mls) */
6403 ARCH(6T2);
6404 tmp2 = load_reg(s, rn);
6405 tcg_gen_sub_i32(tmp, tmp2, tmp);
6406 dead_tmp(tmp2);
6407 } else if (insn & (1 << 21)) {
6408 /* Add */
6409 tmp2 = load_reg(s, rn);
6410 tcg_gen_add_i32(tmp, tmp, tmp2);
6411 dead_tmp(tmp2);
6413 if (insn & (1 << 20))
6414 gen_logic_CC(tmp);
6415 store_reg(s, rd, tmp);
6416 break;
6417 default:
6418 /* 64 bit mul */
6419 tmp = load_reg(s, rs);
6420 tmp2 = load_reg(s, rm);
6421 if (insn & (1 << 22))
6422 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6423 else
6424 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6425 if (insn & (1 << 21)) /* mult accumulate */
6426 gen_addq(s, tmp64, rn, rd);
6427 if (!(insn & (1 << 23))) { /* double accumulate */
6428 ARCH(6);
6429 gen_addq_lo(s, tmp64, rn);
6430 gen_addq_lo(s, tmp64, rd);
6432 if (insn & (1 << 20))
6433 gen_logicq_cc(tmp64);
6434 gen_storeq_reg(s, rn, rd, tmp64);
6435 break;
6437 } else {
6438 rn = (insn >> 16) & 0xf;
6439 rd = (insn >> 12) & 0xf;
6440 if (insn & (1 << 23)) {
6441 /* load/store exclusive */
6442 op1 = (insn >> 21) & 0x3;
6443 if (op1)
6444 ARCH(6K);
6445 else
6446 ARCH(6);
6447 addr = tcg_temp_local_new_i32();
6448 tcg_gen_mov_i32(addr, cpu_R[rn]);
6449 if (insn & (1 << 20)) {
6450 gen_helper_mark_exclusive(cpu_env, addr);
6451 switch (op1) {
6452 case 0: /* ldrex */
6453 tmp = gen_ld32(addr, IS_USER(s));
6454 break;
6455 case 1: /* ldrexd */
6456 tmp = gen_ld32(addr, IS_USER(s));
6457 store_reg(s, rd, tmp);
6458 tcg_gen_addi_i32(addr, addr, 4);
6459 tmp = gen_ld32(addr, IS_USER(s));
6460 rd++;
6461 break;
6462 case 2: /* ldrexb */
6463 tmp = gen_ld8u(addr, IS_USER(s));
6464 break;
6465 case 3: /* ldrexh */
6466 tmp = gen_ld16u(addr, IS_USER(s));
6467 break;
6468 default:
6469 abort();
6471 store_reg(s, rd, tmp);
6472 } else {
6473 int label = gen_new_label();
6474 rm = insn & 0xf;
6475 tmp2 = tcg_temp_local_new_i32();
6476 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6477 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6478 tmp = load_reg(s,rm);
6479 switch (op1) {
6480 case 0: /* strex */
6481 gen_st32(tmp, addr, IS_USER(s));
6482 break;
6483 case 1: /* strexd */
6484 gen_st32(tmp, addr, IS_USER(s));
6485 tcg_gen_addi_i32(addr, addr, 4);
6486 tmp = load_reg(s, rm + 1);
6487 gen_st32(tmp, addr, IS_USER(s));
6488 break;
6489 case 2: /* strexb */
6490 gen_st8(tmp, addr, IS_USER(s));
6491 break;
6492 case 3: /* strexh */
6493 gen_st16(tmp, addr, IS_USER(s));
6494 break;
6495 default:
6496 abort();
6498 gen_set_label(label);
6499 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6500 tcg_temp_free(tmp2);
6502 tcg_temp_free(addr);
6503 } else {
6504 /* SWP instruction */
6505 rm = (insn) & 0xf;
6507 /* ??? This is not really atomic. However we know
6508 we never have multiple CPUs running in parallel,
6509 so it is good enough. */
6510 addr = load_reg(s, rn);
6511 tmp = load_reg(s, rm);
6512 if (insn & (1 << 22)) {
6513 tmp2 = gen_ld8u(addr, IS_USER(s));
6514 gen_st8(tmp, addr, IS_USER(s));
6515 } else {
6516 tmp2 = gen_ld32(addr, IS_USER(s));
6517 gen_st32(tmp, addr, IS_USER(s));
6519 dead_tmp(addr);
6520 store_reg(s, rd, tmp2);
6523 } else {
6524 int address_offset;
6525 int load;
6526 /* Misc load/store */
6527 rn = (insn >> 16) & 0xf;
6528 rd = (insn >> 12) & 0xf;
6529 addr = load_reg(s, rn);
6530 if (insn & (1 << 24))
6531 gen_add_datah_offset(s, insn, 0, addr);
6532 address_offset = 0;
6533 if (insn & (1 << 20)) {
6534 /* load */
6535 switch(sh) {
6536 case 1:
6537 tmp = gen_ld16u(addr, IS_USER(s));
6538 break;
6539 case 2:
6540 tmp = gen_ld8s(addr, IS_USER(s));
6541 break;
6542 default:
6543 case 3:
6544 tmp = gen_ld16s(addr, IS_USER(s));
6545 break;
6547 load = 1;
6548 } else if (sh & 2) {
6549 /* doubleword */
6550 if (sh & 1) {
6551 /* store */
6552 tmp = load_reg(s, rd);
6553 gen_st32(tmp, addr, IS_USER(s));
6554 tcg_gen_addi_i32(addr, addr, 4);
6555 tmp = load_reg(s, rd + 1);
6556 gen_st32(tmp, addr, IS_USER(s));
6557 load = 0;
6558 } else {
6559 /* load */
6560 tmp = gen_ld32(addr, IS_USER(s));
6561 store_reg(s, rd, tmp);
6562 tcg_gen_addi_i32(addr, addr, 4);
6563 tmp = gen_ld32(addr, IS_USER(s));
6564 rd++;
6565 load = 1;
6567 address_offset = -4;
6568 } else {
6569 /* store */
6570 tmp = load_reg(s, rd);
6571 gen_st16(tmp, addr, IS_USER(s));
6572 load = 0;
6574 /* Perform base writeback before the loaded value to
6575 ensure correct behavior with overlapping index registers.
6576 ldrd with base writeback is is undefined if the
6577 destination and index registers overlap. */
6578 if (!(insn & (1 << 24))) {
6579 gen_add_datah_offset(s, insn, address_offset, addr);
6580 store_reg(s, rn, addr);
6581 } else if (insn & (1 << 21)) {
6582 if (address_offset)
6583 tcg_gen_addi_i32(addr, addr, address_offset);
6584 store_reg(s, rn, addr);
6585 } else {
6586 dead_tmp(addr);
6588 if (load) {
6589 /* Complete the load. */
6590 store_reg(s, rd, tmp);
6593 break;
6594 case 0x4:
6595 case 0x5:
6596 goto do_ldst;
6597 case 0x6:
6598 case 0x7:
6599 if (insn & (1 << 4)) {
6600 ARCH(6);
6601 /* Armv6 Media instructions. */
6602 rm = insn & 0xf;
6603 rn = (insn >> 16) & 0xf;
6604 rd = (insn >> 12) & 0xf;
6605 rs = (insn >> 8) & 0xf;
6606 switch ((insn >> 23) & 3) {
6607 case 0: /* Parallel add/subtract. */
6608 op1 = (insn >> 20) & 7;
6609 tmp = load_reg(s, rn);
6610 tmp2 = load_reg(s, rm);
6611 sh = (insn >> 5) & 7;
6612 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6613 goto illegal_op;
6614 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6615 dead_tmp(tmp2);
6616 store_reg(s, rd, tmp);
6617 break;
6618 case 1:
6619 if ((insn & 0x00700020) == 0) {
6620 /* Halfword pack. */
6621 tmp = load_reg(s, rn);
6622 tmp2 = load_reg(s, rm);
6623 shift = (insn >> 7) & 0x1f;
6624 if (insn & (1 << 6)) {
6625 /* pkhtb */
6626 if (shift == 0)
6627 shift = 31;
6628 tcg_gen_sari_i32(tmp2, tmp2, shift);
6629 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6630 tcg_gen_ext16u_i32(tmp2, tmp2);
6631 } else {
6632 /* pkhbt */
6633 if (shift)
6634 tcg_gen_shli_i32(tmp2, tmp2, shift);
6635 tcg_gen_ext16u_i32(tmp, tmp);
6636 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6638 tcg_gen_or_i32(tmp, tmp, tmp2);
6639 dead_tmp(tmp2);
6640 store_reg(s, rd, tmp);
6641 } else if ((insn & 0x00200020) == 0x00200000) {
6642 /* [us]sat */
6643 tmp = load_reg(s, rm);
6644 shift = (insn >> 7) & 0x1f;
6645 if (insn & (1 << 6)) {
6646 if (shift == 0)
6647 shift = 31;
6648 tcg_gen_sari_i32(tmp, tmp, shift);
6649 } else {
6650 tcg_gen_shli_i32(tmp, tmp, shift);
6652 sh = (insn >> 16) & 0x1f;
6653 if (sh != 0) {
6654 if (insn & (1 << 22))
6655 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6656 else
6657 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6659 store_reg(s, rd, tmp);
6660 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6661 /* [us]sat16 */
6662 tmp = load_reg(s, rm);
6663 sh = (insn >> 16) & 0x1f;
6664 if (sh != 0) {
6665 if (insn & (1 << 22))
6666 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6667 else
6668 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6670 store_reg(s, rd, tmp);
6671 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6672 /* Select bytes. */
6673 tmp = load_reg(s, rn);
6674 tmp2 = load_reg(s, rm);
6675 tmp3 = new_tmp();
6676 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6677 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6678 dead_tmp(tmp3);
6679 dead_tmp(tmp2);
6680 store_reg(s, rd, tmp);
6681 } else if ((insn & 0x000003e0) == 0x00000060) {
6682 tmp = load_reg(s, rm);
6683 shift = (insn >> 10) & 3;
6684 /* ??? In many cases it's not neccessary to do a
6685 rotate, a shift is sufficient. */
6686 if (shift != 0)
6687 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6688 op1 = (insn >> 20) & 7;
6689 switch (op1) {
6690 case 0: gen_sxtb16(tmp); break;
6691 case 2: gen_sxtb(tmp); break;
6692 case 3: gen_sxth(tmp); break;
6693 case 4: gen_uxtb16(tmp); break;
6694 case 6: gen_uxtb(tmp); break;
6695 case 7: gen_uxth(tmp); break;
6696 default: goto illegal_op;
6698 if (rn != 15) {
6699 tmp2 = load_reg(s, rn);
6700 if ((op1 & 3) == 0) {
6701 gen_add16(tmp, tmp2);
6702 } else {
6703 tcg_gen_add_i32(tmp, tmp, tmp2);
6704 dead_tmp(tmp2);
6707 store_reg(s, rd, tmp);
6708 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6709 /* rev */
6710 tmp = load_reg(s, rm);
6711 if (insn & (1 << 22)) {
6712 if (insn & (1 << 7)) {
6713 gen_revsh(tmp);
6714 } else {
6715 ARCH(6T2);
6716 gen_helper_rbit(tmp, tmp);
6718 } else {
6719 if (insn & (1 << 7))
6720 gen_rev16(tmp);
6721 else
6722 tcg_gen_bswap32_i32(tmp, tmp);
6724 store_reg(s, rd, tmp);
6725 } else {
6726 goto illegal_op;
6728 break;
6729 case 2: /* Multiplies (Type 3). */
6730 tmp = load_reg(s, rm);
6731 tmp2 = load_reg(s, rs);
6732 if (insn & (1 << 20)) {
6733 /* Signed multiply most significant [accumulate]. */
6734 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6735 if (insn & (1 << 5))
6736 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6737 tcg_gen_shri_i64(tmp64, tmp64, 32);
6738 tmp = new_tmp();
6739 tcg_gen_trunc_i64_i32(tmp, tmp64);
6740 if (rd != 15) {
6741 tmp2 = load_reg(s, rd);
6742 if (insn & (1 << 6)) {
6743 tcg_gen_sub_i32(tmp, tmp, tmp2);
6744 } else {
6745 tcg_gen_add_i32(tmp, tmp, tmp2);
6747 dead_tmp(tmp2);
6749 store_reg(s, rn, tmp);
6750 } else {
6751 if (insn & (1 << 5))
6752 gen_swap_half(tmp2);
6753 gen_smul_dual(tmp, tmp2);
6754 /* This addition cannot overflow. */
6755 if (insn & (1 << 6)) {
6756 tcg_gen_sub_i32(tmp, tmp, tmp2);
6757 } else {
6758 tcg_gen_add_i32(tmp, tmp, tmp2);
6760 dead_tmp(tmp2);
6761 if (insn & (1 << 22)) {
6762 /* smlald, smlsld */
6763 tmp64 = tcg_temp_new_i64();
6764 tcg_gen_ext_i32_i64(tmp64, tmp);
6765 dead_tmp(tmp);
6766 gen_addq(s, tmp64, rd, rn);
6767 gen_storeq_reg(s, rd, rn, tmp64);
6768 } else {
6769 /* smuad, smusd, smlad, smlsd */
6770 if (rd != 15)
6772 tmp2 = load_reg(s, rd);
6773 gen_helper_add_setq(tmp, tmp, tmp2);
6774 dead_tmp(tmp2);
6776 store_reg(s, rn, tmp);
6779 break;
6780 case 3:
6781 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6782 switch (op1) {
6783 case 0: /* Unsigned sum of absolute differences. */
6784 ARCH(6);
6785 tmp = load_reg(s, rm);
6786 tmp2 = load_reg(s, rs);
6787 gen_helper_usad8(tmp, tmp, tmp2);
6788 dead_tmp(tmp2);
6789 if (rd != 15) {
6790 tmp2 = load_reg(s, rd);
6791 tcg_gen_add_i32(tmp, tmp, tmp2);
6792 dead_tmp(tmp2);
6794 store_reg(s, rn, tmp);
6795 break;
6796 case 0x20: case 0x24: case 0x28: case 0x2c:
6797 /* Bitfield insert/clear. */
6798 ARCH(6T2);
6799 shift = (insn >> 7) & 0x1f;
6800 i = (insn >> 16) & 0x1f;
6801 i = i + 1 - shift;
6802 if (rm == 15) {
6803 tmp = new_tmp();
6804 tcg_gen_movi_i32(tmp, 0);
6805 } else {
6806 tmp = load_reg(s, rm);
6808 if (i != 32) {
6809 tmp2 = load_reg(s, rd);
6810 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6811 dead_tmp(tmp2);
6813 store_reg(s, rd, tmp);
6814 break;
6815 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6816 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6817 ARCH(6T2);
6818 tmp = load_reg(s, rm);
6819 shift = (insn >> 7) & 0x1f;
6820 i = ((insn >> 16) & 0x1f) + 1;
6821 if (shift + i > 32)
6822 goto illegal_op;
6823 if (i < 32) {
6824 if (op1 & 0x20) {
6825 gen_ubfx(tmp, shift, (1u << i) - 1);
6826 } else {
6827 gen_sbfx(tmp, shift, i);
6830 store_reg(s, rd, tmp);
6831 break;
6832 default:
6833 goto illegal_op;
6835 break;
6837 break;
6839 do_ldst:
6840 /* Check for undefined extension instructions
6841 * per the ARM Bible IE:
6842 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6844 sh = (0xf << 20) | (0xf << 4);
6845 if (op1 == 0x7 && ((insn & sh) == sh))
6847 goto illegal_op;
6849 /* load/store byte/word */
6850 rn = (insn >> 16) & 0xf;
6851 rd = (insn >> 12) & 0xf;
6852 tmp2 = load_reg(s, rn);
6853 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6854 if (insn & (1 << 24))
6855 gen_add_data_offset(s, insn, tmp2);
6856 if (insn & (1 << 20)) {
6857 /* load */
6858 if (insn & (1 << 22)) {
6859 tmp = gen_ld8u(tmp2, i);
6860 } else {
6861 tmp = gen_ld32(tmp2, i);
6863 } else {
6864 /* store */
6865 tmp = load_reg(s, rd);
6866 if (insn & (1 << 22))
6867 gen_st8(tmp, tmp2, i);
6868 else
6869 gen_st32(tmp, tmp2, i);
6871 if (!(insn & (1 << 24))) {
6872 gen_add_data_offset(s, insn, tmp2);
6873 store_reg(s, rn, tmp2);
6874 } else if (insn & (1 << 21)) {
6875 store_reg(s, rn, tmp2);
6876 } else {
6877 dead_tmp(tmp2);
6879 if (insn & (1 << 20)) {
6880 /* Complete the load. */
6881 if (rd == 15)
6882 gen_bx(s, tmp);
6883 else
6884 store_reg(s, rd, tmp);
6886 break;
6887 case 0x08:
6888 case 0x09:
6890 int j, n, user, loaded_base;
6891 TCGv loaded_var;
6892 /* load/store multiple words */
6893 /* XXX: store correct base if write back */
6894 user = 0;
6895 if (insn & (1 << 22)) {
6896 if (IS_USER(s))
6897 goto illegal_op; /* only usable in supervisor mode */
6899 if ((insn & (1 << 15)) == 0)
6900 user = 1;
6902 rn = (insn >> 16) & 0xf;
6903 addr = load_reg(s, rn);
6905 /* compute total size */
6906 loaded_base = 0;
6907 TCGV_UNUSED(loaded_var);
6908 n = 0;
6909 for(i=0;i<16;i++) {
6910 if (insn & (1 << i))
6911 n++;
6913 /* XXX: test invalid n == 0 case ? */
6914 if (insn & (1 << 23)) {
6915 if (insn & (1 << 24)) {
6916 /* pre increment */
6917 tcg_gen_addi_i32(addr, addr, 4);
6918 } else {
6919 /* post increment */
6921 } else {
6922 if (insn & (1 << 24)) {
6923 /* pre decrement */
6924 tcg_gen_addi_i32(addr, addr, -(n * 4));
6925 } else {
6926 /* post decrement */
6927 if (n != 1)
6928 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6931 j = 0;
6932 for(i=0;i<16;i++) {
6933 if (insn & (1 << i)) {
6934 if (insn & (1 << 20)) {
6935 /* load */
6936 tmp = gen_ld32(addr, IS_USER(s));
6937 if (i == 15) {
6938 gen_bx(s, tmp);
6939 } else if (user) {
6940 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6941 dead_tmp(tmp);
6942 } else if (i == rn) {
6943 loaded_var = tmp;
6944 loaded_base = 1;
6945 } else {
6946 store_reg(s, i, tmp);
6948 } else {
6949 /* store */
6950 if (i == 15) {
6951 /* special case: r15 = PC + 8 */
6952 val = (long)s->pc + 4;
6953 tmp = new_tmp();
6954 tcg_gen_movi_i32(tmp, val);
6955 } else if (user) {
6956 tmp = new_tmp();
6957 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6958 } else {
6959 tmp = load_reg(s, i);
6961 gen_st32(tmp, addr, IS_USER(s));
6963 j++;
6964 /* no need to add after the last transfer */
6965 if (j != n)
6966 tcg_gen_addi_i32(addr, addr, 4);
6969 if (insn & (1 << 21)) {
6970 /* write back */
6971 if (insn & (1 << 23)) {
6972 if (insn & (1 << 24)) {
6973 /* pre increment */
6974 } else {
6975 /* post increment */
6976 tcg_gen_addi_i32(addr, addr, 4);
6978 } else {
6979 if (insn & (1 << 24)) {
6980 /* pre decrement */
6981 if (n != 1)
6982 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6983 } else {
6984 /* post decrement */
6985 tcg_gen_addi_i32(addr, addr, -(n * 4));
6988 store_reg(s, rn, addr);
6989 } else {
6990 dead_tmp(addr);
6992 if (loaded_base) {
6993 store_reg(s, rn, loaded_var);
6995 if ((insn & (1 << 22)) && !user) {
6996 /* Restore CPSR from SPSR. */
6997 tmp = load_cpu_field(spsr);
6998 gen_set_cpsr(tmp, 0xffffffff);
6999 dead_tmp(tmp);
7000 s->is_jmp = DISAS_UPDATE;
7003 break;
7004 case 0xa:
7005 case 0xb:
7007 int32_t offset;
7009 /* branch (and link) */
7010 val = (int32_t)s->pc;
7011 if (insn & (1 << 24)) {
7012 tmp = new_tmp();
7013 tcg_gen_movi_i32(tmp, val);
7014 store_reg(s, 14, tmp);
7016 offset = (((int32_t)insn << 8) >> 8);
7017 val += (offset << 2) + 4;
7018 gen_jmp(s, val);
7020 break;
7021 case 0xc:
7022 case 0xd:
7023 case 0xe:
7024 /* Coprocessor. */
7025 if (disas_coproc_insn(env, s, insn))
7026 goto illegal_op;
7027 break;
7028 case 0xf:
7029 /* swi */
7030 gen_set_pc_im(s->pc);
7031 s->is_jmp = DISAS_SWI;
7032 break;
7033 default:
7034 illegal_op:
7035 gen_set_condexec(s);
7036 gen_set_pc_im(s->pc - 4);
7037 gen_exception(EXCP_UDEF);
7038 s->is_jmp = DISAS_JUMP;
7039 break;
7044 /* Return true if this is a Thumb-2 logical op. */
7045 static int
7046 thumb2_logic_op(int op)
7048 return (op < 8);
7051 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7052 then set condition code flags based on the result of the operation.
7053 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7054 to the high bit of T1.
7055 Returns zero if the opcode is valid. */
7057 static int
7058 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7060 int logic_cc;
7062 logic_cc = 0;
7063 switch (op) {
7064 case 0: /* and */
7065 tcg_gen_and_i32(t0, t0, t1);
7066 logic_cc = conds;
7067 break;
7068 case 1: /* bic */
7069 tcg_gen_bic_i32(t0, t0, t1);
7070 logic_cc = conds;
7071 break;
7072 case 2: /* orr */
7073 tcg_gen_or_i32(t0, t0, t1);
7074 logic_cc = conds;
7075 break;
7076 case 3: /* orn */
7077 tcg_gen_not_i32(t1, t1);
7078 tcg_gen_or_i32(t0, t0, t1);
7079 logic_cc = conds;
7080 break;
7081 case 4: /* eor */
7082 tcg_gen_xor_i32(t0, t0, t1);
7083 logic_cc = conds;
7084 break;
7085 case 8: /* add */
7086 if (conds)
7087 gen_helper_add_cc(t0, t0, t1);
7088 else
7089 tcg_gen_add_i32(t0, t0, t1);
7090 break;
7091 case 10: /* adc */
7092 if (conds)
7093 gen_helper_adc_cc(t0, t0, t1);
7094 else
7095 gen_adc(t0, t1);
7096 break;
7097 case 11: /* sbc */
7098 if (conds)
7099 gen_helper_sbc_cc(t0, t0, t1);
7100 else
7101 gen_sub_carry(t0, t0, t1);
7102 break;
7103 case 13: /* sub */
7104 if (conds)
7105 gen_helper_sub_cc(t0, t0, t1);
7106 else
7107 tcg_gen_sub_i32(t0, t0, t1);
7108 break;
7109 case 14: /* rsb */
7110 if (conds)
7111 gen_helper_sub_cc(t0, t1, t0);
7112 else
7113 tcg_gen_sub_i32(t0, t1, t0);
7114 break;
7115 default: /* 5, 6, 7, 9, 12, 15. */
7116 return 1;
7118 if (logic_cc) {
7119 gen_logic_CC(t0);
7120 if (shifter_out)
7121 gen_set_CF_bit31(t1);
7123 return 0;
7126 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7127 is not legal. */
7128 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7130 uint32_t insn, imm, shift, offset;
7131 uint32_t rd, rn, rm, rs;
7132 TCGv tmp;
7133 TCGv tmp2;
7134 TCGv tmp3;
7135 TCGv addr;
7136 TCGv_i64 tmp64;
7137 int op;
7138 int shiftop;
7139 int conds;
7140 int logic_cc;
7142 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7143 || arm_feature (env, ARM_FEATURE_M))) {
7144 /* Thumb-1 cores may need to treat bl and blx as a pair of
7145 16-bit instructions to get correct prefetch abort behavior. */
7146 insn = insn_hw1;
7147 if ((insn & (1 << 12)) == 0) {
7148 /* Second half of blx. */
7149 offset = ((insn & 0x7ff) << 1);
7150 tmp = load_reg(s, 14);
7151 tcg_gen_addi_i32(tmp, tmp, offset);
7152 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7154 tmp2 = new_tmp();
7155 tcg_gen_movi_i32(tmp2, s->pc | 1);
7156 store_reg(s, 14, tmp2);
7157 gen_bx(s, tmp);
7158 return 0;
7160 if (insn & (1 << 11)) {
7161 /* Second half of bl. */
7162 offset = ((insn & 0x7ff) << 1) | 1;
7163 tmp = load_reg(s, 14);
7164 tcg_gen_addi_i32(tmp, tmp, offset);
7166 tmp2 = new_tmp();
7167 tcg_gen_movi_i32(tmp2, s->pc | 1);
7168 store_reg(s, 14, tmp2);
7169 gen_bx(s, tmp);
7170 return 0;
7172 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7173 /* Instruction spans a page boundary. Implement it as two
7174 16-bit instructions in case the second half causes an
7175 prefetch abort. */
7176 offset = ((int32_t)insn << 21) >> 9;
7177 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7178 return 0;
7180 /* Fall through to 32-bit decode. */
7183 insn = lduw_code(s->pc);
7184 s->pc += 2;
7185 insn |= (uint32_t)insn_hw1 << 16;
7187 if ((insn & 0xf800e800) != 0xf000e800) {
7188 ARCH(6T2);
7191 rn = (insn >> 16) & 0xf;
7192 rs = (insn >> 12) & 0xf;
7193 rd = (insn >> 8) & 0xf;
7194 rm = insn & 0xf;
7195 switch ((insn >> 25) & 0xf) {
7196 case 0: case 1: case 2: case 3:
7197 /* 16-bit instructions. Should never happen. */
7198 abort();
7199 case 4:
7200 if (insn & (1 << 22)) {
7201 /* Other load/store, table branch. */
7202 if (insn & 0x01200000) {
7203 /* Load/store doubleword. */
7204 if (rn == 15) {
7205 addr = new_tmp();
7206 tcg_gen_movi_i32(addr, s->pc & ~3);
7207 } else {
7208 addr = load_reg(s, rn);
7210 offset = (insn & 0xff) * 4;
7211 if ((insn & (1 << 23)) == 0)
7212 offset = -offset;
7213 if (insn & (1 << 24)) {
7214 tcg_gen_addi_i32(addr, addr, offset);
7215 offset = 0;
7217 if (insn & (1 << 20)) {
7218 /* ldrd */
7219 tmp = gen_ld32(addr, IS_USER(s));
7220 store_reg(s, rs, tmp);
7221 tcg_gen_addi_i32(addr, addr, 4);
7222 tmp = gen_ld32(addr, IS_USER(s));
7223 store_reg(s, rd, tmp);
7224 } else {
7225 /* strd */
7226 tmp = load_reg(s, rs);
7227 gen_st32(tmp, addr, IS_USER(s));
7228 tcg_gen_addi_i32(addr, addr, 4);
7229 tmp = load_reg(s, rd);
7230 gen_st32(tmp, addr, IS_USER(s));
7232 if (insn & (1 << 21)) {
7233 /* Base writeback. */
7234 if (rn == 15)
7235 goto illegal_op;
7236 tcg_gen_addi_i32(addr, addr, offset - 4);
7237 store_reg(s, rn, addr);
7238 } else {
7239 dead_tmp(addr);
7241 } else if ((insn & (1 << 23)) == 0) {
7242 /* Load/store exclusive word. */
7243 addr = tcg_temp_local_new();
7244 tcg_gen_mov_i32(addr, cpu_R[rn]);
7245 if (insn & (1 << 20)) {
7246 gen_helper_mark_exclusive(cpu_env, addr);
7247 tmp = gen_ld32(addr, IS_USER(s));
7248 store_reg(s, rd, tmp);
7249 } else {
7250 int label = gen_new_label();
7251 tmp2 = tcg_temp_local_new();
7252 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7253 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7254 tmp = load_reg(s, rs);
7255 gen_st32(tmp, addr, IS_USER(s));
7256 gen_set_label(label);
7257 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7258 tcg_temp_free(tmp2);
7260 tcg_temp_free(addr);
7261 } else if ((insn & (1 << 6)) == 0) {
7262 /* Table Branch. */
7263 if (rn == 15) {
7264 addr = new_tmp();
7265 tcg_gen_movi_i32(addr, s->pc);
7266 } else {
7267 addr = load_reg(s, rn);
7269 tmp = load_reg(s, rm);
7270 tcg_gen_add_i32(addr, addr, tmp);
7271 if (insn & (1 << 4)) {
7272 /* tbh */
7273 tcg_gen_add_i32(addr, addr, tmp);
7274 dead_tmp(tmp);
7275 tmp = gen_ld16u(addr, IS_USER(s));
7276 } else { /* tbb */
7277 dead_tmp(tmp);
7278 tmp = gen_ld8u(addr, IS_USER(s));
7280 dead_tmp(addr);
7281 tcg_gen_shli_i32(tmp, tmp, 1);
7282 tcg_gen_addi_i32(tmp, tmp, s->pc);
7283 store_reg(s, 15, tmp);
7284 } else {
7285 /* Load/store exclusive byte/halfword/doubleword. */
7286 /* ??? These are not really atomic. However we know
7287 we never have multiple CPUs running in parallel,
7288 so it is good enough. */
7289 op = (insn >> 4) & 0x3;
7290 addr = tcg_temp_local_new();
7291 tcg_gen_mov_i32(addr, cpu_R[rn]);
7292 if (insn & (1 << 20)) {
7293 gen_helper_mark_exclusive(cpu_env, addr);
7294 switch (op) {
7295 case 0:
7296 tmp = gen_ld8u(addr, IS_USER(s));
7297 break;
7298 case 1:
7299 tmp = gen_ld16u(addr, IS_USER(s));
7300 break;
7301 case 3:
7302 tmp = gen_ld32(addr, IS_USER(s));
7303 tcg_gen_addi_i32(addr, addr, 4);
7304 tmp2 = gen_ld32(addr, IS_USER(s));
7305 store_reg(s, rd, tmp2);
7306 break;
7307 default:
7308 goto illegal_op;
7310 store_reg(s, rs, tmp);
7311 } else {
7312 int label = gen_new_label();
7313 tmp2 = tcg_temp_local_new();
7314 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7315 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7316 tmp = load_reg(s, rs);
7317 switch (op) {
7318 case 0:
7319 gen_st8(tmp, addr, IS_USER(s));
7320 break;
7321 case 1:
7322 gen_st16(tmp, addr, IS_USER(s));
7323 break;
7324 case 3:
7325 gen_st32(tmp, addr, IS_USER(s));
7326 tcg_gen_addi_i32(addr, addr, 4);
7327 tmp = load_reg(s, rd);
7328 gen_st32(tmp, addr, IS_USER(s));
7329 break;
7330 default:
7331 goto illegal_op;
7333 gen_set_label(label);
7334 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7335 tcg_temp_free(tmp2);
7337 tcg_temp_free(addr);
7339 } else {
7340 /* Load/store multiple, RFE, SRS. */
7341 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7342 /* Not available in user mode. */
7343 if (IS_USER(s))
7344 goto illegal_op;
7345 if (insn & (1 << 20)) {
7346 /* rfe */
7347 addr = load_reg(s, rn);
7348 if ((insn & (1 << 24)) == 0)
7349 tcg_gen_addi_i32(addr, addr, -8);
7350 /* Load PC into tmp and CPSR into tmp2. */
7351 tmp = gen_ld32(addr, 0);
7352 tcg_gen_addi_i32(addr, addr, 4);
7353 tmp2 = gen_ld32(addr, 0);
7354 if (insn & (1 << 21)) {
7355 /* Base writeback. */
7356 if (insn & (1 << 24)) {
7357 tcg_gen_addi_i32(addr, addr, 4);
7358 } else {
7359 tcg_gen_addi_i32(addr, addr, -4);
7361 store_reg(s, rn, addr);
7362 } else {
7363 dead_tmp(addr);
7365 gen_rfe(s, tmp, tmp2);
7366 } else {
7367 /* srs */
7368 op = (insn & 0x1f);
7369 if (op == (env->uncached_cpsr & CPSR_M)) {
7370 addr = load_reg(s, 13);
7371 } else {
7372 addr = new_tmp();
7373 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7375 if ((insn & (1 << 24)) == 0) {
7376 tcg_gen_addi_i32(addr, addr, -8);
7378 tmp = load_reg(s, 14);
7379 gen_st32(tmp, addr, 0);
7380 tcg_gen_addi_i32(addr, addr, 4);
7381 tmp = new_tmp();
7382 gen_helper_cpsr_read(tmp);
7383 gen_st32(tmp, addr, 0);
7384 if (insn & (1 << 21)) {
7385 if ((insn & (1 << 24)) == 0) {
7386 tcg_gen_addi_i32(addr, addr, -4);
7387 } else {
7388 tcg_gen_addi_i32(addr, addr, 4);
7390 if (op == (env->uncached_cpsr & CPSR_M)) {
7391 store_reg(s, 13, addr);
7392 } else {
7393 gen_helper_set_r13_banked(cpu_env,
7394 tcg_const_i32(op), addr);
7396 } else {
7397 dead_tmp(addr);
7400 } else {
7401 int i;
7402 /* Load/store multiple. */
7403 addr = load_reg(s, rn);
7404 offset = 0;
7405 for (i = 0; i < 16; i++) {
7406 if (insn & (1 << i))
7407 offset += 4;
7409 if (insn & (1 << 24)) {
7410 tcg_gen_addi_i32(addr, addr, -offset);
7413 for (i = 0; i < 16; i++) {
7414 if ((insn & (1 << i)) == 0)
7415 continue;
7416 if (insn & (1 << 20)) {
7417 /* Load. */
7418 tmp = gen_ld32(addr, IS_USER(s));
7419 if (i == 15) {
7420 gen_bx(s, tmp);
7421 } else {
7422 store_reg(s, i, tmp);
7424 } else {
7425 /* Store. */
7426 tmp = load_reg(s, i);
7427 gen_st32(tmp, addr, IS_USER(s));
7429 tcg_gen_addi_i32(addr, addr, 4);
7431 if (insn & (1 << 21)) {
7432 /* Base register writeback. */
7433 if (insn & (1 << 24)) {
7434 tcg_gen_addi_i32(addr, addr, -offset);
7436 /* Fault if writeback register is in register list. */
7437 if (insn & (1 << rn))
7438 goto illegal_op;
7439 store_reg(s, rn, addr);
7440 } else {
7441 dead_tmp(addr);
7445 break;
7446 case 5: /* Data processing register constant shift. */
7447 if (rn == 15) {
7448 tmp = new_tmp();
7449 tcg_gen_movi_i32(tmp, 0);
7450 } else {
7451 tmp = load_reg(s, rn);
7453 tmp2 = load_reg(s, rm);
7454 op = (insn >> 21) & 0xf;
7455 shiftop = (insn >> 4) & 3;
7456 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7457 conds = (insn & (1 << 20)) != 0;
7458 logic_cc = (conds && thumb2_logic_op(op));
7459 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7460 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7461 goto illegal_op;
7462 dead_tmp(tmp2);
7463 if (rd != 15) {
7464 store_reg(s, rd, tmp);
7465 } else {
7466 dead_tmp(tmp);
7468 break;
7469 case 13: /* Misc data processing. */
7470 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7471 if (op < 4 && (insn & 0xf000) != 0xf000)
7472 goto illegal_op;
7473 switch (op) {
7474 case 0: /* Register controlled shift. */
7475 tmp = load_reg(s, rn);
7476 tmp2 = load_reg(s, rm);
7477 if ((insn & 0x70) != 0)
7478 goto illegal_op;
7479 op = (insn >> 21) & 3;
7480 logic_cc = (insn & (1 << 20)) != 0;
7481 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7482 if (logic_cc)
7483 gen_logic_CC(tmp);
7484 store_reg_bx(env, s, rd, tmp);
7485 break;
7486 case 1: /* Sign/zero extend. */
7487 tmp = load_reg(s, rm);
7488 shift = (insn >> 4) & 3;
7489 /* ??? In many cases it's not neccessary to do a
7490 rotate, a shift is sufficient. */
7491 if (shift != 0)
7492 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7493 op = (insn >> 20) & 7;
7494 switch (op) {
7495 case 0: gen_sxth(tmp); break;
7496 case 1: gen_uxth(tmp); break;
7497 case 2: gen_sxtb16(tmp); break;
7498 case 3: gen_uxtb16(tmp); break;
7499 case 4: gen_sxtb(tmp); break;
7500 case 5: gen_uxtb(tmp); break;
7501 default: goto illegal_op;
7503 if (rn != 15) {
7504 tmp2 = load_reg(s, rn);
7505 if ((op >> 1) == 1) {
7506 gen_add16(tmp, tmp2);
7507 } else {
7508 tcg_gen_add_i32(tmp, tmp, tmp2);
7509 dead_tmp(tmp2);
7512 store_reg(s, rd, tmp);
7513 break;
7514 case 2: /* SIMD add/subtract. */
7515 op = (insn >> 20) & 7;
7516 shift = (insn >> 4) & 7;
7517 if ((op & 3) == 3 || (shift & 3) == 3)
7518 goto illegal_op;
7519 tmp = load_reg(s, rn);
7520 tmp2 = load_reg(s, rm);
7521 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7522 dead_tmp(tmp2);
7523 store_reg(s, rd, tmp);
7524 break;
7525 case 3: /* Other data processing. */
7526 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7527 if (op < 4) {
7528 /* Saturating add/subtract. */
7529 tmp = load_reg(s, rn);
7530 tmp2 = load_reg(s, rm);
7531 if (op & 2)
7532 gen_helper_double_saturate(tmp, tmp);
7533 if (op & 1)
7534 gen_helper_sub_saturate(tmp, tmp2, tmp);
7535 else
7536 gen_helper_add_saturate(tmp, tmp, tmp2);
7537 dead_tmp(tmp2);
7538 } else {
7539 tmp = load_reg(s, rn);
7540 switch (op) {
7541 case 0x0a: /* rbit */
7542 gen_helper_rbit(tmp, tmp);
7543 break;
7544 case 0x08: /* rev */
7545 tcg_gen_bswap32_i32(tmp, tmp);
7546 break;
7547 case 0x09: /* rev16 */
7548 gen_rev16(tmp);
7549 break;
7550 case 0x0b: /* revsh */
7551 gen_revsh(tmp);
7552 break;
7553 case 0x10: /* sel */
7554 tmp2 = load_reg(s, rm);
7555 tmp3 = new_tmp();
7556 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7557 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7558 dead_tmp(tmp3);
7559 dead_tmp(tmp2);
7560 break;
7561 case 0x18: /* clz */
7562 gen_helper_clz(tmp, tmp);
7563 break;
7564 default:
7565 goto illegal_op;
7568 store_reg(s, rd, tmp);
7569 break;
7570 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7571 op = (insn >> 4) & 0xf;
7572 tmp = load_reg(s, rn);
7573 tmp2 = load_reg(s, rm);
7574 switch ((insn >> 20) & 7) {
7575 case 0: /* 32 x 32 -> 32 */
7576 tcg_gen_mul_i32(tmp, tmp, tmp2);
7577 dead_tmp(tmp2);
7578 if (rs != 15) {
7579 tmp2 = load_reg(s, rs);
7580 if (op)
7581 tcg_gen_sub_i32(tmp, tmp2, tmp);
7582 else
7583 tcg_gen_add_i32(tmp, tmp, tmp2);
7584 dead_tmp(tmp2);
7586 break;
7587 case 1: /* 16 x 16 -> 32 */
7588 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7589 dead_tmp(tmp2);
7590 if (rs != 15) {
7591 tmp2 = load_reg(s, rs);
7592 gen_helper_add_setq(tmp, tmp, tmp2);
7593 dead_tmp(tmp2);
7595 break;
7596 case 2: /* Dual multiply add. */
7597 case 4: /* Dual multiply subtract. */
7598 if (op)
7599 gen_swap_half(tmp2);
7600 gen_smul_dual(tmp, tmp2);
7601 /* This addition cannot overflow. */
7602 if (insn & (1 << 22)) {
7603 tcg_gen_sub_i32(tmp, tmp, tmp2);
7604 } else {
7605 tcg_gen_add_i32(tmp, tmp, tmp2);
7607 dead_tmp(tmp2);
7608 if (rs != 15)
7610 tmp2 = load_reg(s, rs);
7611 gen_helper_add_setq(tmp, tmp, tmp2);
7612 dead_tmp(tmp2);
7614 break;
7615 case 3: /* 32 * 16 -> 32msb */
7616 if (op)
7617 tcg_gen_sari_i32(tmp2, tmp2, 16);
7618 else
7619 gen_sxth(tmp2);
7620 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7621 tcg_gen_shri_i64(tmp64, tmp64, 16);
7622 tmp = new_tmp();
7623 tcg_gen_trunc_i64_i32(tmp, tmp64);
7624 if (rs != 15)
7626 tmp2 = load_reg(s, rs);
7627 gen_helper_add_setq(tmp, tmp, tmp2);
7628 dead_tmp(tmp2);
7630 break;
7631 case 5: case 6: /* 32 * 32 -> 32msb */
7632 gen_imull(tmp, tmp2);
7633 if (insn & (1 << 5)) {
7634 gen_roundqd(tmp, tmp2);
7635 dead_tmp(tmp2);
7636 } else {
7637 dead_tmp(tmp);
7638 tmp = tmp2;
7640 if (rs != 15) {
7641 tmp2 = load_reg(s, rs);
7642 if (insn & (1 << 21)) {
7643 tcg_gen_add_i32(tmp, tmp, tmp2);
7644 } else {
7645 tcg_gen_sub_i32(tmp, tmp2, tmp);
7647 dead_tmp(tmp2);
7649 break;
7650 case 7: /* Unsigned sum of absolute differences. */
7651 gen_helper_usad8(tmp, tmp, tmp2);
7652 dead_tmp(tmp2);
7653 if (rs != 15) {
7654 tmp2 = load_reg(s, rs);
7655 tcg_gen_add_i32(tmp, tmp, tmp2);
7656 dead_tmp(tmp2);
7658 break;
7660 store_reg(s, rd, tmp);
7661 break;
7662 case 6: case 7: /* 64-bit multiply, Divide. */
7663 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7664 tmp = load_reg(s, rn);
7665 tmp2 = load_reg(s, rm);
7666 if ((op & 0x50) == 0x10) {
7667 /* sdiv, udiv */
7668 if (!arm_feature(env, ARM_FEATURE_DIV))
7669 goto illegal_op;
7670 if (op & 0x20)
7671 gen_helper_udiv(tmp, tmp, tmp2);
7672 else
7673 gen_helper_sdiv(tmp, tmp, tmp2);
7674 dead_tmp(tmp2);
7675 store_reg(s, rd, tmp);
7676 } else if ((op & 0xe) == 0xc) {
7677 /* Dual multiply accumulate long. */
7678 if (op & 1)
7679 gen_swap_half(tmp2);
7680 gen_smul_dual(tmp, tmp2);
7681 if (op & 0x10) {
7682 tcg_gen_sub_i32(tmp, tmp, tmp2);
7683 } else {
7684 tcg_gen_add_i32(tmp, tmp, tmp2);
7686 dead_tmp(tmp2);
7687 /* BUGFIX */
7688 tmp64 = tcg_temp_new_i64();
7689 tcg_gen_ext_i32_i64(tmp64, tmp);
7690 dead_tmp(tmp);
7691 gen_addq(s, tmp64, rs, rd);
7692 gen_storeq_reg(s, rs, rd, tmp64);
7693 } else {
7694 if (op & 0x20) {
7695 /* Unsigned 64-bit multiply */
7696 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7697 } else {
7698 if (op & 8) {
7699 /* smlalxy */
7700 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7701 dead_tmp(tmp2);
7702 tmp64 = tcg_temp_new_i64();
7703 tcg_gen_ext_i32_i64(tmp64, tmp);
7704 dead_tmp(tmp);
7705 } else {
7706 /* Signed 64-bit multiply */
7707 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7710 if (op & 4) {
7711 /* umaal */
7712 gen_addq_lo(s, tmp64, rs);
7713 gen_addq_lo(s, tmp64, rd);
7714 } else if (op & 0x40) {
7715 /* 64-bit accumulate. */
7716 gen_addq(s, tmp64, rs, rd);
7718 gen_storeq_reg(s, rs, rd, tmp64);
7720 break;
7722 break;
7723 case 6: case 7: case 14: case 15:
7724 /* Coprocessor. */
7725 if (((insn >> 24) & 3) == 3) {
7726 /* Translate into the equivalent ARM encoding. */
7727 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7728 if (disas_neon_data_insn(env, s, insn))
7729 goto illegal_op;
7730 } else {
7731 if (insn & (1 << 28))
7732 goto illegal_op;
7733 if (disas_coproc_insn (env, s, insn))
7734 goto illegal_op;
7736 break;
7737 case 8: case 9: case 10: case 11:
7738 if (insn & (1 << 15)) {
7739 /* Branches, misc control. */
7740 if (insn & 0x5000) {
7741 /* Unconditional branch. */
7742 /* signextend(hw1[10:0]) -> offset[:12]. */
7743 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7744 /* hw1[10:0] -> offset[11:1]. */
7745 offset |= (insn & 0x7ff) << 1;
7746 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7747 offset[24:22] already have the same value because of the
7748 sign extension above. */
7749 offset ^= ((~insn) & (1 << 13)) << 10;
7750 offset ^= ((~insn) & (1 << 11)) << 11;
7752 if (insn & (1 << 14)) {
7753 /* Branch and link. */
7754 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7757 offset += s->pc;
7758 if (insn & (1 << 12)) {
7759 /* b/bl */
7760 gen_jmp(s, offset);
7761 } else {
7762 /* blx */
7763 offset &= ~(uint32_t)2;
7764 gen_bx_im(s, offset);
7766 } else if (((insn >> 23) & 7) == 7) {
7767 /* Misc control */
7768 if (insn & (1 << 13))
7769 goto illegal_op;
7771 if (insn & (1 << 26)) {
7772 /* Secure monitor call (v6Z) */
7773 goto illegal_op; /* not implemented. */
7774 } else {
7775 op = (insn >> 20) & 7;
7776 switch (op) {
7777 case 0: /* msr cpsr. */
7778 if (IS_M(env)) {
7779 tmp = load_reg(s, rn);
7780 addr = tcg_const_i32(insn & 0xff);
7781 gen_helper_v7m_msr(cpu_env, addr, tmp);
7782 gen_lookup_tb(s);
7783 break;
7785 /* fall through */
7786 case 1: /* msr spsr. */
7787 if (IS_M(env))
7788 goto illegal_op;
7789 tmp = load_reg(s, rn);
7790 if (gen_set_psr(s,
7791 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7792 op == 1, tmp))
7793 goto illegal_op;
7794 break;
7795 case 2: /* cps, nop-hint. */
7796 if (((insn >> 8) & 7) == 0) {
7797 gen_nop_hint(s, insn & 0xff);
7799 /* Implemented as NOP in user mode. */
7800 if (IS_USER(s))
7801 break;
7802 offset = 0;
7803 imm = 0;
7804 if (insn & (1 << 10)) {
7805 if (insn & (1 << 7))
7806 offset |= CPSR_A;
7807 if (insn & (1 << 6))
7808 offset |= CPSR_I;
7809 if (insn & (1 << 5))
7810 offset |= CPSR_F;
7811 if (insn & (1 << 9))
7812 imm = CPSR_A | CPSR_I | CPSR_F;
7814 if (insn & (1 << 8)) {
7815 offset |= 0x1f;
7816 imm |= (insn & 0x1f);
7818 if (offset) {
7819 gen_set_psr_im(s, offset, 0, imm);
7821 break;
7822 case 3: /* Special control operations. */
7823 op = (insn >> 4) & 0xf;
7824 switch (op) {
7825 case 2: /* clrex */
7826 gen_helper_clrex(cpu_env);
7827 break;
7828 case 4: /* dsb */
7829 case 5: /* dmb */
7830 case 6: /* isb */
7831 /* These execute as NOPs. */
7832 ARCH(7);
7833 break;
7834 default:
7835 goto illegal_op;
7837 break;
7838 case 4: /* bxj */
7839 /* Trivial implementation equivalent to bx. */
7840 tmp = load_reg(s, rn);
7841 gen_bx(s, tmp);
7842 break;
7843 case 5: /* Exception return. */
7844 /* Unpredictable in user mode. */
7845 goto illegal_op;
7846 case 6: /* mrs cpsr. */
7847 tmp = new_tmp();
7848 if (IS_M(env)) {
7849 addr = tcg_const_i32(insn & 0xff);
7850 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7851 } else {
7852 gen_helper_cpsr_read(tmp);
7854 store_reg(s, rd, tmp);
7855 break;
7856 case 7: /* mrs spsr. */
7857 /* Not accessible in user mode. */
7858 if (IS_USER(s) || IS_M(env))
7859 goto illegal_op;
7860 tmp = load_cpu_field(spsr);
7861 store_reg(s, rd, tmp);
7862 break;
7865 } else {
7866 /* Conditional branch. */
7867 op = (insn >> 22) & 0xf;
7868 /* Generate a conditional jump to next instruction. */
7869 s->condlabel = gen_new_label();
7870 gen_test_cc(op ^ 1, s->condlabel);
7871 s->condjmp = 1;
7873 /* offset[11:1] = insn[10:0] */
7874 offset = (insn & 0x7ff) << 1;
7875 /* offset[17:12] = insn[21:16]. */
7876 offset |= (insn & 0x003f0000) >> 4;
7877 /* offset[31:20] = insn[26]. */
7878 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7879 /* offset[18] = insn[13]. */
7880 offset |= (insn & (1 << 13)) << 5;
7881 /* offset[19] = insn[11]. */
7882 offset |= (insn & (1 << 11)) << 8;
7884 /* jump to the offset */
7885 gen_jmp(s, s->pc + offset);
7887 } else {
7888 /* Data processing immediate. */
7889 if (insn & (1 << 25)) {
7890 if (insn & (1 << 24)) {
7891 if (insn & (1 << 20))
7892 goto illegal_op;
7893 /* Bitfield/Saturate. */
7894 op = (insn >> 21) & 7;
7895 imm = insn & 0x1f;
7896 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7897 if (rn == 15) {
7898 tmp = new_tmp();
7899 tcg_gen_movi_i32(tmp, 0);
7900 } else {
7901 tmp = load_reg(s, rn);
7903 switch (op) {
7904 case 2: /* Signed bitfield extract. */
7905 imm++;
7906 if (shift + imm > 32)
7907 goto illegal_op;
7908 if (imm < 32)
7909 gen_sbfx(tmp, shift, imm);
7910 break;
7911 case 6: /* Unsigned bitfield extract. */
7912 imm++;
7913 if (shift + imm > 32)
7914 goto illegal_op;
7915 if (imm < 32)
7916 gen_ubfx(tmp, shift, (1u << imm) - 1);
7917 break;
7918 case 3: /* Bitfield insert/clear. */
7919 if (imm < shift)
7920 goto illegal_op;
7921 imm = imm + 1 - shift;
7922 if (imm != 32) {
7923 tmp2 = load_reg(s, rd);
7924 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7925 dead_tmp(tmp2);
7927 break;
7928 case 7:
7929 goto illegal_op;
7930 default: /* Saturate. */
7931 if (shift) {
7932 if (op & 1)
7933 tcg_gen_sari_i32(tmp, tmp, shift);
7934 else
7935 tcg_gen_shli_i32(tmp, tmp, shift);
7937 tmp2 = tcg_const_i32(imm);
7938 if (op & 4) {
7939 /* Unsigned. */
7940 if ((op & 1) && shift == 0)
7941 gen_helper_usat16(tmp, tmp, tmp2);
7942 else
7943 gen_helper_usat(tmp, tmp, tmp2);
7944 } else {
7945 /* Signed. */
7946 if ((op & 1) && shift == 0)
7947 gen_helper_ssat16(tmp, tmp, tmp2);
7948 else
7949 gen_helper_ssat(tmp, tmp, tmp2);
7951 break;
7953 store_reg(s, rd, tmp);
7954 } else {
7955 imm = ((insn & 0x04000000) >> 15)
7956 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7957 if (insn & (1 << 22)) {
7958 /* 16-bit immediate. */
7959 imm |= (insn >> 4) & 0xf000;
7960 if (insn & (1 << 23)) {
7961 /* movt */
7962 tmp = load_reg(s, rd);
7963 tcg_gen_ext16u_i32(tmp, tmp);
7964 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7965 } else {
7966 /* movw */
7967 tmp = new_tmp();
7968 tcg_gen_movi_i32(tmp, imm);
7970 } else {
7971 /* Add/sub 12-bit immediate. */
7972 if (rn == 15) {
7973 offset = s->pc & ~(uint32_t)3;
7974 if (insn & (1 << 23))
7975 offset -= imm;
7976 else
7977 offset += imm;
7978 tmp = new_tmp();
7979 tcg_gen_movi_i32(tmp, offset);
7980 } else {
7981 tmp = load_reg(s, rn);
7982 if (insn & (1 << 23))
7983 tcg_gen_subi_i32(tmp, tmp, imm);
7984 else
7985 tcg_gen_addi_i32(tmp, tmp, imm);
7988 store_reg(s, rd, tmp);
7990 } else {
7991 int shifter_out = 0;
7992 /* modified 12-bit immediate. */
7993 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7994 imm = (insn & 0xff);
7995 switch (shift) {
7996 case 0: /* XY */
7997 /* Nothing to do. */
7998 break;
7999 case 1: /* 00XY00XY */
8000 imm |= imm << 16;
8001 break;
8002 case 2: /* XY00XY00 */
8003 imm |= imm << 16;
8004 imm <<= 8;
8005 break;
8006 case 3: /* XYXYXYXY */
8007 imm |= imm << 16;
8008 imm |= imm << 8;
8009 break;
8010 default: /* Rotated constant. */
8011 shift = (shift << 1) | (imm >> 7);
8012 imm |= 0x80;
8013 imm = imm << (32 - shift);
8014 shifter_out = 1;
8015 break;
8017 tmp2 = new_tmp();
8018 tcg_gen_movi_i32(tmp2, imm);
8019 rn = (insn >> 16) & 0xf;
8020 if (rn == 15) {
8021 tmp = new_tmp();
8022 tcg_gen_movi_i32(tmp, 0);
8023 } else {
8024 tmp = load_reg(s, rn);
8026 op = (insn >> 21) & 0xf;
8027 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8028 shifter_out, tmp, tmp2))
8029 goto illegal_op;
8030 dead_tmp(tmp2);
8031 rd = (insn >> 8) & 0xf;
8032 if (rd != 15) {
8033 store_reg(s, rd, tmp);
8034 } else {
8035 dead_tmp(tmp);
8039 break;
8040 case 12: /* Load/store single data item. */
8042 int postinc = 0;
8043 int writeback = 0;
8044 int user;
8045 if ((insn & 0x01100000) == 0x01000000) {
8046 if (disas_neon_ls_insn(env, s, insn))
8047 goto illegal_op;
8048 break;
8050 user = IS_USER(s);
8051 if (rn == 15) {
8052 addr = new_tmp();
8053 /* PC relative. */
8054 /* s->pc has already been incremented by 4. */
8055 imm = s->pc & 0xfffffffc;
8056 if (insn & (1 << 23))
8057 imm += insn & 0xfff;
8058 else
8059 imm -= insn & 0xfff;
8060 tcg_gen_movi_i32(addr, imm);
8061 } else {
8062 addr = load_reg(s, rn);
8063 if (insn & (1 << 23)) {
8064 /* Positive offset. */
8065 imm = insn & 0xfff;
8066 tcg_gen_addi_i32(addr, addr, imm);
8067 } else {
8068 op = (insn >> 8) & 7;
8069 imm = insn & 0xff;
8070 switch (op) {
8071 case 0: case 8: /* Shifted Register. */
8072 shift = (insn >> 4) & 0xf;
8073 if (shift > 3)
8074 goto illegal_op;
8075 tmp = load_reg(s, rm);
8076 if (shift)
8077 tcg_gen_shli_i32(tmp, tmp, shift);
8078 tcg_gen_add_i32(addr, addr, tmp);
8079 dead_tmp(tmp);
8080 break;
8081 case 4: /* Negative offset. */
8082 tcg_gen_addi_i32(addr, addr, -imm);
8083 break;
8084 case 6: /* User privilege. */
8085 tcg_gen_addi_i32(addr, addr, imm);
8086 user = 1;
8087 break;
8088 case 1: /* Post-decrement. */
8089 imm = -imm;
8090 /* Fall through. */
8091 case 3: /* Post-increment. */
8092 postinc = 1;
8093 writeback = 1;
8094 break;
8095 case 5: /* Pre-decrement. */
8096 imm = -imm;
8097 /* Fall through. */
8098 case 7: /* Pre-increment. */
8099 tcg_gen_addi_i32(addr, addr, imm);
8100 writeback = 1;
8101 break;
8102 default:
8103 goto illegal_op;
8107 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8108 if (insn & (1 << 20)) {
8109 /* Load. */
8110 if (rs == 15 && op != 2) {
8111 if (op & 2)
8112 goto illegal_op;
8113 /* Memory hint. Implemented as NOP. */
8114 } else {
8115 switch (op) {
8116 case 0: tmp = gen_ld8u(addr, user); break;
8117 case 4: tmp = gen_ld8s(addr, user); break;
8118 case 1: tmp = gen_ld16u(addr, user); break;
8119 case 5: tmp = gen_ld16s(addr, user); break;
8120 case 2: tmp = gen_ld32(addr, user); break;
8121 default: goto illegal_op;
8123 if (rs == 15) {
8124 gen_bx(s, tmp);
8125 } else {
8126 store_reg(s, rs, tmp);
8129 } else {
8130 /* Store. */
8131 if (rs == 15)
8132 goto illegal_op;
8133 tmp = load_reg(s, rs);
8134 switch (op) {
8135 case 0: gen_st8(tmp, addr, user); break;
8136 case 1: gen_st16(tmp, addr, user); break;
8137 case 2: gen_st32(tmp, addr, user); break;
8138 default: goto illegal_op;
8141 if (postinc)
8142 tcg_gen_addi_i32(addr, addr, imm);
8143 if (writeback) {
8144 store_reg(s, rn, addr);
8145 } else {
8146 dead_tmp(addr);
8149 break;
8150 default:
8151 goto illegal_op;
8153 return 0;
8154 illegal_op:
8155 return 1;
8158 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8160 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8161 int32_t offset;
8162 int i;
8163 TCGv tmp;
8164 TCGv tmp2;
8165 TCGv addr;
8167 if (s->condexec_mask) {
8168 cond = s->condexec_cond;
8169 s->condlabel = gen_new_label();
8170 gen_test_cc(cond ^ 1, s->condlabel);
8171 s->condjmp = 1;
8174 insn = lduw_code(s->pc);
8175 s->pc += 2;
8177 switch (insn >> 12) {
8178 case 0: case 1:
8180 rd = insn & 7;
8181 op = (insn >> 11) & 3;
8182 if (op == 3) {
8183 /* add/subtract */
8184 rn = (insn >> 3) & 7;
8185 tmp = load_reg(s, rn);
8186 if (insn & (1 << 10)) {
8187 /* immediate */
8188 tmp2 = new_tmp();
8189 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8190 } else {
8191 /* reg */
8192 rm = (insn >> 6) & 7;
8193 tmp2 = load_reg(s, rm);
8195 if (insn & (1 << 9)) {
8196 if (s->condexec_mask)
8197 tcg_gen_sub_i32(tmp, tmp, tmp2);
8198 else
8199 gen_helper_sub_cc(tmp, tmp, tmp2);
8200 } else {
8201 if (s->condexec_mask)
8202 tcg_gen_add_i32(tmp, tmp, tmp2);
8203 else
8204 gen_helper_add_cc(tmp, tmp, tmp2);
8206 dead_tmp(tmp2);
8207 store_reg(s, rd, tmp);
8208 } else {
8209 /* shift immediate */
8210 rm = (insn >> 3) & 7;
8211 shift = (insn >> 6) & 0x1f;
8212 tmp = load_reg(s, rm);
8213 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8214 if (!s->condexec_mask)
8215 gen_logic_CC(tmp);
8216 store_reg(s, rd, tmp);
8218 break;
8219 case 2: case 3:
8220 /* arithmetic large immediate */
8221 op = (insn >> 11) & 3;
8222 rd = (insn >> 8) & 0x7;
8223 if (op == 0) { /* mov */
8224 tmp = new_tmp();
8225 tcg_gen_movi_i32(tmp, insn & 0xff);
8226 if (!s->condexec_mask)
8227 gen_logic_CC(tmp);
8228 store_reg(s, rd, tmp);
8229 } else {
8230 tmp = load_reg(s, rd);
8231 tmp2 = new_tmp();
8232 tcg_gen_movi_i32(tmp2, insn & 0xff);
8233 switch (op) {
8234 case 1: /* cmp */
8235 gen_helper_sub_cc(tmp, tmp, tmp2);
8236 dead_tmp(tmp);
8237 dead_tmp(tmp2);
8238 break;
8239 case 2: /* add */
8240 if (s->condexec_mask)
8241 tcg_gen_add_i32(tmp, tmp, tmp2);
8242 else
8243 gen_helper_add_cc(tmp, tmp, tmp2);
8244 dead_tmp(tmp2);
8245 store_reg(s, rd, tmp);
8246 break;
8247 case 3: /* sub */
8248 if (s->condexec_mask)
8249 tcg_gen_sub_i32(tmp, tmp, tmp2);
8250 else
8251 gen_helper_sub_cc(tmp, tmp, tmp2);
8252 dead_tmp(tmp2);
8253 store_reg(s, rd, tmp);
8254 break;
8257 break;
8258 case 4:
8259 if (insn & (1 << 11)) {
8260 rd = (insn >> 8) & 7;
8261 /* load pc-relative. Bit 1 of PC is ignored. */
8262 val = s->pc + 2 + ((insn & 0xff) * 4);
8263 val &= ~(uint32_t)2;
8264 addr = new_tmp();
8265 tcg_gen_movi_i32(addr, val);
8266 tmp = gen_ld32(addr, IS_USER(s));
8267 dead_tmp(addr);
8268 store_reg(s, rd, tmp);
8269 break;
8271 if (insn & (1 << 10)) {
8272 /* data processing extended or blx */
8273 rd = (insn & 7) | ((insn >> 4) & 8);
8274 rm = (insn >> 3) & 0xf;
8275 op = (insn >> 8) & 3;
8276 switch (op) {
8277 case 0: /* add */
8278 tmp = load_reg(s, rd);
8279 tmp2 = load_reg(s, rm);
8280 tcg_gen_add_i32(tmp, tmp, tmp2);
8281 dead_tmp(tmp2);
8282 store_reg(s, rd, tmp);
8283 break;
8284 case 1: /* cmp */
8285 tmp = load_reg(s, rd);
8286 tmp2 = load_reg(s, rm);
8287 gen_helper_sub_cc(tmp, tmp, tmp2);
8288 dead_tmp(tmp2);
8289 dead_tmp(tmp);
8290 break;
8291 case 2: /* mov/cpy */
8292 tmp = load_reg(s, rm);
8293 store_reg(s, rd, tmp);
8294 break;
8295 case 3:/* branch [and link] exchange thumb register */
8296 tmp = load_reg(s, rm);
8297 if (insn & (1 << 7)) {
8298 val = (uint32_t)s->pc | 1;
8299 tmp2 = new_tmp();
8300 tcg_gen_movi_i32(tmp2, val);
8301 store_reg(s, 14, tmp2);
8303 gen_bx(s, tmp);
8304 break;
8306 break;
8309 /* data processing register */
8310 rd = insn & 7;
8311 rm = (insn >> 3) & 7;
8312 op = (insn >> 6) & 0xf;
8313 if (op == 2 || op == 3 || op == 4 || op == 7) {
8314 /* the shift/rotate ops want the operands backwards */
8315 val = rm;
8316 rm = rd;
8317 rd = val;
8318 val = 1;
8319 } else {
8320 val = 0;
8323 if (op == 9) { /* neg */
8324 tmp = new_tmp();
8325 tcg_gen_movi_i32(tmp, 0);
8326 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8327 tmp = load_reg(s, rd);
8328 } else {
8329 TCGV_UNUSED(tmp);
8332 tmp2 = load_reg(s, rm);
8333 switch (op) {
8334 case 0x0: /* and */
8335 tcg_gen_and_i32(tmp, tmp, tmp2);
8336 if (!s->condexec_mask)
8337 gen_logic_CC(tmp);
8338 break;
8339 case 0x1: /* eor */
8340 tcg_gen_xor_i32(tmp, tmp, tmp2);
8341 if (!s->condexec_mask)
8342 gen_logic_CC(tmp);
8343 break;
8344 case 0x2: /* lsl */
8345 if (s->condexec_mask) {
8346 gen_helper_shl(tmp2, tmp2, tmp);
8347 } else {
8348 gen_helper_shl_cc(tmp2, tmp2, tmp);
8349 gen_logic_CC(tmp2);
8351 break;
8352 case 0x3: /* lsr */
8353 if (s->condexec_mask) {
8354 gen_helper_shr(tmp2, tmp2, tmp);
8355 } else {
8356 gen_helper_shr_cc(tmp2, tmp2, tmp);
8357 gen_logic_CC(tmp2);
8359 break;
8360 case 0x4: /* asr */
8361 if (s->condexec_mask) {
8362 gen_helper_sar(tmp2, tmp2, tmp);
8363 } else {
8364 gen_helper_sar_cc(tmp2, tmp2, tmp);
8365 gen_logic_CC(tmp2);
8367 break;
8368 case 0x5: /* adc */
8369 if (s->condexec_mask)
8370 gen_adc(tmp, tmp2);
8371 else
8372 gen_helper_adc_cc(tmp, tmp, tmp2);
8373 break;
8374 case 0x6: /* sbc */
8375 if (s->condexec_mask)
8376 gen_sub_carry(tmp, tmp, tmp2);
8377 else
8378 gen_helper_sbc_cc(tmp, tmp, tmp2);
8379 break;
8380 case 0x7: /* ror */
8381 if (s->condexec_mask) {
8382 gen_helper_ror(tmp2, tmp2, tmp);
8383 } else {
8384 gen_helper_ror_cc(tmp2, tmp2, tmp);
8385 gen_logic_CC(tmp2);
8387 break;
8388 case 0x8: /* tst */
8389 tcg_gen_and_i32(tmp, tmp, tmp2);
8390 gen_logic_CC(tmp);
8391 rd = 16;
8392 break;
8393 case 0x9: /* neg */
8394 if (s->condexec_mask)
8395 tcg_gen_neg_i32(tmp, tmp2);
8396 else
8397 gen_helper_sub_cc(tmp, tmp, tmp2);
8398 break;
8399 case 0xa: /* cmp */
8400 gen_helper_sub_cc(tmp, tmp, tmp2);
8401 rd = 16;
8402 break;
8403 case 0xb: /* cmn */
8404 gen_helper_add_cc(tmp, tmp, tmp2);
8405 rd = 16;
8406 break;
8407 case 0xc: /* orr */
8408 tcg_gen_or_i32(tmp, tmp, tmp2);
8409 if (!s->condexec_mask)
8410 gen_logic_CC(tmp);
8411 break;
8412 case 0xd: /* mul */
8413 gen_mull(tmp, tmp2);
8414 if (!s->condexec_mask)
8415 gen_logic_CC(tmp);
8416 break;
8417 case 0xe: /* bic */
8418 tcg_gen_bic_i32(tmp, tmp, tmp2);
8419 if (!s->condexec_mask)
8420 gen_logic_CC(tmp);
8421 break;
8422 case 0xf: /* mvn */
8423 tcg_gen_not_i32(tmp2, tmp2);
8424 if (!s->condexec_mask)
8425 gen_logic_CC(tmp2);
8426 val = 1;
8427 rm = rd;
8428 break;
8430 if (rd != 16) {
8431 if (val) {
8432 store_reg(s, rm, tmp2);
8433 if (op != 0xf)
8434 dead_tmp(tmp);
8435 } else {
8436 store_reg(s, rd, tmp);
8437 dead_tmp(tmp2);
8439 } else {
8440 dead_tmp(tmp);
8441 dead_tmp(tmp2);
8443 break;
8445 case 5:
8446 /* load/store register offset. */
8447 rd = insn & 7;
8448 rn = (insn >> 3) & 7;
8449 rm = (insn >> 6) & 7;
8450 op = (insn >> 9) & 7;
8451 addr = load_reg(s, rn);
8452 tmp = load_reg(s, rm);
8453 tcg_gen_add_i32(addr, addr, tmp);
8454 dead_tmp(tmp);
8456 if (op < 3) /* store */
8457 tmp = load_reg(s, rd);
8459 switch (op) {
8460 case 0: /* str */
8461 gen_st32(tmp, addr, IS_USER(s));
8462 break;
8463 case 1: /* strh */
8464 gen_st16(tmp, addr, IS_USER(s));
8465 break;
8466 case 2: /* strb */
8467 gen_st8(tmp, addr, IS_USER(s));
8468 break;
8469 case 3: /* ldrsb */
8470 tmp = gen_ld8s(addr, IS_USER(s));
8471 break;
8472 case 4: /* ldr */
8473 tmp = gen_ld32(addr, IS_USER(s));
8474 break;
8475 case 5: /* ldrh */
8476 tmp = gen_ld16u(addr, IS_USER(s));
8477 break;
8478 case 6: /* ldrb */
8479 tmp = gen_ld8u(addr, IS_USER(s));
8480 break;
8481 case 7: /* ldrsh */
8482 tmp = gen_ld16s(addr, IS_USER(s));
8483 break;
8485 if (op >= 3) /* load */
8486 store_reg(s, rd, tmp);
8487 dead_tmp(addr);
8488 break;
8490 case 6:
8491 /* load/store word immediate offset */
8492 rd = insn & 7;
8493 rn = (insn >> 3) & 7;
8494 addr = load_reg(s, rn);
8495 val = (insn >> 4) & 0x7c;
8496 tcg_gen_addi_i32(addr, addr, val);
8498 if (insn & (1 << 11)) {
8499 /* load */
8500 tmp = gen_ld32(addr, IS_USER(s));
8501 store_reg(s, rd, tmp);
8502 } else {
8503 /* store */
8504 tmp = load_reg(s, rd);
8505 gen_st32(tmp, addr, IS_USER(s));
8507 dead_tmp(addr);
8508 break;
8510 case 7:
8511 /* load/store byte immediate offset */
8512 rd = insn & 7;
8513 rn = (insn >> 3) & 7;
8514 addr = load_reg(s, rn);
8515 val = (insn >> 6) & 0x1f;
8516 tcg_gen_addi_i32(addr, addr, val);
8518 if (insn & (1 << 11)) {
8519 /* load */
8520 tmp = gen_ld8u(addr, IS_USER(s));
8521 store_reg(s, rd, tmp);
8522 } else {
8523 /* store */
8524 tmp = load_reg(s, rd);
8525 gen_st8(tmp, addr, IS_USER(s));
8527 dead_tmp(addr);
8528 break;
8530 case 8:
8531 /* load/store halfword immediate offset */
8532 rd = insn & 7;
8533 rn = (insn >> 3) & 7;
8534 addr = load_reg(s, rn);
8535 val = (insn >> 5) & 0x3e;
8536 tcg_gen_addi_i32(addr, addr, val);
8538 if (insn & (1 << 11)) {
8539 /* load */
8540 tmp = gen_ld16u(addr, IS_USER(s));
8541 store_reg(s, rd, tmp);
8542 } else {
8543 /* store */
8544 tmp = load_reg(s, rd);
8545 gen_st16(tmp, addr, IS_USER(s));
8547 dead_tmp(addr);
8548 break;
8550 case 9:
8551 /* load/store from stack */
8552 rd = (insn >> 8) & 7;
8553 addr = load_reg(s, 13);
8554 val = (insn & 0xff) * 4;
8555 tcg_gen_addi_i32(addr, addr, val);
8557 if (insn & (1 << 11)) {
8558 /* load */
8559 tmp = gen_ld32(addr, IS_USER(s));
8560 store_reg(s, rd, tmp);
8561 } else {
8562 /* store */
8563 tmp = load_reg(s, rd);
8564 gen_st32(tmp, addr, IS_USER(s));
8566 dead_tmp(addr);
8567 break;
8569 case 10:
8570 /* add to high reg */
8571 rd = (insn >> 8) & 7;
8572 if (insn & (1 << 11)) {
8573 /* SP */
8574 tmp = load_reg(s, 13);
8575 } else {
8576 /* PC. bit 1 is ignored. */
8577 tmp = new_tmp();
8578 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8580 val = (insn & 0xff) * 4;
8581 tcg_gen_addi_i32(tmp, tmp, val);
8582 store_reg(s, rd, tmp);
8583 break;
8585 case 11:
8586 /* misc */
8587 op = (insn >> 8) & 0xf;
8588 switch (op) {
8589 case 0:
8590 /* adjust stack pointer */
8591 tmp = load_reg(s, 13);
8592 val = (insn & 0x7f) * 4;
8593 if (insn & (1 << 7))
8594 val = -(int32_t)val;
8595 tcg_gen_addi_i32(tmp, tmp, val);
8596 store_reg(s, 13, tmp);
8597 break;
8599 case 2: /* sign/zero extend. */
8600 ARCH(6);
8601 rd = insn & 7;
8602 rm = (insn >> 3) & 7;
8603 tmp = load_reg(s, rm);
8604 switch ((insn >> 6) & 3) {
8605 case 0: gen_sxth(tmp); break;
8606 case 1: gen_sxtb(tmp); break;
8607 case 2: gen_uxth(tmp); break;
8608 case 3: gen_uxtb(tmp); break;
8610 store_reg(s, rd, tmp);
8611 break;
8612 case 4: case 5: case 0xc: case 0xd:
8613 /* push/pop */
8614 addr = load_reg(s, 13);
8615 if (insn & (1 << 8))
8616 offset = 4;
8617 else
8618 offset = 0;
8619 for (i = 0; i < 8; i++) {
8620 if (insn & (1 << i))
8621 offset += 4;
8623 if ((insn & (1 << 11)) == 0) {
8624 tcg_gen_addi_i32(addr, addr, -offset);
8626 for (i = 0; i < 8; i++) {
8627 if (insn & (1 << i)) {
8628 if (insn & (1 << 11)) {
8629 /* pop */
8630 tmp = gen_ld32(addr, IS_USER(s));
8631 store_reg(s, i, tmp);
8632 } else {
8633 /* push */
8634 tmp = load_reg(s, i);
8635 gen_st32(tmp, addr, IS_USER(s));
8637 /* advance to the next address. */
8638 tcg_gen_addi_i32(addr, addr, 4);
8641 TCGV_UNUSED(tmp);
8642 if (insn & (1 << 8)) {
8643 if (insn & (1 << 11)) {
8644 /* pop pc */
8645 tmp = gen_ld32(addr, IS_USER(s));
8646 /* don't set the pc until the rest of the instruction
8647 has completed */
8648 } else {
8649 /* push lr */
8650 tmp = load_reg(s, 14);
8651 gen_st32(tmp, addr, IS_USER(s));
8653 tcg_gen_addi_i32(addr, addr, 4);
8655 if ((insn & (1 << 11)) == 0) {
8656 tcg_gen_addi_i32(addr, addr, -offset);
8658 /* write back the new stack pointer */
8659 store_reg(s, 13, addr);
8660 /* set the new PC value */
8661 if ((insn & 0x0900) == 0x0900)
8662 gen_bx(s, tmp);
8663 break;
8665 case 1: case 3: case 9: case 11: /* czb */
8666 rm = insn & 7;
8667 tmp = load_reg(s, rm);
8668 s->condlabel = gen_new_label();
8669 s->condjmp = 1;
8670 if (insn & (1 << 11))
8671 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8672 else
8673 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8674 dead_tmp(tmp);
8675 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8676 val = (uint32_t)s->pc + 2;
8677 val += offset;
8678 gen_jmp(s, val);
8679 break;
8681 case 15: /* IT, nop-hint. */
8682 if ((insn & 0xf) == 0) {
8683 gen_nop_hint(s, (insn >> 4) & 0xf);
8684 break;
8686 /* If Then. */
8687 s->condexec_cond = (insn >> 4) & 0xe;
8688 s->condexec_mask = insn & 0x1f;
8689 /* No actual code generated for this insn, just setup state. */
8690 break;
8692 case 0xe: /* bkpt */
8693 gen_set_condexec(s);
8694 gen_set_pc_im(s->pc - 2);
8695 gen_exception(EXCP_BKPT);
8696 s->is_jmp = DISAS_JUMP;
8697 break;
8699 case 0xa: /* rev */
8700 ARCH(6);
8701 rn = (insn >> 3) & 0x7;
8702 rd = insn & 0x7;
8703 tmp = load_reg(s, rn);
8704 switch ((insn >> 6) & 3) {
8705 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8706 case 1: gen_rev16(tmp); break;
8707 case 3: gen_revsh(tmp); break;
8708 default: goto illegal_op;
8710 store_reg(s, rd, tmp);
8711 break;
8713 case 6: /* cps */
8714 ARCH(6);
8715 if (IS_USER(s))
8716 break;
8717 if (IS_M(env)) {
8718 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8719 /* PRIMASK */
8720 if (insn & 1) {
8721 addr = tcg_const_i32(16);
8722 gen_helper_v7m_msr(cpu_env, addr, tmp);
8724 /* FAULTMASK */
8725 if (insn & 2) {
8726 addr = tcg_const_i32(17);
8727 gen_helper_v7m_msr(cpu_env, addr, tmp);
8729 gen_lookup_tb(s);
8730 } else {
8731 if (insn & (1 << 4))
8732 shift = CPSR_A | CPSR_I | CPSR_F;
8733 else
8734 shift = 0;
8735 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8737 break;
8739 default:
8740 goto undef;
8742 break;
8744 case 12:
8745 /* load/store multiple */
8746 rn = (insn >> 8) & 0x7;
8747 addr = load_reg(s, rn);
8748 for (i = 0; i < 8; i++) {
8749 if (insn & (1 << i)) {
8750 if (insn & (1 << 11)) {
8751 /* load */
8752 tmp = gen_ld32(addr, IS_USER(s));
8753 store_reg(s, i, tmp);
8754 } else {
8755 /* store */
8756 tmp = load_reg(s, i);
8757 gen_st32(tmp, addr, IS_USER(s));
8759 /* advance to the next address */
8760 tcg_gen_addi_i32(addr, addr, 4);
8763 /* Base register writeback. */
8764 if ((insn & (1 << rn)) == 0) {
8765 store_reg(s, rn, addr);
8766 } else {
8767 dead_tmp(addr);
8769 break;
8771 case 13:
8772 /* conditional branch or swi */
8773 cond = (insn >> 8) & 0xf;
8774 if (cond == 0xe)
8775 goto undef;
8777 if (cond == 0xf) {
8778 /* swi */
8779 gen_set_condexec(s);
8780 gen_set_pc_im(s->pc);
8781 s->is_jmp = DISAS_SWI;
8782 break;
8784 /* generate a conditional jump to next instruction */
8785 s->condlabel = gen_new_label();
8786 gen_test_cc(cond ^ 1, s->condlabel);
8787 s->condjmp = 1;
8789 /* jump to the offset */
8790 val = (uint32_t)s->pc + 2;
8791 offset = ((int32_t)insn << 24) >> 24;
8792 val += offset << 1;
8793 gen_jmp(s, val);
8794 break;
8796 case 14:
8797 if (insn & (1 << 11)) {
8798 if (disas_thumb2_insn(env, s, insn))
8799 goto undef32;
8800 break;
8802 /* unconditional branch */
8803 val = (uint32_t)s->pc;
8804 offset = ((int32_t)insn << 21) >> 21;
8805 val += (offset << 1) + 2;
8806 gen_jmp(s, val);
8807 break;
8809 case 15:
8810 if (disas_thumb2_insn(env, s, insn))
8811 goto undef32;
8812 break;
8814 return;
8815 undef32:
8816 gen_set_condexec(s);
8817 gen_set_pc_im(s->pc - 4);
8818 gen_exception(EXCP_UDEF);
8819 s->is_jmp = DISAS_JUMP;
8820 return;
8821 illegal_op:
8822 undef:
8823 gen_set_condexec(s);
8824 gen_set_pc_im(s->pc - 2);
8825 gen_exception(EXCP_UDEF);
8826 s->is_jmp = DISAS_JUMP;
8829 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8830 basic block 'tb'. If search_pc is TRUE, also generate PC
8831 information for each intermediate instruction. */
8832 static inline void gen_intermediate_code_internal(CPUState *env,
8833 TranslationBlock *tb,
8834 int search_pc)
8836 DisasContext dc1, *dc = &dc1;
8837 CPUBreakpoint *bp;
8838 uint16_t *gen_opc_end;
8839 int j, lj;
8840 target_ulong pc_start;
8841 uint32_t next_page_start;
8842 int num_insns;
8843 int max_insns;
8845 /* generate intermediate code */
8846 num_temps = 0;
8848 pc_start = tb->pc;
8850 dc->tb = tb;
8852 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8854 dc->is_jmp = DISAS_NEXT;
8855 dc->pc = pc_start;
8856 dc->singlestep_enabled = env->singlestep_enabled;
8857 dc->condjmp = 0;
8858 dc->thumb = env->thumb;
8859 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8860 dc->condexec_cond = env->condexec_bits >> 4;
8861 #if !defined(CONFIG_USER_ONLY)
8862 if (IS_M(env)) {
8863 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8864 } else {
8865 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8867 #endif
8868 cpu_F0s = tcg_temp_new_i32();
8869 cpu_F1s = tcg_temp_new_i32();
8870 cpu_F0d = tcg_temp_new_i64();
8871 cpu_F1d = tcg_temp_new_i64();
8872 cpu_V0 = cpu_F0d;
8873 cpu_V1 = cpu_F1d;
8874 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8875 cpu_M0 = tcg_temp_new_i64();
8876 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8877 lj = -1;
8878 num_insns = 0;
8879 max_insns = tb->cflags & CF_COUNT_MASK;
8880 if (max_insns == 0)
8881 max_insns = CF_COUNT_MASK;
8883 gen_icount_start();
8884 /* Reset the conditional execution bits immediately. This avoids
8885 complications trying to do it at the end of the block. */
8886 if (env->condexec_bits)
8888 TCGv tmp = new_tmp();
8889 tcg_gen_movi_i32(tmp, 0);
8890 store_cpu_field(tmp, condexec_bits);
8892 do {
8893 #ifdef CONFIG_USER_ONLY
8894 /* Intercept jump to the magic kernel page. */
8895 if (dc->pc >= 0xffff0000) {
8896 /* We always get here via a jump, so know we are not in a
8897 conditional execution block. */
8898 gen_exception(EXCP_KERNEL_TRAP);
8899 dc->is_jmp = DISAS_UPDATE;
8900 break;
8902 #else
8903 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8904 /* We always get here via a jump, so know we are not in a
8905 conditional execution block. */
8906 gen_exception(EXCP_EXCEPTION_EXIT);
8907 dc->is_jmp = DISAS_UPDATE;
8908 break;
8910 #endif
8912 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8913 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8914 if (bp->pc == dc->pc) {
8915 gen_set_condexec(dc);
8916 gen_set_pc_im(dc->pc);
8917 gen_exception(EXCP_DEBUG);
8918 dc->is_jmp = DISAS_JUMP;
8919 /* Advance PC so that clearing the breakpoint will
8920 invalidate this TB. */
8921 dc->pc += 2;
8922 goto done_generating;
8923 break;
8927 if (search_pc) {
8928 j = gen_opc_ptr - gen_opc_buf;
8929 if (lj < j) {
8930 lj++;
8931 while (lj < j)
8932 gen_opc_instr_start[lj++] = 0;
8934 gen_opc_pc[lj] = dc->pc;
8935 gen_opc_instr_start[lj] = 1;
8936 gen_opc_icount[lj] = num_insns;
8939 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8940 gen_io_start();
8942 if (env->thumb) {
8943 disas_thumb_insn(env, dc);
8944 if (dc->condexec_mask) {
8945 dc->condexec_cond = (dc->condexec_cond & 0xe)
8946 | ((dc->condexec_mask >> 4) & 1);
8947 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8948 if (dc->condexec_mask == 0) {
8949 dc->condexec_cond = 0;
8952 } else {
8953 disas_arm_insn(env, dc);
8955 if (num_temps) {
8956 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8957 num_temps = 0;
8960 if (dc->condjmp && !dc->is_jmp) {
8961 gen_set_label(dc->condlabel);
8962 dc->condjmp = 0;
8964 /* Translation stops when a conditional branch is encountered.
8965 * Otherwise the subsequent code could get translated several times.
8966 * Also stop translation when a page boundary is reached. This
8967 * ensures prefetch aborts occur at the right place. */
8968 num_insns ++;
8969 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8970 !env->singlestep_enabled &&
8971 !singlestep &&
8972 dc->pc < next_page_start &&
8973 num_insns < max_insns);
8975 if (tb->cflags & CF_LAST_IO) {
8976 if (dc->condjmp) {
8977 /* FIXME: This can theoretically happen with self-modifying
8978 code. */
8979 cpu_abort(env, "IO on conditional branch instruction");
8981 gen_io_end();
8984 /* At this stage dc->condjmp will only be set when the skipped
8985 instruction was a conditional branch or trap, and the PC has
8986 already been written. */
8987 if (unlikely(env->singlestep_enabled)) {
8988 /* Make sure the pc is updated, and raise a debug exception. */
8989 if (dc->condjmp) {
8990 gen_set_condexec(dc);
8991 if (dc->is_jmp == DISAS_SWI) {
8992 gen_exception(EXCP_SWI);
8993 } else {
8994 gen_exception(EXCP_DEBUG);
8996 gen_set_label(dc->condlabel);
8998 if (dc->condjmp || !dc->is_jmp) {
8999 gen_set_pc_im(dc->pc);
9000 dc->condjmp = 0;
9002 gen_set_condexec(dc);
9003 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9004 gen_exception(EXCP_SWI);
9005 } else {
9006 /* FIXME: Single stepping a WFI insn will not halt
9007 the CPU. */
9008 gen_exception(EXCP_DEBUG);
9010 } else {
9011 /* While branches must always occur at the end of an IT block,
9012 there are a few other things that can cause us to terminate
9013 the TB in the middel of an IT block:
9014 - Exception generating instructions (bkpt, swi, undefined).
9015 - Page boundaries.
9016 - Hardware watchpoints.
9017 Hardware breakpoints have already been handled and skip this code.
9019 gen_set_condexec(dc);
9020 switch(dc->is_jmp) {
9021 case DISAS_NEXT:
9022 gen_goto_tb(dc, 1, dc->pc);
9023 break;
9024 default:
9025 case DISAS_JUMP:
9026 case DISAS_UPDATE:
9027 /* indicate that the hash table must be used to find the next TB */
9028 tcg_gen_exit_tb(0);
9029 break;
9030 case DISAS_TB_JUMP:
9031 /* nothing more to generate */
9032 break;
9033 case DISAS_WFI:
9034 gen_helper_wfi();
9035 break;
9036 case DISAS_SWI:
9037 gen_exception(EXCP_SWI);
9038 break;
9040 if (dc->condjmp) {
9041 gen_set_label(dc->condlabel);
9042 gen_set_condexec(dc);
9043 gen_goto_tb(dc, 1, dc->pc);
9044 dc->condjmp = 0;
9048 done_generating:
9049 gen_icount_end(tb, num_insns);
9050 *gen_opc_ptr = INDEX_op_end;
9052 #ifdef DEBUG_DISAS
9053 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9054 qemu_log("----------------\n");
9055 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9056 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9057 qemu_log("\n");
9059 #endif
9060 if (search_pc) {
9061 j = gen_opc_ptr - gen_opc_buf;
9062 lj++;
9063 while (lj <= j)
9064 gen_opc_instr_start[lj++] = 0;
9065 } else {
9066 tb->size = dc->pc - pc_start;
9067 tb->icount = num_insns;
9071 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9073 gen_intermediate_code_internal(env, tb, 0);
9076 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9078 gen_intermediate_code_internal(env, tb, 1);
9081 static const char *cpu_mode_names[16] = {
9082 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9083 "???", "???", "???", "und", "???", "???", "???", "sys"
9086 void cpu_dump_state(CPUState *env, FILE *f,
9087 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9088 int flags)
9090 int i;
9091 #if 0
9092 union {
9093 uint32_t i;
9094 float s;
9095 } s0, s1;
9096 CPU_DoubleU d;
9097 /* ??? This assumes float64 and double have the same layout.
9098 Oh well, it's only debug dumps. */
9099 union {
9100 float64 f64;
9101 double d;
9102 } d0;
9103 #endif
9104 uint32_t psr;
9106 for(i=0;i<16;i++) {
9107 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9108 if ((i % 4) == 3)
9109 cpu_fprintf(f, "\n");
9110 else
9111 cpu_fprintf(f, " ");
9113 psr = cpsr_read(env);
9114 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9115 psr,
9116 psr & (1 << 31) ? 'N' : '-',
9117 psr & (1 << 30) ? 'Z' : '-',
9118 psr & (1 << 29) ? 'C' : '-',
9119 psr & (1 << 28) ? 'V' : '-',
9120 psr & CPSR_T ? 'T' : 'A',
9121 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9123 #if 0
9124 for (i = 0; i < 16; i++) {
9125 d.d = env->vfp.regs[i];
9126 s0.i = d.l.lower;
9127 s1.i = d.l.upper;
9128 d0.f64 = d.d;
9129 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9130 i * 2, (int)s0.i, s0.s,
9131 i * 2 + 1, (int)s1.i, s1.s,
9132 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9133 d0.d);
9135 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9136 #endif
9139 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9140 unsigned long searched_pc, int pc_pos, void *puc)
9142 env->regs[15] = gen_opc_pc[pc_pos];