nand: boot code cleanup
[qemu/mini2440.git] / target-arm / translate.c
blobadac19a267cca2e50f97a23ae750d0d2cc888dd8
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, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <inttypes.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
32 #include "qemu-log.h"
34 #include "helpers.h"
35 #define GEN_HELPER 1
36 #include "helpers.h"
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext {
48 target_ulong pc;
49 int is_jmp;
50 /* Nonzero if this instruction has been conditionally skipped. */
51 int condjmp;
52 /* The label that will be jumped to when the instruction is skipped. */
53 int condlabel;
54 /* Thumb-2 condtional execution bits. */
55 int condexec_mask;
56 int condexec_cond;
57 struct TranslationBlock *tb;
58 int singlestep_enabled;
59 int thumb;
60 #if !defined(CONFIG_USER_ONLY)
61 int user;
62 #endif
63 } DisasContext;
65 #if defined(CONFIG_USER_ONLY)
66 #define IS_USER(s) 1
67 #else
68 #define IS_USER(s) (s->user)
69 #endif
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
73 #define DISAS_WFI 4
74 #define DISAS_SWI 5
76 static TCGv_ptr cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
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 /* initialize TCG globals. */
89 void arm_translate_init(void)
91 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
93 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
94 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
96 #define GEN_HELPER 2
97 #include "helpers.h"
100 /* The code generator doesn't like lots of temporaries, so maintain our own
101 cache for reuse within a function. */
102 #define MAX_TEMPS 8
103 static int num_temps;
104 static TCGv temps[MAX_TEMPS];
106 /* Allocate a temporary variable. */
107 static TCGv_i32 new_tmp(void)
109 TCGv tmp;
110 if (num_temps == MAX_TEMPS)
111 abort();
113 if (GET_TCGV_I32(temps[num_temps]))
114 return temps[num_temps++];
116 tmp = tcg_temp_new_i32();
117 temps[num_temps++] = tmp;
118 return tmp;
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp)
124 int i;
125 num_temps--;
126 i = num_temps;
127 if (TCGV_EQUAL(temps[i], tmp))
128 return;
130 /* Shuffle this temp to the last slot. */
131 while (!TCGV_EQUAL(temps[i], tmp))
132 i--;
133 while (i < num_temps) {
134 temps[i] = temps[i + 1];
135 i++;
137 temps[i] = tmp;
140 static inline TCGv load_cpu_offset(int offset)
142 TCGv tmp = new_tmp();
143 tcg_gen_ld_i32(tmp, cpu_env, offset);
144 return tmp;
147 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
149 static inline void store_cpu_offset(TCGv var, int offset)
151 tcg_gen_st_i32(var, cpu_env, offset);
152 dead_tmp(var);
155 #define store_cpu_field(var, name) \
156 store_cpu_offset(var, offsetof(CPUState, name))
158 /* Set a variable to the value of a CPU register. */
159 static void load_reg_var(DisasContext *s, TCGv var, int reg)
161 if (reg == 15) {
162 uint32_t addr;
163 /* normaly, since we updated PC, we need only to add one insn */
164 if (s->thumb)
165 addr = (long)s->pc + 2;
166 else
167 addr = (long)s->pc + 4;
168 tcg_gen_movi_i32(var, addr);
169 } else {
170 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
174 /* Create a new temporary and set it to the value of a CPU register. */
175 static inline TCGv load_reg(DisasContext *s, int reg)
177 TCGv tmp = new_tmp();
178 load_reg_var(s, tmp, reg);
179 return tmp;
182 /* Set a CPU register. The source must be a temporary and will be
183 marked as dead. */
184 static void store_reg(DisasContext *s, int reg, TCGv var)
186 if (reg == 15) {
187 tcg_gen_andi_i32(var, var, ~1);
188 s->is_jmp = DISAS_JUMP;
190 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
191 dead_tmp(var);
195 /* Basic operations. */
196 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
197 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
198 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
200 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
201 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
203 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
205 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
207 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
209 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
211 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
214 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
215 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
216 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
217 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
219 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
220 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
222 /* Value extensions. */
223 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
224 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
225 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
226 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
228 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
229 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
231 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
233 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
234 /* Set NZCV flags from the high 4 bits of var. */
235 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
237 static void gen_exception(int excp)
239 TCGv tmp = new_tmp();
240 tcg_gen_movi_i32(tmp, excp);
241 gen_helper_exception(tmp);
242 dead_tmp(tmp);
245 static void gen_smul_dual(TCGv a, TCGv b)
247 TCGv tmp1 = new_tmp();
248 TCGv tmp2 = new_tmp();
249 tcg_gen_ext16s_i32(tmp1, a);
250 tcg_gen_ext16s_i32(tmp2, b);
251 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
252 dead_tmp(tmp2);
253 tcg_gen_sari_i32(a, a, 16);
254 tcg_gen_sari_i32(b, b, 16);
255 tcg_gen_mul_i32(b, b, a);
256 tcg_gen_mov_i32(a, tmp1);
257 dead_tmp(tmp1);
260 /* Byteswap each halfword. */
261 static void gen_rev16(TCGv var)
263 TCGv tmp = new_tmp();
264 tcg_gen_shri_i32(tmp, var, 8);
265 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
266 tcg_gen_shli_i32(var, var, 8);
267 tcg_gen_andi_i32(var, var, 0xff00ff00);
268 tcg_gen_or_i32(var, var, tmp);
269 dead_tmp(tmp);
272 /* Byteswap low halfword and sign extend. */
273 static void gen_revsh(TCGv var)
275 TCGv tmp = new_tmp();
276 tcg_gen_shri_i32(tmp, var, 8);
277 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
278 tcg_gen_shli_i32(var, var, 8);
279 tcg_gen_ext8s_i32(var, var);
280 tcg_gen_or_i32(var, var, tmp);
281 dead_tmp(tmp);
284 /* Unsigned bitfield extract. */
285 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
287 if (shift)
288 tcg_gen_shri_i32(var, var, shift);
289 tcg_gen_andi_i32(var, var, mask);
292 /* Signed bitfield extract. */
293 static void gen_sbfx(TCGv var, int shift, int width)
295 uint32_t signbit;
297 if (shift)
298 tcg_gen_sari_i32(var, var, shift);
299 if (shift + width < 32) {
300 signbit = 1u << (width - 1);
301 tcg_gen_andi_i32(var, var, (1u << width) - 1);
302 tcg_gen_xori_i32(var, var, signbit);
303 tcg_gen_subi_i32(var, var, signbit);
307 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
308 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
310 tcg_gen_andi_i32(val, val, mask);
311 tcg_gen_shli_i32(val, val, shift);
312 tcg_gen_andi_i32(base, base, ~(mask << shift));
313 tcg_gen_or_i32(dest, base, val);
316 /* Round the top 32 bits of a 64-bit value. */
317 static void gen_roundqd(TCGv a, TCGv b)
319 tcg_gen_shri_i32(a, a, 31);
320 tcg_gen_add_i32(a, a, b);
323 /* FIXME: Most targets have native widening multiplication.
324 It would be good to use that instead of a full wide multiply. */
325 /* 32x32->64 multiply. Marks inputs as dead. */
326 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
328 TCGv_i64 tmp1 = tcg_temp_new_i64();
329 TCGv_i64 tmp2 = tcg_temp_new_i64();
331 tcg_gen_extu_i32_i64(tmp1, a);
332 dead_tmp(a);
333 tcg_gen_extu_i32_i64(tmp2, b);
334 dead_tmp(b);
335 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
336 return tmp1;
339 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
341 TCGv_i64 tmp1 = tcg_temp_new_i64();
342 TCGv_i64 tmp2 = tcg_temp_new_i64();
344 tcg_gen_ext_i32_i64(tmp1, a);
345 dead_tmp(a);
346 tcg_gen_ext_i32_i64(tmp2, b);
347 dead_tmp(b);
348 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
349 return tmp1;
352 /* Unsigned 32x32->64 multiply. */
353 static void gen_op_mull_T0_T1(void)
355 TCGv_i64 tmp1 = tcg_temp_new_i64();
356 TCGv_i64 tmp2 = tcg_temp_new_i64();
358 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
359 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
360 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
361 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
362 tcg_gen_shri_i64(tmp1, tmp1, 32);
363 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
366 /* Signed 32x32->64 multiply. */
367 static void gen_imull(TCGv a, TCGv b)
369 TCGv_i64 tmp1 = tcg_temp_new_i64();
370 TCGv_i64 tmp2 = tcg_temp_new_i64();
372 tcg_gen_ext_i32_i64(tmp1, a);
373 tcg_gen_ext_i32_i64(tmp2, b);
374 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
375 tcg_gen_trunc_i64_i32(a, tmp1);
376 tcg_gen_shri_i64(tmp1, tmp1, 32);
377 tcg_gen_trunc_i64_i32(b, tmp1);
380 /* Swap low and high halfwords. */
381 static void gen_swap_half(TCGv var)
383 TCGv tmp = new_tmp();
384 tcg_gen_shri_i32(tmp, var, 16);
385 tcg_gen_shli_i32(var, var, 16);
386 tcg_gen_or_i32(var, var, tmp);
387 dead_tmp(tmp);
390 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
391 tmp = (t0 ^ t1) & 0x8000;
392 t0 &= ~0x8000;
393 t1 &= ~0x8000;
394 t0 = (t0 + t1) ^ tmp;
397 static void gen_add16(TCGv t0, TCGv t1)
399 TCGv tmp = new_tmp();
400 tcg_gen_xor_i32(tmp, t0, t1);
401 tcg_gen_andi_i32(tmp, tmp, 0x8000);
402 tcg_gen_andi_i32(t0, t0, ~0x8000);
403 tcg_gen_andi_i32(t1, t1, ~0x8000);
404 tcg_gen_add_i32(t0, t0, t1);
405 tcg_gen_xor_i32(t0, t0, tmp);
406 dead_tmp(tmp);
407 dead_tmp(t1);
410 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
412 /* Set CF to the top bit of var. */
413 static void gen_set_CF_bit31(TCGv var)
415 TCGv tmp = new_tmp();
416 tcg_gen_shri_i32(tmp, var, 31);
417 gen_set_CF(tmp);
418 dead_tmp(tmp);
421 /* Set N and Z flags from var. */
422 static inline void gen_logic_CC(TCGv var)
424 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
425 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
428 /* T0 += T1 + CF. */
429 static void gen_adc_T0_T1(void)
431 TCGv tmp;
432 gen_op_addl_T0_T1();
433 tmp = load_cpu_field(CF);
434 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
435 dead_tmp(tmp);
438 /* dest = T0 + T1 + CF. */
439 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
441 TCGv tmp;
442 tcg_gen_add_i32(dest, t0, t1);
443 tmp = load_cpu_field(CF);
444 tcg_gen_add_i32(dest, dest, tmp);
445 dead_tmp(tmp);
448 /* dest = T0 - T1 + CF - 1. */
449 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
451 TCGv tmp;
452 tcg_gen_sub_i32(dest, t0, t1);
453 tmp = load_cpu_field(CF);
454 tcg_gen_add_i32(dest, dest, tmp);
455 tcg_gen_subi_i32(dest, dest, 1);
456 dead_tmp(tmp);
459 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
460 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
462 /* T0 &= ~T1. Clobbers T1. */
463 /* FIXME: Implement bic natively. */
464 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
466 TCGv tmp = new_tmp();
467 tcg_gen_not_i32(tmp, t1);
468 tcg_gen_and_i32(dest, t0, tmp);
469 dead_tmp(tmp);
471 static inline void gen_op_bicl_T0_T1(void)
473 gen_op_notl_T1();
474 gen_op_andl_T0_T1();
477 /* FIXME: Implement this natively. */
478 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
480 /* FIXME: Implement this natively. */
481 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
483 TCGv tmp;
485 if (i == 0)
486 return;
488 tmp = new_tmp();
489 tcg_gen_shri_i32(tmp, t1, i);
490 tcg_gen_shli_i32(t1, t1, 32 - i);
491 tcg_gen_or_i32(t0, t1, tmp);
492 dead_tmp(tmp);
495 static void shifter_out_im(TCGv var, int shift)
497 TCGv tmp = new_tmp();
498 if (shift == 0) {
499 tcg_gen_andi_i32(tmp, var, 1);
500 } else {
501 tcg_gen_shri_i32(tmp, var, shift);
502 if (shift != 31)
503 tcg_gen_andi_i32(tmp, tmp, 1);
505 gen_set_CF(tmp);
506 dead_tmp(tmp);
509 /* Shift by immediate. Includes special handling for shift == 0. */
510 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
512 switch (shiftop) {
513 case 0: /* LSL */
514 if (shift != 0) {
515 if (flags)
516 shifter_out_im(var, 32 - shift);
517 tcg_gen_shli_i32(var, var, shift);
519 break;
520 case 1: /* LSR */
521 if (shift == 0) {
522 if (flags) {
523 tcg_gen_shri_i32(var, var, 31);
524 gen_set_CF(var);
526 tcg_gen_movi_i32(var, 0);
527 } else {
528 if (flags)
529 shifter_out_im(var, shift - 1);
530 tcg_gen_shri_i32(var, var, shift);
532 break;
533 case 2: /* ASR */
534 if (shift == 0)
535 shift = 32;
536 if (flags)
537 shifter_out_im(var, shift - 1);
538 if (shift == 32)
539 shift = 31;
540 tcg_gen_sari_i32(var, var, shift);
541 break;
542 case 3: /* ROR/RRX */
543 if (shift != 0) {
544 if (flags)
545 shifter_out_im(var, shift - 1);
546 tcg_gen_rori_i32(var, var, shift); break;
547 } else {
548 TCGv tmp = load_cpu_field(CF);
549 if (flags)
550 shifter_out_im(var, 0);
551 tcg_gen_shri_i32(var, var, 1);
552 tcg_gen_shli_i32(tmp, tmp, 31);
553 tcg_gen_or_i32(var, var, tmp);
554 dead_tmp(tmp);
559 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
560 TCGv shift, int flags)
562 if (flags) {
563 switch (shiftop) {
564 case 0: gen_helper_shl_cc(var, var, shift); break;
565 case 1: gen_helper_shr_cc(var, var, shift); break;
566 case 2: gen_helper_sar_cc(var, var, shift); break;
567 case 3: gen_helper_ror_cc(var, var, shift); break;
569 } else {
570 switch (shiftop) {
571 case 0: gen_helper_shl(var, var, shift); break;
572 case 1: gen_helper_shr(var, var, shift); break;
573 case 2: gen_helper_sar(var, var, shift); break;
574 case 3: gen_helper_ror(var, var, shift); break;
577 dead_tmp(shift);
580 #define PAS_OP(pfx) \
581 switch (op2) { \
582 case 0: gen_pas_helper(glue(pfx,add16)); break; \
583 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
584 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
585 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
586 case 4: gen_pas_helper(glue(pfx,add8)); break; \
587 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
589 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
591 TCGv_ptr tmp;
593 switch (op1) {
594 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
595 case 1:
596 tmp = tcg_temp_new_ptr();
597 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
598 PAS_OP(s)
599 break;
600 case 5:
601 tmp = tcg_temp_new_ptr();
602 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
603 PAS_OP(u)
604 break;
605 #undef gen_pas_helper
606 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
607 case 2:
608 PAS_OP(q);
609 break;
610 case 3:
611 PAS_OP(sh);
612 break;
613 case 6:
614 PAS_OP(uq);
615 break;
616 case 7:
617 PAS_OP(uh);
618 break;
619 #undef gen_pas_helper
622 #undef PAS_OP
624 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
625 #define PAS_OP(pfx) \
626 switch (op2) { \
627 case 0: gen_pas_helper(glue(pfx,add8)); break; \
628 case 1: gen_pas_helper(glue(pfx,add16)); break; \
629 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
630 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
631 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
632 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
634 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
636 TCGv_ptr tmp;
638 switch (op1) {
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
640 case 0:
641 tmp = tcg_temp_new_ptr();
642 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
643 PAS_OP(s)
644 break;
645 case 4:
646 tmp = tcg_temp_new_ptr();
647 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
648 PAS_OP(u)
649 break;
650 #undef gen_pas_helper
651 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
652 case 1:
653 PAS_OP(q);
654 break;
655 case 2:
656 PAS_OP(sh);
657 break;
658 case 5:
659 PAS_OP(uq);
660 break;
661 case 6:
662 PAS_OP(uh);
663 break;
664 #undef gen_pas_helper
667 #undef PAS_OP
669 static void gen_test_cc(int cc, int label)
671 TCGv tmp;
672 TCGv tmp2;
673 int inv;
675 switch (cc) {
676 case 0: /* eq: Z */
677 tmp = load_cpu_field(ZF);
678 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
679 break;
680 case 1: /* ne: !Z */
681 tmp = load_cpu_field(ZF);
682 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
683 break;
684 case 2: /* cs: C */
685 tmp = load_cpu_field(CF);
686 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
687 break;
688 case 3: /* cc: !C */
689 tmp = load_cpu_field(CF);
690 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
691 break;
692 case 4: /* mi: N */
693 tmp = load_cpu_field(NF);
694 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
695 break;
696 case 5: /* pl: !N */
697 tmp = load_cpu_field(NF);
698 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
699 break;
700 case 6: /* vs: V */
701 tmp = load_cpu_field(VF);
702 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
703 break;
704 case 7: /* vc: !V */
705 tmp = load_cpu_field(VF);
706 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
707 break;
708 case 8: /* hi: C && !Z */
709 inv = gen_new_label();
710 tmp = load_cpu_field(CF);
711 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
712 dead_tmp(tmp);
713 tmp = load_cpu_field(ZF);
714 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
715 gen_set_label(inv);
716 break;
717 case 9: /* ls: !C || Z */
718 tmp = load_cpu_field(CF);
719 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
720 dead_tmp(tmp);
721 tmp = load_cpu_field(ZF);
722 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
723 break;
724 case 10: /* ge: N == V -> N ^ V == 0 */
725 tmp = load_cpu_field(VF);
726 tmp2 = load_cpu_field(NF);
727 tcg_gen_xor_i32(tmp, tmp, tmp2);
728 dead_tmp(tmp2);
729 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
730 break;
731 case 11: /* lt: N != V -> N ^ V != 0 */
732 tmp = load_cpu_field(VF);
733 tmp2 = load_cpu_field(NF);
734 tcg_gen_xor_i32(tmp, tmp, tmp2);
735 dead_tmp(tmp2);
736 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
737 break;
738 case 12: /* gt: !Z && N == V */
739 inv = gen_new_label();
740 tmp = load_cpu_field(ZF);
741 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
742 dead_tmp(tmp);
743 tmp = load_cpu_field(VF);
744 tmp2 = load_cpu_field(NF);
745 tcg_gen_xor_i32(tmp, tmp, tmp2);
746 dead_tmp(tmp2);
747 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
748 gen_set_label(inv);
749 break;
750 case 13: /* le: Z || N != V */
751 tmp = load_cpu_field(ZF);
752 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
753 dead_tmp(tmp);
754 tmp = load_cpu_field(VF);
755 tmp2 = load_cpu_field(NF);
756 tcg_gen_xor_i32(tmp, tmp, tmp2);
757 dead_tmp(tmp2);
758 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
759 break;
760 default:
761 fprintf(stderr, "Bad condition code 0x%x\n", cc);
762 abort();
764 dead_tmp(tmp);
767 static const uint8_t table_logic_cc[16] = {
768 1, /* and */
769 1, /* xor */
770 0, /* sub */
771 0, /* rsb */
772 0, /* add */
773 0, /* adc */
774 0, /* sbc */
775 0, /* rsc */
776 1, /* andl */
777 1, /* xorl */
778 0, /* cmp */
779 0, /* cmn */
780 1, /* orr */
781 1, /* mov */
782 1, /* bic */
783 1, /* mvn */
786 /* Set PC and Thumb state from an immediate address. */
787 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
789 TCGv tmp;
791 s->is_jmp = DISAS_UPDATE;
792 tmp = new_tmp();
793 if (s->thumb != (addr & 1)) {
794 tcg_gen_movi_i32(tmp, addr & 1);
795 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
797 tcg_gen_movi_i32(tmp, addr & ~1);
798 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
799 dead_tmp(tmp);
802 /* Set PC and Thumb state from var. var is marked as dead. */
803 static inline void gen_bx(DisasContext *s, TCGv var)
805 TCGv tmp;
807 s->is_jmp = DISAS_UPDATE;
808 tmp = new_tmp();
809 tcg_gen_andi_i32(tmp, var, 1);
810 store_cpu_field(tmp, thumb);
811 tcg_gen_andi_i32(var, var, ~1);
812 store_cpu_field(var, regs[15]);
815 /* TODO: This should be removed. Use gen_bx instead. */
816 static inline void gen_bx_T0(DisasContext *s)
818 TCGv tmp = new_tmp();
819 tcg_gen_mov_i32(tmp, cpu_T[0]);
820 gen_bx(s, tmp);
823 /* Variant of store_reg which uses branch&exchange logic when storing
824 to r15 in ARM architecture v7 and above. The source must be a temporary
825 and will be marked as dead. */
826 static inline void store_reg_bx(CPUState *env, DisasContext *s,
827 int reg, TCGv var)
829 if (reg == 15 && ENABLE_ARCH_7) {
830 gen_bx(s, var);
831 } else {
832 store_reg(s, reg, var);
836 static inline TCGv gen_ld8s(TCGv addr, int index)
838 TCGv tmp = new_tmp();
839 tcg_gen_qemu_ld8s(tmp, addr, index);
840 return tmp;
842 static inline TCGv gen_ld8u(TCGv addr, int index)
844 TCGv tmp = new_tmp();
845 tcg_gen_qemu_ld8u(tmp, addr, index);
846 return tmp;
848 static inline TCGv gen_ld16s(TCGv addr, int index)
850 TCGv tmp = new_tmp();
851 tcg_gen_qemu_ld16s(tmp, addr, index);
852 return tmp;
854 static inline TCGv gen_ld16u(TCGv addr, int index)
856 TCGv tmp = new_tmp();
857 tcg_gen_qemu_ld16u(tmp, addr, index);
858 return tmp;
860 static inline TCGv gen_ld32(TCGv addr, int index)
862 TCGv tmp = new_tmp();
863 tcg_gen_qemu_ld32u(tmp, addr, index);
864 return tmp;
866 static inline void gen_st8(TCGv val, TCGv addr, int index)
868 tcg_gen_qemu_st8(val, addr, index);
869 dead_tmp(val);
871 static inline void gen_st16(TCGv val, TCGv addr, int index)
873 tcg_gen_qemu_st16(val, addr, index);
874 dead_tmp(val);
876 static inline void gen_st32(TCGv val, TCGv addr, int index)
878 tcg_gen_qemu_st32(val, addr, index);
879 dead_tmp(val);
882 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
884 load_reg_var(s, cpu_T[0], reg);
887 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
889 load_reg_var(s, cpu_T[1], reg);
892 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
894 load_reg_var(s, cpu_T[2], reg);
897 static inline void gen_set_pc_im(uint32_t val)
899 TCGv tmp = new_tmp();
900 tcg_gen_movi_i32(tmp, val);
901 store_cpu_field(tmp, regs[15]);
904 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
906 TCGv tmp;
907 if (reg == 15) {
908 tmp = new_tmp();
909 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
910 } else {
911 tmp = cpu_T[t];
913 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
914 if (reg == 15) {
915 dead_tmp(tmp);
916 s->is_jmp = DISAS_JUMP;
920 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
922 gen_movl_reg_TN(s, reg, 0);
925 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
927 gen_movl_reg_TN(s, reg, 1);
930 /* Force a TB lookup after an instruction that changes the CPU state. */
931 static inline void gen_lookup_tb(DisasContext *s)
933 gen_op_movl_T0_im(s->pc);
934 gen_movl_reg_T0(s, 15);
935 s->is_jmp = DISAS_UPDATE;
938 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
939 TCGv var)
941 int val, rm, shift, shiftop;
942 TCGv offset;
944 if (!(insn & (1 << 25))) {
945 /* immediate */
946 val = insn & 0xfff;
947 if (!(insn & (1 << 23)))
948 val = -val;
949 if (val != 0)
950 tcg_gen_addi_i32(var, var, val);
951 } else {
952 /* shift/register */
953 rm = (insn) & 0xf;
954 shift = (insn >> 7) & 0x1f;
955 shiftop = (insn >> 5) & 3;
956 offset = load_reg(s, rm);
957 gen_arm_shift_im(offset, shiftop, shift, 0);
958 if (!(insn & (1 << 23)))
959 tcg_gen_sub_i32(var, var, offset);
960 else
961 tcg_gen_add_i32(var, var, offset);
962 dead_tmp(offset);
966 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
967 int extra, TCGv var)
969 int val, rm;
970 TCGv offset;
972 if (insn & (1 << 22)) {
973 /* immediate */
974 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
975 if (!(insn & (1 << 23)))
976 val = -val;
977 val += extra;
978 if (val != 0)
979 tcg_gen_addi_i32(var, var, val);
980 } else {
981 /* register */
982 if (extra)
983 tcg_gen_addi_i32(var, var, extra);
984 rm = (insn) & 0xf;
985 offset = load_reg(s, rm);
986 if (!(insn & (1 << 23)))
987 tcg_gen_sub_i32(var, var, offset);
988 else
989 tcg_gen_add_i32(var, var, offset);
990 dead_tmp(offset);
994 #define VFP_OP2(name) \
995 static inline void gen_vfp_##name(int dp) \
997 if (dp) \
998 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
999 else \
1000 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1003 VFP_OP2(add)
1004 VFP_OP2(sub)
1005 VFP_OP2(mul)
1006 VFP_OP2(div)
1008 #undef VFP_OP2
1010 static inline void gen_vfp_abs(int dp)
1012 if (dp)
1013 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1014 else
1015 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1018 static inline void gen_vfp_neg(int dp)
1020 if (dp)
1021 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1022 else
1023 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1026 static inline void gen_vfp_sqrt(int dp)
1028 if (dp)
1029 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1030 else
1031 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1034 static inline void gen_vfp_cmp(int dp)
1036 if (dp)
1037 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1038 else
1039 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1042 static inline void gen_vfp_cmpe(int dp)
1044 if (dp)
1045 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1046 else
1047 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1050 static inline void gen_vfp_F1_ld0(int dp)
1052 if (dp)
1053 tcg_gen_movi_i64(cpu_F1d, 0);
1054 else
1055 tcg_gen_movi_i32(cpu_F1s, 0);
1058 static inline void gen_vfp_uito(int dp)
1060 if (dp)
1061 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1062 else
1063 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1066 static inline void gen_vfp_sito(int dp)
1068 if (dp)
1069 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1070 else
1071 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1074 static inline void gen_vfp_toui(int dp)
1076 if (dp)
1077 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1078 else
1079 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1082 static inline void gen_vfp_touiz(int dp)
1084 if (dp)
1085 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1086 else
1087 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1090 static inline void gen_vfp_tosi(int dp)
1092 if (dp)
1093 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1094 else
1095 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1098 static inline void gen_vfp_tosiz(int dp)
1100 if (dp)
1101 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1102 else
1103 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1106 #define VFP_GEN_FIX(name) \
1107 static inline void gen_vfp_##name(int dp, int shift) \
1109 if (dp) \
1110 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1111 else \
1112 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1114 VFP_GEN_FIX(tosh)
1115 VFP_GEN_FIX(tosl)
1116 VFP_GEN_FIX(touh)
1117 VFP_GEN_FIX(toul)
1118 VFP_GEN_FIX(shto)
1119 VFP_GEN_FIX(slto)
1120 VFP_GEN_FIX(uhto)
1121 VFP_GEN_FIX(ulto)
1122 #undef VFP_GEN_FIX
1124 static inline void gen_vfp_ld(DisasContext *s, int dp)
1126 if (dp)
1127 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1128 else
1129 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1132 static inline void gen_vfp_st(DisasContext *s, int dp)
1134 if (dp)
1135 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1136 else
1137 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1140 static inline long
1141 vfp_reg_offset (int dp, int reg)
1143 if (dp)
1144 return offsetof(CPUARMState, vfp.regs[reg]);
1145 else if (reg & 1) {
1146 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1147 + offsetof(CPU_DoubleU, l.upper);
1148 } else {
1149 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1150 + offsetof(CPU_DoubleU, l.lower);
1154 /* Return the offset of a 32-bit piece of a NEON register.
1155 zero is the least significant end of the register. */
1156 static inline long
1157 neon_reg_offset (int reg, int n)
1159 int sreg;
1160 sreg = reg * 2 + n;
1161 return vfp_reg_offset(0, sreg);
1164 /* FIXME: Remove these. */
1165 #define neon_T0 cpu_T[0]
1166 #define neon_T1 cpu_T[1]
1167 #define NEON_GET_REG(T, reg, n) \
1168 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1169 #define NEON_SET_REG(T, reg, n) \
1170 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1172 static TCGv neon_load_reg(int reg, int pass)
1174 TCGv tmp = new_tmp();
1175 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1176 return tmp;
1179 static void neon_store_reg(int reg, int pass, TCGv var)
1181 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1182 dead_tmp(var);
1185 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1187 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1190 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1192 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1195 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1196 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1197 #define tcg_gen_st_f32 tcg_gen_st_i32
1198 #define tcg_gen_st_f64 tcg_gen_st_i64
1200 static inline void gen_mov_F0_vreg(int dp, int reg)
1202 if (dp)
1203 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1204 else
1205 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1208 static inline void gen_mov_F1_vreg(int dp, int reg)
1210 if (dp)
1211 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1212 else
1213 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1216 static inline void gen_mov_vreg_F0(int dp, int reg)
1218 if (dp)
1219 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1220 else
1221 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1224 #define ARM_CP_RW_BIT (1 << 20)
1226 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1228 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1231 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1233 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1236 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1238 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1241 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1243 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1246 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1248 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1251 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1253 iwmmxt_store_reg(cpu_M0, rn);
1256 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1258 iwmmxt_load_reg(cpu_M0, rn);
1261 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1263 iwmmxt_load_reg(cpu_V1, rn);
1264 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1267 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1269 iwmmxt_load_reg(cpu_V1, rn);
1270 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1273 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1275 iwmmxt_load_reg(cpu_V1, rn);
1276 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1279 #define IWMMXT_OP(name) \
1280 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1282 iwmmxt_load_reg(cpu_V1, rn); \
1283 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1286 #define IWMMXT_OP_ENV(name) \
1287 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1289 iwmmxt_load_reg(cpu_V1, rn); \
1290 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1293 #define IWMMXT_OP_ENV_SIZE(name) \
1294 IWMMXT_OP_ENV(name##b) \
1295 IWMMXT_OP_ENV(name##w) \
1296 IWMMXT_OP_ENV(name##l)
1298 #define IWMMXT_OP_ENV1(name) \
1299 static inline void gen_op_iwmmxt_##name##_M0(void) \
1301 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1304 IWMMXT_OP(maddsq)
1305 IWMMXT_OP(madduq)
1306 IWMMXT_OP(sadb)
1307 IWMMXT_OP(sadw)
1308 IWMMXT_OP(mulslw)
1309 IWMMXT_OP(mulshw)
1310 IWMMXT_OP(mululw)
1311 IWMMXT_OP(muluhw)
1312 IWMMXT_OP(macsw)
1313 IWMMXT_OP(macuw)
1315 IWMMXT_OP_ENV_SIZE(unpackl)
1316 IWMMXT_OP_ENV_SIZE(unpackh)
1318 IWMMXT_OP_ENV1(unpacklub)
1319 IWMMXT_OP_ENV1(unpackluw)
1320 IWMMXT_OP_ENV1(unpacklul)
1321 IWMMXT_OP_ENV1(unpackhub)
1322 IWMMXT_OP_ENV1(unpackhuw)
1323 IWMMXT_OP_ENV1(unpackhul)
1324 IWMMXT_OP_ENV1(unpacklsb)
1325 IWMMXT_OP_ENV1(unpacklsw)
1326 IWMMXT_OP_ENV1(unpacklsl)
1327 IWMMXT_OP_ENV1(unpackhsb)
1328 IWMMXT_OP_ENV1(unpackhsw)
1329 IWMMXT_OP_ENV1(unpackhsl)
1331 IWMMXT_OP_ENV_SIZE(cmpeq)
1332 IWMMXT_OP_ENV_SIZE(cmpgtu)
1333 IWMMXT_OP_ENV_SIZE(cmpgts)
1335 IWMMXT_OP_ENV_SIZE(mins)
1336 IWMMXT_OP_ENV_SIZE(minu)
1337 IWMMXT_OP_ENV_SIZE(maxs)
1338 IWMMXT_OP_ENV_SIZE(maxu)
1340 IWMMXT_OP_ENV_SIZE(subn)
1341 IWMMXT_OP_ENV_SIZE(addn)
1342 IWMMXT_OP_ENV_SIZE(subu)
1343 IWMMXT_OP_ENV_SIZE(addu)
1344 IWMMXT_OP_ENV_SIZE(subs)
1345 IWMMXT_OP_ENV_SIZE(adds)
1347 IWMMXT_OP_ENV(avgb0)
1348 IWMMXT_OP_ENV(avgb1)
1349 IWMMXT_OP_ENV(avgw0)
1350 IWMMXT_OP_ENV(avgw1)
1352 IWMMXT_OP(msadb)
1354 IWMMXT_OP_ENV(packuw)
1355 IWMMXT_OP_ENV(packul)
1356 IWMMXT_OP_ENV(packuq)
1357 IWMMXT_OP_ENV(packsw)
1358 IWMMXT_OP_ENV(packsl)
1359 IWMMXT_OP_ENV(packsq)
1361 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1363 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1366 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1368 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1371 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1373 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1376 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1378 iwmmxt_load_reg(cpu_V1, rn);
1379 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1382 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1384 TCGv tmp = tcg_const_i32(shift);
1385 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1388 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1390 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1391 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1392 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1395 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1397 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1398 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1399 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1402 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1404 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1405 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1406 if (mask != ~0u)
1407 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1410 static void gen_op_iwmmxt_set_mup(void)
1412 TCGv tmp;
1413 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1414 tcg_gen_ori_i32(tmp, tmp, 2);
1415 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1418 static void gen_op_iwmmxt_set_cup(void)
1420 TCGv tmp;
1421 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1422 tcg_gen_ori_i32(tmp, tmp, 1);
1423 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1426 static void gen_op_iwmmxt_setpsr_nz(void)
1428 TCGv tmp = new_tmp();
1429 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1430 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1433 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1435 iwmmxt_load_reg(cpu_V1, rn);
1436 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1437 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1441 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1443 iwmmxt_load_reg(cpu_V0, rn);
1444 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1445 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1446 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1449 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1451 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1452 iwmmxt_store_reg(cpu_V0, rn);
1455 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1457 int rd;
1458 uint32_t offset;
1460 rd = (insn >> 16) & 0xf;
1461 gen_movl_T1_reg(s, rd);
1463 offset = (insn & 0xff) << ((insn >> 7) & 2);
1464 if (insn & (1 << 24)) {
1465 /* Pre indexed */
1466 if (insn & (1 << 23))
1467 gen_op_addl_T1_im(offset);
1468 else
1469 gen_op_addl_T1_im(-offset);
1471 if (insn & (1 << 21))
1472 gen_movl_reg_T1(s, rd);
1473 } else if (insn & (1 << 21)) {
1474 /* Post indexed */
1475 if (insn & (1 << 23))
1476 gen_op_movl_T0_im(offset);
1477 else
1478 gen_op_movl_T0_im(- offset);
1479 gen_op_addl_T0_T1();
1480 gen_movl_reg_T0(s, rd);
1481 } else if (!(insn & (1 << 23)))
1482 return 1;
1483 return 0;
1486 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1488 int rd = (insn >> 0) & 0xf;
1490 if (insn & (1 << 8))
1491 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1492 return 1;
1493 else
1494 gen_op_iwmmxt_movl_T0_wCx(rd);
1495 else
1496 gen_iwmmxt_movl_T0_T1_wRn(rd);
1498 gen_op_movl_T1_im(mask);
1499 gen_op_andl_T0_T1();
1500 return 0;
1503 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1504 (ie. an undefined instruction). */
1505 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1507 int rd, wrd;
1508 int rdhi, rdlo, rd0, rd1, i;
1509 TCGv tmp;
1511 if ((insn & 0x0e000e00) == 0x0c000000) {
1512 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1513 wrd = insn & 0xf;
1514 rdlo = (insn >> 12) & 0xf;
1515 rdhi = (insn >> 16) & 0xf;
1516 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1517 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1518 gen_movl_reg_T0(s, rdlo);
1519 gen_movl_reg_T1(s, rdhi);
1520 } else { /* TMCRR */
1521 gen_movl_T0_reg(s, rdlo);
1522 gen_movl_T1_reg(s, rdhi);
1523 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1524 gen_op_iwmmxt_set_mup();
1526 return 0;
1529 wrd = (insn >> 12) & 0xf;
1530 if (gen_iwmmxt_address(s, insn))
1531 return 1;
1532 if (insn & ARM_CP_RW_BIT) {
1533 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1534 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1535 tcg_gen_mov_i32(cpu_T[0], tmp);
1536 dead_tmp(tmp);
1537 gen_op_iwmmxt_movl_wCx_T0(wrd);
1538 } else {
1539 i = 1;
1540 if (insn & (1 << 8)) {
1541 if (insn & (1 << 22)) { /* WLDRD */
1542 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1543 i = 0;
1544 } else { /* WLDRW wRd */
1545 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1547 } else {
1548 if (insn & (1 << 22)) { /* WLDRH */
1549 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1550 } else { /* WLDRB */
1551 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1554 if (i) {
1555 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1556 dead_tmp(tmp);
1558 gen_op_iwmmxt_movq_wRn_M0(wrd);
1560 } else {
1561 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1562 gen_op_iwmmxt_movl_T0_wCx(wrd);
1563 tmp = new_tmp();
1564 tcg_gen_mov_i32(tmp, cpu_T[0]);
1565 gen_st32(tmp, cpu_T[1], IS_USER(s));
1566 } else {
1567 gen_op_iwmmxt_movq_M0_wRn(wrd);
1568 tmp = new_tmp();
1569 if (insn & (1 << 8)) {
1570 if (insn & (1 << 22)) { /* WSTRD */
1571 dead_tmp(tmp);
1572 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1573 } else { /* WSTRW wRd */
1574 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1575 gen_st32(tmp, cpu_T[1], IS_USER(s));
1577 } else {
1578 if (insn & (1 << 22)) { /* WSTRH */
1579 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1580 gen_st16(tmp, cpu_T[1], IS_USER(s));
1581 } else { /* WSTRB */
1582 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1583 gen_st8(tmp, cpu_T[1], IS_USER(s));
1588 return 0;
1591 if ((insn & 0x0f000000) != 0x0e000000)
1592 return 1;
1594 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1595 case 0x000: /* WOR */
1596 wrd = (insn >> 12) & 0xf;
1597 rd0 = (insn >> 0) & 0xf;
1598 rd1 = (insn >> 16) & 0xf;
1599 gen_op_iwmmxt_movq_M0_wRn(rd0);
1600 gen_op_iwmmxt_orq_M0_wRn(rd1);
1601 gen_op_iwmmxt_setpsr_nz();
1602 gen_op_iwmmxt_movq_wRn_M0(wrd);
1603 gen_op_iwmmxt_set_mup();
1604 gen_op_iwmmxt_set_cup();
1605 break;
1606 case 0x011: /* TMCR */
1607 if (insn & 0xf)
1608 return 1;
1609 rd = (insn >> 12) & 0xf;
1610 wrd = (insn >> 16) & 0xf;
1611 switch (wrd) {
1612 case ARM_IWMMXT_wCID:
1613 case ARM_IWMMXT_wCASF:
1614 break;
1615 case ARM_IWMMXT_wCon:
1616 gen_op_iwmmxt_set_cup();
1617 /* Fall through. */
1618 case ARM_IWMMXT_wCSSF:
1619 gen_op_iwmmxt_movl_T0_wCx(wrd);
1620 gen_movl_T1_reg(s, rd);
1621 gen_op_bicl_T0_T1();
1622 gen_op_iwmmxt_movl_wCx_T0(wrd);
1623 break;
1624 case ARM_IWMMXT_wCGR0:
1625 case ARM_IWMMXT_wCGR1:
1626 case ARM_IWMMXT_wCGR2:
1627 case ARM_IWMMXT_wCGR3:
1628 gen_op_iwmmxt_set_cup();
1629 gen_movl_reg_T0(s, rd);
1630 gen_op_iwmmxt_movl_wCx_T0(wrd);
1631 break;
1632 default:
1633 return 1;
1635 break;
1636 case 0x100: /* WXOR */
1637 wrd = (insn >> 12) & 0xf;
1638 rd0 = (insn >> 0) & 0xf;
1639 rd1 = (insn >> 16) & 0xf;
1640 gen_op_iwmmxt_movq_M0_wRn(rd0);
1641 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1642 gen_op_iwmmxt_setpsr_nz();
1643 gen_op_iwmmxt_movq_wRn_M0(wrd);
1644 gen_op_iwmmxt_set_mup();
1645 gen_op_iwmmxt_set_cup();
1646 break;
1647 case 0x111: /* TMRC */
1648 if (insn & 0xf)
1649 return 1;
1650 rd = (insn >> 12) & 0xf;
1651 wrd = (insn >> 16) & 0xf;
1652 gen_op_iwmmxt_movl_T0_wCx(wrd);
1653 gen_movl_reg_T0(s, rd);
1654 break;
1655 case 0x300: /* WANDN */
1656 wrd = (insn >> 12) & 0xf;
1657 rd0 = (insn >> 0) & 0xf;
1658 rd1 = (insn >> 16) & 0xf;
1659 gen_op_iwmmxt_movq_M0_wRn(rd0);
1660 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1661 gen_op_iwmmxt_andq_M0_wRn(rd1);
1662 gen_op_iwmmxt_setpsr_nz();
1663 gen_op_iwmmxt_movq_wRn_M0(wrd);
1664 gen_op_iwmmxt_set_mup();
1665 gen_op_iwmmxt_set_cup();
1666 break;
1667 case 0x200: /* WAND */
1668 wrd = (insn >> 12) & 0xf;
1669 rd0 = (insn >> 0) & 0xf;
1670 rd1 = (insn >> 16) & 0xf;
1671 gen_op_iwmmxt_movq_M0_wRn(rd0);
1672 gen_op_iwmmxt_andq_M0_wRn(rd1);
1673 gen_op_iwmmxt_setpsr_nz();
1674 gen_op_iwmmxt_movq_wRn_M0(wrd);
1675 gen_op_iwmmxt_set_mup();
1676 gen_op_iwmmxt_set_cup();
1677 break;
1678 case 0x810: case 0xa10: /* WMADD */
1679 wrd = (insn >> 12) & 0xf;
1680 rd0 = (insn >> 0) & 0xf;
1681 rd1 = (insn >> 16) & 0xf;
1682 gen_op_iwmmxt_movq_M0_wRn(rd0);
1683 if (insn & (1 << 21))
1684 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1685 else
1686 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1687 gen_op_iwmmxt_movq_wRn_M0(wrd);
1688 gen_op_iwmmxt_set_mup();
1689 break;
1690 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1691 wrd = (insn >> 12) & 0xf;
1692 rd0 = (insn >> 16) & 0xf;
1693 rd1 = (insn >> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0);
1695 switch ((insn >> 22) & 3) {
1696 case 0:
1697 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1698 break;
1699 case 1:
1700 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1701 break;
1702 case 2:
1703 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1704 break;
1705 case 3:
1706 return 1;
1708 gen_op_iwmmxt_movq_wRn_M0(wrd);
1709 gen_op_iwmmxt_set_mup();
1710 gen_op_iwmmxt_set_cup();
1711 break;
1712 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1713 wrd = (insn >> 12) & 0xf;
1714 rd0 = (insn >> 16) & 0xf;
1715 rd1 = (insn >> 0) & 0xf;
1716 gen_op_iwmmxt_movq_M0_wRn(rd0);
1717 switch ((insn >> 22) & 3) {
1718 case 0:
1719 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1720 break;
1721 case 1:
1722 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1723 break;
1724 case 2:
1725 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1726 break;
1727 case 3:
1728 return 1;
1730 gen_op_iwmmxt_movq_wRn_M0(wrd);
1731 gen_op_iwmmxt_set_mup();
1732 gen_op_iwmmxt_set_cup();
1733 break;
1734 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1735 wrd = (insn >> 12) & 0xf;
1736 rd0 = (insn >> 16) & 0xf;
1737 rd1 = (insn >> 0) & 0xf;
1738 gen_op_iwmmxt_movq_M0_wRn(rd0);
1739 if (insn & (1 << 22))
1740 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1741 else
1742 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1743 if (!(insn & (1 << 20)))
1744 gen_op_iwmmxt_addl_M0_wRn(wrd);
1745 gen_op_iwmmxt_movq_wRn_M0(wrd);
1746 gen_op_iwmmxt_set_mup();
1747 break;
1748 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1749 wrd = (insn >> 12) & 0xf;
1750 rd0 = (insn >> 16) & 0xf;
1751 rd1 = (insn >> 0) & 0xf;
1752 gen_op_iwmmxt_movq_M0_wRn(rd0);
1753 if (insn & (1 << 21)) {
1754 if (insn & (1 << 20))
1755 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1756 else
1757 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1758 } else {
1759 if (insn & (1 << 20))
1760 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1761 else
1762 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1764 gen_op_iwmmxt_movq_wRn_M0(wrd);
1765 gen_op_iwmmxt_set_mup();
1766 break;
1767 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1768 wrd = (insn >> 12) & 0xf;
1769 rd0 = (insn >> 16) & 0xf;
1770 rd1 = (insn >> 0) & 0xf;
1771 gen_op_iwmmxt_movq_M0_wRn(rd0);
1772 if (insn & (1 << 21))
1773 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1774 else
1775 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1776 if (!(insn & (1 << 20))) {
1777 iwmmxt_load_reg(cpu_V1, wrd);
1778 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd);
1781 gen_op_iwmmxt_set_mup();
1782 break;
1783 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1784 wrd = (insn >> 12) & 0xf;
1785 rd0 = (insn >> 16) & 0xf;
1786 rd1 = (insn >> 0) & 0xf;
1787 gen_op_iwmmxt_movq_M0_wRn(rd0);
1788 switch ((insn >> 22) & 3) {
1789 case 0:
1790 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1791 break;
1792 case 1:
1793 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1794 break;
1795 case 2:
1796 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1797 break;
1798 case 3:
1799 return 1;
1801 gen_op_iwmmxt_movq_wRn_M0(wrd);
1802 gen_op_iwmmxt_set_mup();
1803 gen_op_iwmmxt_set_cup();
1804 break;
1805 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1806 wrd = (insn >> 12) & 0xf;
1807 rd0 = (insn >> 16) & 0xf;
1808 rd1 = (insn >> 0) & 0xf;
1809 gen_op_iwmmxt_movq_M0_wRn(rd0);
1810 if (insn & (1 << 22)) {
1811 if (insn & (1 << 20))
1812 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1813 else
1814 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1815 } else {
1816 if (insn & (1 << 20))
1817 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1818 else
1819 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1821 gen_op_iwmmxt_movq_wRn_M0(wrd);
1822 gen_op_iwmmxt_set_mup();
1823 gen_op_iwmmxt_set_cup();
1824 break;
1825 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1826 wrd = (insn >> 12) & 0xf;
1827 rd0 = (insn >> 16) & 0xf;
1828 rd1 = (insn >> 0) & 0xf;
1829 gen_op_iwmmxt_movq_M0_wRn(rd0);
1830 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1831 gen_op_movl_T1_im(7);
1832 gen_op_andl_T0_T1();
1833 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1834 gen_op_iwmmxt_movq_wRn_M0(wrd);
1835 gen_op_iwmmxt_set_mup();
1836 break;
1837 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1838 rd = (insn >> 12) & 0xf;
1839 wrd = (insn >> 16) & 0xf;
1840 gen_movl_T0_reg(s, rd);
1841 gen_op_iwmmxt_movq_M0_wRn(wrd);
1842 switch ((insn >> 6) & 3) {
1843 case 0:
1844 gen_op_movl_T1_im(0xff);
1845 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1846 break;
1847 case 1:
1848 gen_op_movl_T1_im(0xffff);
1849 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1850 break;
1851 case 2:
1852 gen_op_movl_T1_im(0xffffffff);
1853 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1854 break;
1855 case 3:
1856 return 1;
1858 gen_op_iwmmxt_movq_wRn_M0(wrd);
1859 gen_op_iwmmxt_set_mup();
1860 break;
1861 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1862 rd = (insn >> 12) & 0xf;
1863 wrd = (insn >> 16) & 0xf;
1864 if (rd == 15)
1865 return 1;
1866 gen_op_iwmmxt_movq_M0_wRn(wrd);
1867 switch ((insn >> 22) & 3) {
1868 case 0:
1869 if (insn & 8)
1870 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1871 else {
1872 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1874 break;
1875 case 1:
1876 if (insn & 8)
1877 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1878 else {
1879 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1881 break;
1882 case 2:
1883 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1884 break;
1885 case 3:
1886 return 1;
1888 gen_movl_reg_T0(s, rd);
1889 break;
1890 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1891 if ((insn & 0x000ff008) != 0x0003f000)
1892 return 1;
1893 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1894 switch ((insn >> 22) & 3) {
1895 case 0:
1896 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1897 break;
1898 case 1:
1899 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1900 break;
1901 case 2:
1902 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1903 break;
1904 case 3:
1905 return 1;
1907 gen_op_shll_T1_im(28);
1908 gen_set_nzcv(cpu_T[1]);
1909 break;
1910 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1911 rd = (insn >> 12) & 0xf;
1912 wrd = (insn >> 16) & 0xf;
1913 gen_movl_T0_reg(s, rd);
1914 switch ((insn >> 6) & 3) {
1915 case 0:
1916 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1917 break;
1918 case 1:
1919 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1920 break;
1921 case 2:
1922 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1923 break;
1924 case 3:
1925 return 1;
1927 gen_op_iwmmxt_movq_wRn_M0(wrd);
1928 gen_op_iwmmxt_set_mup();
1929 break;
1930 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1931 if ((insn & 0x000ff00f) != 0x0003f000)
1932 return 1;
1933 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1934 switch ((insn >> 22) & 3) {
1935 case 0:
1936 for (i = 0; i < 7; i ++) {
1937 gen_op_shll_T1_im(4);
1938 gen_op_andl_T0_T1();
1940 break;
1941 case 1:
1942 for (i = 0; i < 3; i ++) {
1943 gen_op_shll_T1_im(8);
1944 gen_op_andl_T0_T1();
1946 break;
1947 case 2:
1948 gen_op_shll_T1_im(16);
1949 gen_op_andl_T0_T1();
1950 break;
1951 case 3:
1952 return 1;
1954 gen_set_nzcv(cpu_T[0]);
1955 break;
1956 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1957 wrd = (insn >> 12) & 0xf;
1958 rd0 = (insn >> 16) & 0xf;
1959 gen_op_iwmmxt_movq_M0_wRn(rd0);
1960 switch ((insn >> 22) & 3) {
1961 case 0:
1962 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1963 break;
1964 case 1:
1965 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1966 break;
1967 case 2:
1968 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1969 break;
1970 case 3:
1971 return 1;
1973 gen_op_iwmmxt_movq_wRn_M0(wrd);
1974 gen_op_iwmmxt_set_mup();
1975 break;
1976 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1977 if ((insn & 0x000ff00f) != 0x0003f000)
1978 return 1;
1979 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1980 switch ((insn >> 22) & 3) {
1981 case 0:
1982 for (i = 0; i < 7; i ++) {
1983 gen_op_shll_T1_im(4);
1984 gen_op_orl_T0_T1();
1986 break;
1987 case 1:
1988 for (i = 0; i < 3; i ++) {
1989 gen_op_shll_T1_im(8);
1990 gen_op_orl_T0_T1();
1992 break;
1993 case 2:
1994 gen_op_shll_T1_im(16);
1995 gen_op_orl_T0_T1();
1996 break;
1997 case 3:
1998 return 1;
2000 gen_set_nzcv(cpu_T[0]);
2001 break;
2002 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2003 rd = (insn >> 12) & 0xf;
2004 rd0 = (insn >> 16) & 0xf;
2005 if ((insn & 0xf) != 0)
2006 return 1;
2007 gen_op_iwmmxt_movq_M0_wRn(rd0);
2008 switch ((insn >> 22) & 3) {
2009 case 0:
2010 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2011 break;
2012 case 1:
2013 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2014 break;
2015 case 2:
2016 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2017 break;
2018 case 3:
2019 return 1;
2021 gen_movl_reg_T0(s, rd);
2022 break;
2023 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2024 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2025 wrd = (insn >> 12) & 0xf;
2026 rd0 = (insn >> 16) & 0xf;
2027 rd1 = (insn >> 0) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0);
2029 switch ((insn >> 22) & 3) {
2030 case 0:
2031 if (insn & (1 << 21))
2032 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2033 else
2034 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2035 break;
2036 case 1:
2037 if (insn & (1 << 21))
2038 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2039 else
2040 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2041 break;
2042 case 2:
2043 if (insn & (1 << 21))
2044 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2045 else
2046 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2047 break;
2048 case 3:
2049 return 1;
2051 gen_op_iwmmxt_movq_wRn_M0(wrd);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2054 break;
2055 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2056 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2057 wrd = (insn >> 12) & 0xf;
2058 rd0 = (insn >> 16) & 0xf;
2059 gen_op_iwmmxt_movq_M0_wRn(rd0);
2060 switch ((insn >> 22) & 3) {
2061 case 0:
2062 if (insn & (1 << 21))
2063 gen_op_iwmmxt_unpacklsb_M0();
2064 else
2065 gen_op_iwmmxt_unpacklub_M0();
2066 break;
2067 case 1:
2068 if (insn & (1 << 21))
2069 gen_op_iwmmxt_unpacklsw_M0();
2070 else
2071 gen_op_iwmmxt_unpackluw_M0();
2072 break;
2073 case 2:
2074 if (insn & (1 << 21))
2075 gen_op_iwmmxt_unpacklsl_M0();
2076 else
2077 gen_op_iwmmxt_unpacklul_M0();
2078 break;
2079 case 3:
2080 return 1;
2082 gen_op_iwmmxt_movq_wRn_M0(wrd);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2085 break;
2086 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2087 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2088 wrd = (insn >> 12) & 0xf;
2089 rd0 = (insn >> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0);
2091 switch ((insn >> 22) & 3) {
2092 case 0:
2093 if (insn & (1 << 21))
2094 gen_op_iwmmxt_unpackhsb_M0();
2095 else
2096 gen_op_iwmmxt_unpackhub_M0();
2097 break;
2098 case 1:
2099 if (insn & (1 << 21))
2100 gen_op_iwmmxt_unpackhsw_M0();
2101 else
2102 gen_op_iwmmxt_unpackhuw_M0();
2103 break;
2104 case 2:
2105 if (insn & (1 << 21))
2106 gen_op_iwmmxt_unpackhsl_M0();
2107 else
2108 gen_op_iwmmxt_unpackhul_M0();
2109 break;
2110 case 3:
2111 return 1;
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 gen_op_iwmmxt_set_cup();
2116 break;
2117 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2118 case 0x214: case 0x614: case 0xa14: case 0xe14:
2119 wrd = (insn >> 12) & 0xf;
2120 rd0 = (insn >> 16) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0);
2122 if (gen_iwmmxt_shift(insn, 0xff))
2123 return 1;
2124 switch ((insn >> 22) & 3) {
2125 case 0:
2126 return 1;
2127 case 1:
2128 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2129 break;
2130 case 2:
2131 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2132 break;
2133 case 3:
2134 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2135 break;
2137 gen_op_iwmmxt_movq_wRn_M0(wrd);
2138 gen_op_iwmmxt_set_mup();
2139 gen_op_iwmmxt_set_cup();
2140 break;
2141 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2142 case 0x014: case 0x414: case 0x814: case 0xc14:
2143 wrd = (insn >> 12) & 0xf;
2144 rd0 = (insn >> 16) & 0xf;
2145 gen_op_iwmmxt_movq_M0_wRn(rd0);
2146 if (gen_iwmmxt_shift(insn, 0xff))
2147 return 1;
2148 switch ((insn >> 22) & 3) {
2149 case 0:
2150 return 1;
2151 case 1:
2152 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2153 break;
2154 case 2:
2155 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2156 break;
2157 case 3:
2158 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2159 break;
2161 gen_op_iwmmxt_movq_wRn_M0(wrd);
2162 gen_op_iwmmxt_set_mup();
2163 gen_op_iwmmxt_set_cup();
2164 break;
2165 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2166 case 0x114: case 0x514: case 0x914: case 0xd14:
2167 wrd = (insn >> 12) & 0xf;
2168 rd0 = (insn >> 16) & 0xf;
2169 gen_op_iwmmxt_movq_M0_wRn(rd0);
2170 if (gen_iwmmxt_shift(insn, 0xff))
2171 return 1;
2172 switch ((insn >> 22) & 3) {
2173 case 0:
2174 return 1;
2175 case 1:
2176 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2177 break;
2178 case 2:
2179 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2180 break;
2181 case 3:
2182 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2183 break;
2185 gen_op_iwmmxt_movq_wRn_M0(wrd);
2186 gen_op_iwmmxt_set_mup();
2187 gen_op_iwmmxt_set_cup();
2188 break;
2189 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2190 case 0x314: case 0x714: case 0xb14: case 0xf14:
2191 wrd = (insn >> 12) & 0xf;
2192 rd0 = (insn >> 16) & 0xf;
2193 gen_op_iwmmxt_movq_M0_wRn(rd0);
2194 switch ((insn >> 22) & 3) {
2195 case 0:
2196 return 1;
2197 case 1:
2198 if (gen_iwmmxt_shift(insn, 0xf))
2199 return 1;
2200 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2201 break;
2202 case 2:
2203 if (gen_iwmmxt_shift(insn, 0x1f))
2204 return 1;
2205 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2206 break;
2207 case 3:
2208 if (gen_iwmmxt_shift(insn, 0x3f))
2209 return 1;
2210 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2211 break;
2213 gen_op_iwmmxt_movq_wRn_M0(wrd);
2214 gen_op_iwmmxt_set_mup();
2215 gen_op_iwmmxt_set_cup();
2216 break;
2217 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2218 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2219 wrd = (insn >> 12) & 0xf;
2220 rd0 = (insn >> 16) & 0xf;
2221 rd1 = (insn >> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0);
2223 switch ((insn >> 22) & 3) {
2224 case 0:
2225 if (insn & (1 << 21))
2226 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2227 else
2228 gen_op_iwmmxt_minub_M0_wRn(rd1);
2229 break;
2230 case 1:
2231 if (insn & (1 << 21))
2232 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2233 else
2234 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2235 break;
2236 case 2:
2237 if (insn & (1 << 21))
2238 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2239 else
2240 gen_op_iwmmxt_minul_M0_wRn(rd1);
2241 break;
2242 case 3:
2243 return 1;
2245 gen_op_iwmmxt_movq_wRn_M0(wrd);
2246 gen_op_iwmmxt_set_mup();
2247 break;
2248 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2249 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2250 wrd = (insn >> 12) & 0xf;
2251 rd0 = (insn >> 16) & 0xf;
2252 rd1 = (insn >> 0) & 0xf;
2253 gen_op_iwmmxt_movq_M0_wRn(rd0);
2254 switch ((insn >> 22) & 3) {
2255 case 0:
2256 if (insn & (1 << 21))
2257 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2258 else
2259 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2260 break;
2261 case 1:
2262 if (insn & (1 << 21))
2263 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2264 else
2265 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2266 break;
2267 case 2:
2268 if (insn & (1 << 21))
2269 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2270 else
2271 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2272 break;
2273 case 3:
2274 return 1;
2276 gen_op_iwmmxt_movq_wRn_M0(wrd);
2277 gen_op_iwmmxt_set_mup();
2278 break;
2279 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2280 case 0x402: case 0x502: case 0x602: case 0x702:
2281 wrd = (insn >> 12) & 0xf;
2282 rd0 = (insn >> 16) & 0xf;
2283 rd1 = (insn >> 0) & 0xf;
2284 gen_op_iwmmxt_movq_M0_wRn(rd0);
2285 gen_op_movl_T0_im((insn >> 20) & 3);
2286 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd);
2288 gen_op_iwmmxt_set_mup();
2289 break;
2290 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2291 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2292 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2293 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2294 wrd = (insn >> 12) & 0xf;
2295 rd0 = (insn >> 16) & 0xf;
2296 rd1 = (insn >> 0) & 0xf;
2297 gen_op_iwmmxt_movq_M0_wRn(rd0);
2298 switch ((insn >> 20) & 0xf) {
2299 case 0x0:
2300 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2301 break;
2302 case 0x1:
2303 gen_op_iwmmxt_subub_M0_wRn(rd1);
2304 break;
2305 case 0x3:
2306 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2307 break;
2308 case 0x4:
2309 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2310 break;
2311 case 0x5:
2312 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2313 break;
2314 case 0x7:
2315 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2316 break;
2317 case 0x8:
2318 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2319 break;
2320 case 0x9:
2321 gen_op_iwmmxt_subul_M0_wRn(rd1);
2322 break;
2323 case 0xb:
2324 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2325 break;
2326 default:
2327 return 1;
2329 gen_op_iwmmxt_movq_wRn_M0(wrd);
2330 gen_op_iwmmxt_set_mup();
2331 gen_op_iwmmxt_set_cup();
2332 break;
2333 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2334 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2335 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2336 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2337 wrd = (insn >> 12) & 0xf;
2338 rd0 = (insn >> 16) & 0xf;
2339 gen_op_iwmmxt_movq_M0_wRn(rd0);
2340 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2341 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2342 gen_op_iwmmxt_movq_wRn_M0(wrd);
2343 gen_op_iwmmxt_set_mup();
2344 gen_op_iwmmxt_set_cup();
2345 break;
2346 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2347 case 0x418: case 0x518: case 0x618: case 0x718:
2348 case 0x818: case 0x918: case 0xa18: case 0xb18:
2349 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2350 wrd = (insn >> 12) & 0xf;
2351 rd0 = (insn >> 16) & 0xf;
2352 rd1 = (insn >> 0) & 0xf;
2353 gen_op_iwmmxt_movq_M0_wRn(rd0);
2354 switch ((insn >> 20) & 0xf) {
2355 case 0x0:
2356 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2357 break;
2358 case 0x1:
2359 gen_op_iwmmxt_addub_M0_wRn(rd1);
2360 break;
2361 case 0x3:
2362 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2363 break;
2364 case 0x4:
2365 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2366 break;
2367 case 0x5:
2368 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2369 break;
2370 case 0x7:
2371 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2372 break;
2373 case 0x8:
2374 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2375 break;
2376 case 0x9:
2377 gen_op_iwmmxt_addul_M0_wRn(rd1);
2378 break;
2379 case 0xb:
2380 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2381 break;
2382 default:
2383 return 1;
2385 gen_op_iwmmxt_movq_wRn_M0(wrd);
2386 gen_op_iwmmxt_set_mup();
2387 gen_op_iwmmxt_set_cup();
2388 break;
2389 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2390 case 0x408: case 0x508: case 0x608: case 0x708:
2391 case 0x808: case 0x908: case 0xa08: case 0xb08:
2392 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2393 wrd = (insn >> 12) & 0xf;
2394 rd0 = (insn >> 16) & 0xf;
2395 rd1 = (insn >> 0) & 0xf;
2396 gen_op_iwmmxt_movq_M0_wRn(rd0);
2397 if (!(insn & (1 << 20)))
2398 return 1;
2399 switch ((insn >> 22) & 3) {
2400 case 0:
2401 return 1;
2402 case 1:
2403 if (insn & (1 << 21))
2404 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2405 else
2406 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2407 break;
2408 case 2:
2409 if (insn & (1 << 21))
2410 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2411 else
2412 gen_op_iwmmxt_packul_M0_wRn(rd1);
2413 break;
2414 case 3:
2415 if (insn & (1 << 21))
2416 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2417 else
2418 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2419 break;
2421 gen_op_iwmmxt_movq_wRn_M0(wrd);
2422 gen_op_iwmmxt_set_mup();
2423 gen_op_iwmmxt_set_cup();
2424 break;
2425 case 0x201: case 0x203: case 0x205: case 0x207:
2426 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2427 case 0x211: case 0x213: case 0x215: case 0x217:
2428 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2429 wrd = (insn >> 5) & 0xf;
2430 rd0 = (insn >> 12) & 0xf;
2431 rd1 = (insn >> 0) & 0xf;
2432 if (rd0 == 0xf || rd1 == 0xf)
2433 return 1;
2434 gen_op_iwmmxt_movq_M0_wRn(wrd);
2435 switch ((insn >> 16) & 0xf) {
2436 case 0x0: /* TMIA */
2437 gen_movl_T0_reg(s, rd0);
2438 gen_movl_T1_reg(s, rd1);
2439 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2440 break;
2441 case 0x8: /* TMIAPH */
2442 gen_movl_T0_reg(s, rd0);
2443 gen_movl_T1_reg(s, rd1);
2444 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2445 break;
2446 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2447 gen_movl_T1_reg(s, rd0);
2448 if (insn & (1 << 16))
2449 gen_op_shrl_T1_im(16);
2450 gen_op_movl_T0_T1();
2451 gen_movl_T1_reg(s, rd1);
2452 if (insn & (1 << 17))
2453 gen_op_shrl_T1_im(16);
2454 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2455 break;
2456 default:
2457 return 1;
2459 gen_op_iwmmxt_movq_wRn_M0(wrd);
2460 gen_op_iwmmxt_set_mup();
2461 break;
2462 default:
2463 return 1;
2466 return 0;
2469 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2470 (ie. an undefined instruction). */
2471 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2473 int acc, rd0, rd1, rdhi, rdlo;
2475 if ((insn & 0x0ff00f10) == 0x0e200010) {
2476 /* Multiply with Internal Accumulate Format */
2477 rd0 = (insn >> 12) & 0xf;
2478 rd1 = insn & 0xf;
2479 acc = (insn >> 5) & 7;
2481 if (acc != 0)
2482 return 1;
2484 switch ((insn >> 16) & 0xf) {
2485 case 0x0: /* MIA */
2486 gen_movl_T0_reg(s, rd0);
2487 gen_movl_T1_reg(s, rd1);
2488 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2489 break;
2490 case 0x8: /* MIAPH */
2491 gen_movl_T0_reg(s, rd0);
2492 gen_movl_T1_reg(s, rd1);
2493 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2494 break;
2495 case 0xc: /* MIABB */
2496 case 0xd: /* MIABT */
2497 case 0xe: /* MIATB */
2498 case 0xf: /* MIATT */
2499 gen_movl_T1_reg(s, rd0);
2500 if (insn & (1 << 16))
2501 gen_op_shrl_T1_im(16);
2502 gen_op_movl_T0_T1();
2503 gen_movl_T1_reg(s, rd1);
2504 if (insn & (1 << 17))
2505 gen_op_shrl_T1_im(16);
2506 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2507 break;
2508 default:
2509 return 1;
2512 gen_op_iwmmxt_movq_wRn_M0(acc);
2513 return 0;
2516 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2517 /* Internal Accumulator Access Format */
2518 rdhi = (insn >> 16) & 0xf;
2519 rdlo = (insn >> 12) & 0xf;
2520 acc = insn & 7;
2522 if (acc != 0)
2523 return 1;
2525 if (insn & ARM_CP_RW_BIT) { /* MRA */
2526 gen_iwmmxt_movl_T0_T1_wRn(acc);
2527 gen_movl_reg_T0(s, rdlo);
2528 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2529 gen_op_andl_T0_T1();
2530 gen_movl_reg_T0(s, rdhi);
2531 } else { /* MAR */
2532 gen_movl_T0_reg(s, rdlo);
2533 gen_movl_T1_reg(s, rdhi);
2534 gen_iwmmxt_movl_wRn_T0_T1(acc);
2536 return 0;
2539 return 1;
2542 /* Disassemble system coprocessor instruction. Return nonzero if
2543 instruction is not defined. */
2544 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2546 TCGv tmp;
2547 uint32_t rd = (insn >> 12) & 0xf;
2548 uint32_t cp = (insn >> 8) & 0xf;
2549 if (IS_USER(s)) {
2550 return 1;
2553 if (insn & ARM_CP_RW_BIT) {
2554 if (!env->cp[cp].cp_read)
2555 return 1;
2556 gen_set_pc_im(s->pc);
2557 tmp = new_tmp();
2558 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2559 store_reg(s, rd, tmp);
2560 } else {
2561 if (!env->cp[cp].cp_write)
2562 return 1;
2563 gen_set_pc_im(s->pc);
2564 tmp = load_reg(s, rd);
2565 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2566 dead_tmp(tmp);
2568 return 0;
2571 static int cp15_user_ok(uint32_t insn)
2573 int cpn = (insn >> 16) & 0xf;
2574 int cpm = insn & 0xf;
2575 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2577 if (cpn == 13 && cpm == 0) {
2578 /* TLS register. */
2579 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2580 return 1;
2582 if (cpn == 7) {
2583 /* ISB, DSB, DMB. */
2584 if ((cpm == 5 && op == 4)
2585 || (cpm == 10 && (op == 4 || op == 5)))
2586 return 1;
2588 return 0;
2591 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2592 instruction is not defined. */
2593 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2595 uint32_t rd;
2596 TCGv tmp;
2598 /* M profile cores use memory mapped registers instead of cp15. */
2599 if (arm_feature(env, ARM_FEATURE_M))
2600 return 1;
2602 if ((insn & (1 << 25)) == 0) {
2603 if (insn & (1 << 20)) {
2604 /* mrrc */
2605 return 1;
2607 /* mcrr. Used for block cache operations, so implement as no-op. */
2608 return 0;
2610 if ((insn & (1 << 4)) == 0) {
2611 /* cdp */
2612 return 1;
2614 if (IS_USER(s) && !cp15_user_ok(insn)) {
2615 return 1;
2617 if ((insn & 0x0fff0fff) == 0x0e070f90
2618 || (insn & 0x0fff0fff) == 0x0e070f58) {
2619 /* Wait for interrupt. */
2620 gen_set_pc_im(s->pc);
2621 s->is_jmp = DISAS_WFI;
2622 return 0;
2624 rd = (insn >> 12) & 0xf;
2625 if (insn & ARM_CP_RW_BIT) {
2626 tmp = new_tmp();
2627 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2628 /* If the destination register is r15 then sets condition codes. */
2629 if (rd != 15)
2630 store_reg(s, rd, tmp);
2631 else
2632 dead_tmp(tmp);
2633 } else {
2634 tmp = load_reg(s, rd);
2635 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2636 dead_tmp(tmp);
2637 /* Normally we would always end the TB here, but Linux
2638 * arch/arm/mach-pxa/sleep.S expects two instructions following
2639 * an MMU enable to execute from cache. Imitate this behaviour. */
2640 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2641 (insn & 0x0fff0fff) != 0x0e010f10)
2642 gen_lookup_tb(s);
2644 return 0;
2647 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2648 #define VFP_SREG(insn, bigbit, smallbit) \
2649 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2650 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2651 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2652 reg = (((insn) >> (bigbit)) & 0x0f) \
2653 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2654 } else { \
2655 if (insn & (1 << (smallbit))) \
2656 return 1; \
2657 reg = ((insn) >> (bigbit)) & 0x0f; \
2658 }} while (0)
2660 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2661 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2662 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2663 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2664 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2665 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2667 /* Move between integer and VFP cores. */
2668 static TCGv gen_vfp_mrs(void)
2670 TCGv tmp = new_tmp();
2671 tcg_gen_mov_i32(tmp, cpu_F0s);
2672 return tmp;
2675 static void gen_vfp_msr(TCGv tmp)
2677 tcg_gen_mov_i32(cpu_F0s, tmp);
2678 dead_tmp(tmp);
2681 static inline int
2682 vfp_enabled(CPUState * env)
2684 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2687 static void gen_neon_dup_u8(TCGv var, int shift)
2689 TCGv tmp = new_tmp();
2690 if (shift)
2691 tcg_gen_shri_i32(var, var, shift);
2692 tcg_gen_ext8u_i32(var, var);
2693 tcg_gen_shli_i32(tmp, var, 8);
2694 tcg_gen_or_i32(var, var, tmp);
2695 tcg_gen_shli_i32(tmp, var, 16);
2696 tcg_gen_or_i32(var, var, tmp);
2697 dead_tmp(tmp);
2700 static void gen_neon_dup_low16(TCGv var)
2702 TCGv tmp = new_tmp();
2703 tcg_gen_ext16u_i32(var, var);
2704 tcg_gen_shli_i32(tmp, var, 16);
2705 tcg_gen_or_i32(var, var, tmp);
2706 dead_tmp(tmp);
2709 static void gen_neon_dup_high16(TCGv var)
2711 TCGv tmp = new_tmp();
2712 tcg_gen_andi_i32(var, var, 0xffff0000);
2713 tcg_gen_shri_i32(tmp, var, 16);
2714 tcg_gen_or_i32(var, var, tmp);
2715 dead_tmp(tmp);
2718 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2719 (ie. an undefined instruction). */
2720 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2722 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2723 int dp, veclen;
2724 TCGv tmp;
2725 TCGv tmp2;
2727 if (!arm_feature(env, ARM_FEATURE_VFP))
2728 return 1;
2730 if (!vfp_enabled(env)) {
2731 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2732 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2733 return 1;
2734 rn = (insn >> 16) & 0xf;
2735 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2736 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2737 return 1;
2739 dp = ((insn & 0xf00) == 0xb00);
2740 switch ((insn >> 24) & 0xf) {
2741 case 0xe:
2742 if (insn & (1 << 4)) {
2743 /* single register transfer */
2744 rd = (insn >> 12) & 0xf;
2745 if (dp) {
2746 int size;
2747 int pass;
2749 VFP_DREG_N(rn, insn);
2750 if (insn & 0xf)
2751 return 1;
2752 if (insn & 0x00c00060
2753 && !arm_feature(env, ARM_FEATURE_NEON))
2754 return 1;
2756 pass = (insn >> 21) & 1;
2757 if (insn & (1 << 22)) {
2758 size = 0;
2759 offset = ((insn >> 5) & 3) * 8;
2760 } else if (insn & (1 << 5)) {
2761 size = 1;
2762 offset = (insn & (1 << 6)) ? 16 : 0;
2763 } else {
2764 size = 2;
2765 offset = 0;
2767 if (insn & ARM_CP_RW_BIT) {
2768 /* vfp->arm */
2769 tmp = neon_load_reg(rn, pass);
2770 switch (size) {
2771 case 0:
2772 if (offset)
2773 tcg_gen_shri_i32(tmp, tmp, offset);
2774 if (insn & (1 << 23))
2775 gen_uxtb(tmp);
2776 else
2777 gen_sxtb(tmp);
2778 break;
2779 case 1:
2780 if (insn & (1 << 23)) {
2781 if (offset) {
2782 tcg_gen_shri_i32(tmp, tmp, 16);
2783 } else {
2784 gen_uxth(tmp);
2786 } else {
2787 if (offset) {
2788 tcg_gen_sari_i32(tmp, tmp, 16);
2789 } else {
2790 gen_sxth(tmp);
2793 break;
2794 case 2:
2795 break;
2797 store_reg(s, rd, tmp);
2798 } else {
2799 /* arm->vfp */
2800 tmp = load_reg(s, rd);
2801 if (insn & (1 << 23)) {
2802 /* VDUP */
2803 if (size == 0) {
2804 gen_neon_dup_u8(tmp, 0);
2805 } else if (size == 1) {
2806 gen_neon_dup_low16(tmp);
2808 for (n = 0; n <= pass * 2; n++) {
2809 tmp2 = new_tmp();
2810 tcg_gen_mov_i32(tmp2, tmp);
2811 neon_store_reg(rn, n, tmp2);
2813 neon_store_reg(rn, n, tmp);
2814 } else {
2815 /* VMOV */
2816 switch (size) {
2817 case 0:
2818 tmp2 = neon_load_reg(rn, pass);
2819 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2820 dead_tmp(tmp2);
2821 break;
2822 case 1:
2823 tmp2 = neon_load_reg(rn, pass);
2824 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2825 dead_tmp(tmp2);
2826 break;
2827 case 2:
2828 break;
2830 neon_store_reg(rn, pass, tmp);
2833 } else { /* !dp */
2834 if ((insn & 0x6f) != 0x00)
2835 return 1;
2836 rn = VFP_SREG_N(insn);
2837 if (insn & ARM_CP_RW_BIT) {
2838 /* vfp->arm */
2839 if (insn & (1 << 21)) {
2840 /* system register */
2841 rn >>= 1;
2843 switch (rn) {
2844 case ARM_VFP_FPSID:
2845 /* VFP2 allows access to FSID from userspace.
2846 VFP3 restricts all id registers to privileged
2847 accesses. */
2848 if (IS_USER(s)
2849 && arm_feature(env, ARM_FEATURE_VFP3))
2850 return 1;
2851 tmp = load_cpu_field(vfp.xregs[rn]);
2852 break;
2853 case ARM_VFP_FPEXC:
2854 if (IS_USER(s))
2855 return 1;
2856 tmp = load_cpu_field(vfp.xregs[rn]);
2857 break;
2858 case ARM_VFP_FPINST:
2859 case ARM_VFP_FPINST2:
2860 /* Not present in VFP3. */
2861 if (IS_USER(s)
2862 || arm_feature(env, ARM_FEATURE_VFP3))
2863 return 1;
2864 tmp = load_cpu_field(vfp.xregs[rn]);
2865 break;
2866 case ARM_VFP_FPSCR:
2867 if (rd == 15) {
2868 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2869 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2870 } else {
2871 tmp = new_tmp();
2872 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2874 break;
2875 case ARM_VFP_MVFR0:
2876 case ARM_VFP_MVFR1:
2877 if (IS_USER(s)
2878 || !arm_feature(env, ARM_FEATURE_VFP3))
2879 return 1;
2880 tmp = load_cpu_field(vfp.xregs[rn]);
2881 break;
2882 default:
2883 return 1;
2885 } else {
2886 gen_mov_F0_vreg(0, rn);
2887 tmp = gen_vfp_mrs();
2889 if (rd == 15) {
2890 /* Set the 4 flag bits in the CPSR. */
2891 gen_set_nzcv(tmp);
2892 dead_tmp(tmp);
2893 } else {
2894 store_reg(s, rd, tmp);
2896 } else {
2897 /* arm->vfp */
2898 tmp = load_reg(s, rd);
2899 if (insn & (1 << 21)) {
2900 rn >>= 1;
2901 /* system register */
2902 switch (rn) {
2903 case ARM_VFP_FPSID:
2904 case ARM_VFP_MVFR0:
2905 case ARM_VFP_MVFR1:
2906 /* Writes are ignored. */
2907 break;
2908 case ARM_VFP_FPSCR:
2909 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2910 dead_tmp(tmp);
2911 gen_lookup_tb(s);
2912 break;
2913 case ARM_VFP_FPEXC:
2914 if (IS_USER(s))
2915 return 1;
2916 store_cpu_field(tmp, vfp.xregs[rn]);
2917 gen_lookup_tb(s);
2918 break;
2919 case ARM_VFP_FPINST:
2920 case ARM_VFP_FPINST2:
2921 store_cpu_field(tmp, vfp.xregs[rn]);
2922 break;
2923 default:
2924 return 1;
2926 } else {
2927 gen_vfp_msr(tmp);
2928 gen_mov_vreg_F0(0, rn);
2932 } else {
2933 /* data processing */
2934 /* The opcode is in bits 23, 21, 20 and 6. */
2935 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2936 if (dp) {
2937 if (op == 15) {
2938 /* rn is opcode */
2939 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2940 } else {
2941 /* rn is register number */
2942 VFP_DREG_N(rn, insn);
2945 if (op == 15 && (rn == 15 || rn > 17)) {
2946 /* Integer or single precision destination. */
2947 rd = VFP_SREG_D(insn);
2948 } else {
2949 VFP_DREG_D(rd, insn);
2952 if (op == 15 && (rn == 16 || rn == 17)) {
2953 /* Integer source. */
2954 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2955 } else {
2956 VFP_DREG_M(rm, insn);
2958 } else {
2959 rn = VFP_SREG_N(insn);
2960 if (op == 15 && rn == 15) {
2961 /* Double precision destination. */
2962 VFP_DREG_D(rd, insn);
2963 } else {
2964 rd = VFP_SREG_D(insn);
2966 rm = VFP_SREG_M(insn);
2969 veclen = env->vfp.vec_len;
2970 if (op == 15 && rn > 3)
2971 veclen = 0;
2973 /* Shut up compiler warnings. */
2974 delta_m = 0;
2975 delta_d = 0;
2976 bank_mask = 0;
2978 if (veclen > 0) {
2979 if (dp)
2980 bank_mask = 0xc;
2981 else
2982 bank_mask = 0x18;
2984 /* Figure out what type of vector operation this is. */
2985 if ((rd & bank_mask) == 0) {
2986 /* scalar */
2987 veclen = 0;
2988 } else {
2989 if (dp)
2990 delta_d = (env->vfp.vec_stride >> 1) + 1;
2991 else
2992 delta_d = env->vfp.vec_stride + 1;
2994 if ((rm & bank_mask) == 0) {
2995 /* mixed scalar/vector */
2996 delta_m = 0;
2997 } else {
2998 /* vector */
2999 delta_m = delta_d;
3004 /* Load the initial operands. */
3005 if (op == 15) {
3006 switch (rn) {
3007 case 16:
3008 case 17:
3009 /* Integer source */
3010 gen_mov_F0_vreg(0, rm);
3011 break;
3012 case 8:
3013 case 9:
3014 /* Compare */
3015 gen_mov_F0_vreg(dp, rd);
3016 gen_mov_F1_vreg(dp, rm);
3017 break;
3018 case 10:
3019 case 11:
3020 /* Compare with zero */
3021 gen_mov_F0_vreg(dp, rd);
3022 gen_vfp_F1_ld0(dp);
3023 break;
3024 case 20:
3025 case 21:
3026 case 22:
3027 case 23:
3028 case 28:
3029 case 29:
3030 case 30:
3031 case 31:
3032 /* Source and destination the same. */
3033 gen_mov_F0_vreg(dp, rd);
3034 break;
3035 default:
3036 /* One source operand. */
3037 gen_mov_F0_vreg(dp, rm);
3038 break;
3040 } else {
3041 /* Two source operands. */
3042 gen_mov_F0_vreg(dp, rn);
3043 gen_mov_F1_vreg(dp, rm);
3046 for (;;) {
3047 /* Perform the calculation. */
3048 switch (op) {
3049 case 0: /* mac: fd + (fn * fm) */
3050 gen_vfp_mul(dp);
3051 gen_mov_F1_vreg(dp, rd);
3052 gen_vfp_add(dp);
3053 break;
3054 case 1: /* nmac: fd - (fn * fm) */
3055 gen_vfp_mul(dp);
3056 gen_vfp_neg(dp);
3057 gen_mov_F1_vreg(dp, rd);
3058 gen_vfp_add(dp);
3059 break;
3060 case 2: /* msc: -fd + (fn * fm) */
3061 gen_vfp_mul(dp);
3062 gen_mov_F1_vreg(dp, rd);
3063 gen_vfp_sub(dp);
3064 break;
3065 case 3: /* nmsc: -fd - (fn * fm) */
3066 gen_vfp_mul(dp);
3067 gen_vfp_neg(dp);
3068 gen_mov_F1_vreg(dp, rd);
3069 gen_vfp_sub(dp);
3070 break;
3071 case 4: /* mul: fn * fm */
3072 gen_vfp_mul(dp);
3073 break;
3074 case 5: /* nmul: -(fn * fm) */
3075 gen_vfp_mul(dp);
3076 gen_vfp_neg(dp);
3077 break;
3078 case 6: /* add: fn + fm */
3079 gen_vfp_add(dp);
3080 break;
3081 case 7: /* sub: fn - fm */
3082 gen_vfp_sub(dp);
3083 break;
3084 case 8: /* div: fn / fm */
3085 gen_vfp_div(dp);
3086 break;
3087 case 14: /* fconst */
3088 if (!arm_feature(env, ARM_FEATURE_VFP3))
3089 return 1;
3091 n = (insn << 12) & 0x80000000;
3092 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3093 if (dp) {
3094 if (i & 0x40)
3095 i |= 0x3f80;
3096 else
3097 i |= 0x4000;
3098 n |= i << 16;
3099 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3100 } else {
3101 if (i & 0x40)
3102 i |= 0x780;
3103 else
3104 i |= 0x800;
3105 n |= i << 19;
3106 tcg_gen_movi_i32(cpu_F0s, n);
3108 break;
3109 case 15: /* extension space */
3110 switch (rn) {
3111 case 0: /* cpy */
3112 /* no-op */
3113 break;
3114 case 1: /* abs */
3115 gen_vfp_abs(dp);
3116 break;
3117 case 2: /* neg */
3118 gen_vfp_neg(dp);
3119 break;
3120 case 3: /* sqrt */
3121 gen_vfp_sqrt(dp);
3122 break;
3123 case 8: /* cmp */
3124 gen_vfp_cmp(dp);
3125 break;
3126 case 9: /* cmpe */
3127 gen_vfp_cmpe(dp);
3128 break;
3129 case 10: /* cmpz */
3130 gen_vfp_cmp(dp);
3131 break;
3132 case 11: /* cmpez */
3133 gen_vfp_F1_ld0(dp);
3134 gen_vfp_cmpe(dp);
3135 break;
3136 case 15: /* single<->double conversion */
3137 if (dp)
3138 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3139 else
3140 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3141 break;
3142 case 16: /* fuito */
3143 gen_vfp_uito(dp);
3144 break;
3145 case 17: /* fsito */
3146 gen_vfp_sito(dp);
3147 break;
3148 case 20: /* fshto */
3149 if (!arm_feature(env, ARM_FEATURE_VFP3))
3150 return 1;
3151 gen_vfp_shto(dp, 16 - rm);
3152 break;
3153 case 21: /* fslto */
3154 if (!arm_feature(env, ARM_FEATURE_VFP3))
3155 return 1;
3156 gen_vfp_slto(dp, 32 - rm);
3157 break;
3158 case 22: /* fuhto */
3159 if (!arm_feature(env, ARM_FEATURE_VFP3))
3160 return 1;
3161 gen_vfp_uhto(dp, 16 - rm);
3162 break;
3163 case 23: /* fulto */
3164 if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 return 1;
3166 gen_vfp_ulto(dp, 32 - rm);
3167 break;
3168 case 24: /* ftoui */
3169 gen_vfp_toui(dp);
3170 break;
3171 case 25: /* ftouiz */
3172 gen_vfp_touiz(dp);
3173 break;
3174 case 26: /* ftosi */
3175 gen_vfp_tosi(dp);
3176 break;
3177 case 27: /* ftosiz */
3178 gen_vfp_tosiz(dp);
3179 break;
3180 case 28: /* ftosh */
3181 if (!arm_feature(env, ARM_FEATURE_VFP3))
3182 return 1;
3183 gen_vfp_tosh(dp, 16 - rm);
3184 break;
3185 case 29: /* ftosl */
3186 if (!arm_feature(env, ARM_FEATURE_VFP3))
3187 return 1;
3188 gen_vfp_tosl(dp, 32 - rm);
3189 break;
3190 case 30: /* ftouh */
3191 if (!arm_feature(env, ARM_FEATURE_VFP3))
3192 return 1;
3193 gen_vfp_touh(dp, 16 - rm);
3194 break;
3195 case 31: /* ftoul */
3196 if (!arm_feature(env, ARM_FEATURE_VFP3))
3197 return 1;
3198 gen_vfp_toul(dp, 32 - rm);
3199 break;
3200 default: /* undefined */
3201 printf ("rn:%d\n", rn);
3202 return 1;
3204 break;
3205 default: /* undefined */
3206 printf ("op:%d\n", op);
3207 return 1;
3210 /* Write back the result. */
3211 if (op == 15 && (rn >= 8 && rn <= 11))
3212 ; /* Comparison, do nothing. */
3213 else if (op == 15 && rn > 17)
3214 /* Integer result. */
3215 gen_mov_vreg_F0(0, rd);
3216 else if (op == 15 && rn == 15)
3217 /* conversion */
3218 gen_mov_vreg_F0(!dp, rd);
3219 else
3220 gen_mov_vreg_F0(dp, rd);
3222 /* break out of the loop if we have finished */
3223 if (veclen == 0)
3224 break;
3226 if (op == 15 && delta_m == 0) {
3227 /* single source one-many */
3228 while (veclen--) {
3229 rd = ((rd + delta_d) & (bank_mask - 1))
3230 | (rd & bank_mask);
3231 gen_mov_vreg_F0(dp, rd);
3233 break;
3235 /* Setup the next operands. */
3236 veclen--;
3237 rd = ((rd + delta_d) & (bank_mask - 1))
3238 | (rd & bank_mask);
3240 if (op == 15) {
3241 /* One source operand. */
3242 rm = ((rm + delta_m) & (bank_mask - 1))
3243 | (rm & bank_mask);
3244 gen_mov_F0_vreg(dp, rm);
3245 } else {
3246 /* Two source operands. */
3247 rn = ((rn + delta_d) & (bank_mask - 1))
3248 | (rn & bank_mask);
3249 gen_mov_F0_vreg(dp, rn);
3250 if (delta_m) {
3251 rm = ((rm + delta_m) & (bank_mask - 1))
3252 | (rm & bank_mask);
3253 gen_mov_F1_vreg(dp, rm);
3258 break;
3259 case 0xc:
3260 case 0xd:
3261 if (dp && (insn & 0x03e00000) == 0x00400000) {
3262 /* two-register transfer */
3263 rn = (insn >> 16) & 0xf;
3264 rd = (insn >> 12) & 0xf;
3265 if (dp) {
3266 VFP_DREG_M(rm, insn);
3267 } else {
3268 rm = VFP_SREG_M(insn);
3271 if (insn & ARM_CP_RW_BIT) {
3272 /* vfp->arm */
3273 if (dp) {
3274 gen_mov_F0_vreg(0, rm * 2);
3275 tmp = gen_vfp_mrs();
3276 store_reg(s, rd, tmp);
3277 gen_mov_F0_vreg(0, rm * 2 + 1);
3278 tmp = gen_vfp_mrs();
3279 store_reg(s, rn, tmp);
3280 } else {
3281 gen_mov_F0_vreg(0, rm);
3282 tmp = gen_vfp_mrs();
3283 store_reg(s, rn, tmp);
3284 gen_mov_F0_vreg(0, rm + 1);
3285 tmp = gen_vfp_mrs();
3286 store_reg(s, rd, tmp);
3288 } else {
3289 /* arm->vfp */
3290 if (dp) {
3291 tmp = load_reg(s, rd);
3292 gen_vfp_msr(tmp);
3293 gen_mov_vreg_F0(0, rm * 2);
3294 tmp = load_reg(s, rn);
3295 gen_vfp_msr(tmp);
3296 gen_mov_vreg_F0(0, rm * 2 + 1);
3297 } else {
3298 tmp = load_reg(s, rn);
3299 gen_vfp_msr(tmp);
3300 gen_mov_vreg_F0(0, rm);
3301 tmp = load_reg(s, rd);
3302 gen_vfp_msr(tmp);
3303 gen_mov_vreg_F0(0, rm + 1);
3306 } else {
3307 /* Load/store */
3308 rn = (insn >> 16) & 0xf;
3309 if (dp)
3310 VFP_DREG_D(rd, insn);
3311 else
3312 rd = VFP_SREG_D(insn);
3313 if (s->thumb && rn == 15) {
3314 gen_op_movl_T1_im(s->pc & ~2);
3315 } else {
3316 gen_movl_T1_reg(s, rn);
3318 if ((insn & 0x01200000) == 0x01000000) {
3319 /* Single load/store */
3320 offset = (insn & 0xff) << 2;
3321 if ((insn & (1 << 23)) == 0)
3322 offset = -offset;
3323 gen_op_addl_T1_im(offset);
3324 if (insn & (1 << 20)) {
3325 gen_vfp_ld(s, dp);
3326 gen_mov_vreg_F0(dp, rd);
3327 } else {
3328 gen_mov_F0_vreg(dp, rd);
3329 gen_vfp_st(s, dp);
3331 } else {
3332 /* load/store multiple */
3333 if (dp)
3334 n = (insn >> 1) & 0x7f;
3335 else
3336 n = insn & 0xff;
3338 if (insn & (1 << 24)) /* pre-decrement */
3339 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3341 if (dp)
3342 offset = 8;
3343 else
3344 offset = 4;
3345 for (i = 0; i < n; i++) {
3346 if (insn & ARM_CP_RW_BIT) {
3347 /* load */
3348 gen_vfp_ld(s, dp);
3349 gen_mov_vreg_F0(dp, rd + i);
3350 } else {
3351 /* store */
3352 gen_mov_F0_vreg(dp, rd + i);
3353 gen_vfp_st(s, dp);
3355 gen_op_addl_T1_im(offset);
3357 if (insn & (1 << 21)) {
3358 /* writeback */
3359 if (insn & (1 << 24))
3360 offset = -offset * n;
3361 else if (dp && (insn & 1))
3362 offset = 4;
3363 else
3364 offset = 0;
3366 if (offset != 0)
3367 gen_op_addl_T1_im(offset);
3368 gen_movl_reg_T1(s, rn);
3372 break;
3373 default:
3374 /* Should never happen. */
3375 return 1;
3377 return 0;
3380 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3382 TranslationBlock *tb;
3384 tb = s->tb;
3385 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3386 tcg_gen_goto_tb(n);
3387 gen_set_pc_im(dest);
3388 tcg_gen_exit_tb((long)tb + n);
3389 } else {
3390 gen_set_pc_im(dest);
3391 tcg_gen_exit_tb(0);
3395 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3397 if (unlikely(s->singlestep_enabled)) {
3398 /* An indirect jump so that we still trigger the debug exception. */
3399 if (s->thumb)
3400 dest |= 1;
3401 gen_bx_im(s, dest);
3402 } else {
3403 gen_goto_tb(s, 0, dest);
3404 s->is_jmp = DISAS_TB_JUMP;
3408 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3410 if (x)
3411 tcg_gen_sari_i32(t0, t0, 16);
3412 else
3413 gen_sxth(t0);
3414 if (y)
3415 tcg_gen_sari_i32(t1, t1, 16);
3416 else
3417 gen_sxth(t1);
3418 tcg_gen_mul_i32(t0, t0, t1);
3421 /* Return the mask of PSR bits set by a MSR instruction. */
3422 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3423 uint32_t mask;
3425 mask = 0;
3426 if (flags & (1 << 0))
3427 mask |= 0xff;
3428 if (flags & (1 << 1))
3429 mask |= 0xff00;
3430 if (flags & (1 << 2))
3431 mask |= 0xff0000;
3432 if (flags & (1 << 3))
3433 mask |= 0xff000000;
3435 /* Mask out undefined bits. */
3436 mask &= ~CPSR_RESERVED;
3437 if (!arm_feature(env, ARM_FEATURE_V6))
3438 mask &= ~(CPSR_E | CPSR_GE);
3439 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3440 mask &= ~CPSR_IT;
3441 /* Mask out execution state bits. */
3442 if (!spsr)
3443 mask &= ~CPSR_EXEC;
3444 /* Mask out privileged bits. */
3445 if (IS_USER(s))
3446 mask &= CPSR_USER;
3447 return mask;
3450 /* Returns nonzero if access to the PSR is not permitted. */
3451 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3453 TCGv tmp;
3454 if (spsr) {
3455 /* ??? This is also undefined in system mode. */
3456 if (IS_USER(s))
3457 return 1;
3459 tmp = load_cpu_field(spsr);
3460 tcg_gen_andi_i32(tmp, tmp, ~mask);
3461 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3462 tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3463 store_cpu_field(tmp, spsr);
3464 } else {
3465 gen_set_cpsr(cpu_T[0], mask);
3467 gen_lookup_tb(s);
3468 return 0;
3471 /* Generate an old-style exception return. Marks pc as dead. */
3472 static void gen_exception_return(DisasContext *s, TCGv pc)
3474 TCGv tmp;
3475 store_reg(s, 15, pc);
3476 tmp = load_cpu_field(spsr);
3477 gen_set_cpsr(tmp, 0xffffffff);
3478 dead_tmp(tmp);
3479 s->is_jmp = DISAS_UPDATE;
3482 /* Generate a v6 exception return. Marks both values as dead. */
3483 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3485 gen_set_cpsr(cpsr, 0xffffffff);
3486 dead_tmp(cpsr);
3487 store_reg(s, 15, pc);
3488 s->is_jmp = DISAS_UPDATE;
3491 static inline void
3492 gen_set_condexec (DisasContext *s)
3494 if (s->condexec_mask) {
3495 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3496 TCGv tmp = new_tmp();
3497 tcg_gen_movi_i32(tmp, val);
3498 store_cpu_field(tmp, condexec_bits);
3502 static void gen_nop_hint(DisasContext *s, int val)
3504 switch (val) {
3505 case 3: /* wfi */
3506 gen_set_pc_im(s->pc);
3507 s->is_jmp = DISAS_WFI;
3508 break;
3509 case 2: /* wfe */
3510 case 4: /* sev */
3511 /* TODO: Implement SEV and WFE. May help SMP performance. */
3512 default: /* nop */
3513 break;
3517 /* These macros help make the code more readable when migrating from the
3518 old dyngen helpers. They should probably be removed when
3519 T0/T1 are removed. */
3520 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3521 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3523 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3525 static inline int gen_neon_add(int size)
3527 switch (size) {
3528 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3529 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3530 case 2: gen_op_addl_T0_T1(); break;
3531 default: return 1;
3533 return 0;
3536 static inline void gen_neon_rsb(int size)
3538 switch (size) {
3539 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3540 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3541 case 2: gen_op_rsbl_T0_T1(); break;
3542 default: return;
3546 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3547 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3548 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3549 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3550 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3552 /* FIXME: This is wrong. They set the wrong overflow bit. */
3553 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3554 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3555 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3556 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3558 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3559 switch ((size << 1) | u) { \
3560 case 0: \
3561 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3562 break; \
3563 case 1: \
3564 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3565 break; \
3566 case 2: \
3567 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3568 break; \
3569 case 3: \
3570 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3571 break; \
3572 case 4: \
3573 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3574 break; \
3575 case 5: \
3576 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3577 break; \
3578 default: return 1; \
3579 }} while (0)
3581 #define GEN_NEON_INTEGER_OP(name) do { \
3582 switch ((size << 1) | u) { \
3583 case 0: \
3584 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3585 break; \
3586 case 1: \
3587 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3588 break; \
3589 case 2: \
3590 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3591 break; \
3592 case 3: \
3593 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3594 break; \
3595 case 4: \
3596 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3597 break; \
3598 case 5: \
3599 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3600 break; \
3601 default: return 1; \
3602 }} while (0)
3604 static inline void
3605 gen_neon_movl_scratch_T0(int scratch)
3607 uint32_t offset;
3609 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3610 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3613 static inline void
3614 gen_neon_movl_scratch_T1(int scratch)
3616 uint32_t offset;
3618 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3619 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3622 static inline void
3623 gen_neon_movl_T0_scratch(int scratch)
3625 uint32_t offset;
3627 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3628 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3631 static inline void
3632 gen_neon_movl_T1_scratch(int scratch)
3634 uint32_t offset;
3636 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3637 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3640 static inline void gen_neon_get_scalar(int size, int reg)
3642 if (size == 1) {
3643 NEON_GET_REG(T0, reg >> 1, reg & 1);
3644 } else {
3645 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3646 if (reg & 1)
3647 gen_neon_dup_low16(cpu_T[0]);
3648 else
3649 gen_neon_dup_high16(cpu_T[0]);
3653 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3655 int n;
3657 for (n = 0; n < q + 1; n += 2) {
3658 NEON_GET_REG(T0, reg, n);
3659 NEON_GET_REG(T0, reg, n + n);
3660 switch (size) {
3661 case 0: gen_helper_neon_unzip_u8(); break;
3662 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3663 case 2: /* no-op */; break;
3664 default: abort();
3666 gen_neon_movl_scratch_T0(tmp + n);
3667 gen_neon_movl_scratch_T1(tmp + n + 1);
3671 static struct {
3672 int nregs;
3673 int interleave;
3674 int spacing;
3675 } neon_ls_element_type[11] = {
3676 {4, 4, 1},
3677 {4, 4, 2},
3678 {4, 1, 1},
3679 {4, 2, 1},
3680 {3, 3, 1},
3681 {3, 3, 2},
3682 {3, 1, 1},
3683 {1, 1, 1},
3684 {2, 2, 1},
3685 {2, 2, 2},
3686 {2, 1, 1}
3689 /* Translate a NEON load/store element instruction. Return nonzero if the
3690 instruction is invalid. */
3691 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3693 int rd, rn, rm;
3694 int op;
3695 int nregs;
3696 int interleave;
3697 int stride;
3698 int size;
3699 int reg;
3700 int pass;
3701 int load;
3702 int shift;
3703 int n;
3704 TCGv tmp;
3705 TCGv tmp2;
3707 if (!vfp_enabled(env))
3708 return 1;
3709 VFP_DREG_D(rd, insn);
3710 rn = (insn >> 16) & 0xf;
3711 rm = insn & 0xf;
3712 load = (insn & (1 << 21)) != 0;
3713 if ((insn & (1 << 23)) == 0) {
3714 /* Load store all elements. */
3715 op = (insn >> 8) & 0xf;
3716 size = (insn >> 6) & 3;
3717 if (op > 10 || size == 3)
3718 return 1;
3719 nregs = neon_ls_element_type[op].nregs;
3720 interleave = neon_ls_element_type[op].interleave;
3721 gen_movl_T1_reg(s, rn);
3722 stride = (1 << size) * interleave;
3723 for (reg = 0; reg < nregs; reg++) {
3724 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3725 gen_movl_T1_reg(s, rn);
3726 gen_op_addl_T1_im((1 << size) * reg);
3727 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3728 gen_movl_T1_reg(s, rn);
3729 gen_op_addl_T1_im(1 << size);
3731 for (pass = 0; pass < 2; pass++) {
3732 if (size == 2) {
3733 if (load) {
3734 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3735 neon_store_reg(rd, pass, tmp);
3736 } else {
3737 tmp = neon_load_reg(rd, pass);
3738 gen_st32(tmp, cpu_T[1], IS_USER(s));
3740 gen_op_addl_T1_im(stride);
3741 } else if (size == 1) {
3742 if (load) {
3743 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3744 gen_op_addl_T1_im(stride);
3745 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3746 gen_op_addl_T1_im(stride);
3747 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3748 dead_tmp(tmp2);
3749 neon_store_reg(rd, pass, tmp);
3750 } else {
3751 tmp = neon_load_reg(rd, pass);
3752 tmp2 = new_tmp();
3753 tcg_gen_shri_i32(tmp2, tmp, 16);
3754 gen_st16(tmp, cpu_T[1], IS_USER(s));
3755 gen_op_addl_T1_im(stride);
3756 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3757 gen_op_addl_T1_im(stride);
3759 } else /* size == 0 */ {
3760 if (load) {
3761 TCGV_UNUSED(tmp2);
3762 for (n = 0; n < 4; n++) {
3763 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3764 gen_op_addl_T1_im(stride);
3765 if (n == 0) {
3766 tmp2 = tmp;
3767 } else {
3768 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3769 dead_tmp(tmp);
3772 neon_store_reg(rd, pass, tmp2);
3773 } else {
3774 tmp2 = neon_load_reg(rd, pass);
3775 for (n = 0; n < 4; n++) {
3776 tmp = new_tmp();
3777 if (n == 0) {
3778 tcg_gen_mov_i32(tmp, tmp2);
3779 } else {
3780 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3782 gen_st8(tmp, cpu_T[1], IS_USER(s));
3783 gen_op_addl_T1_im(stride);
3785 dead_tmp(tmp2);
3789 rd += neon_ls_element_type[op].spacing;
3791 stride = nregs * 8;
3792 } else {
3793 size = (insn >> 10) & 3;
3794 if (size == 3) {
3795 /* Load single element to all lanes. */
3796 if (!load)
3797 return 1;
3798 size = (insn >> 6) & 3;
3799 nregs = ((insn >> 8) & 3) + 1;
3800 stride = (insn & (1 << 5)) ? 2 : 1;
3801 gen_movl_T1_reg(s, rn);
3802 for (reg = 0; reg < nregs; reg++) {
3803 switch (size) {
3804 case 0:
3805 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3806 gen_neon_dup_u8(tmp, 0);
3807 break;
3808 case 1:
3809 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3810 gen_neon_dup_low16(tmp);
3811 break;
3812 case 2:
3813 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3814 break;
3815 case 3:
3816 return 1;
3817 default: /* Avoid compiler warnings. */
3818 abort();
3820 gen_op_addl_T1_im(1 << size);
3821 tmp2 = new_tmp();
3822 tcg_gen_mov_i32(tmp2, tmp);
3823 neon_store_reg(rd, 0, tmp2);
3824 neon_store_reg(rd, 1, tmp);
3825 rd += stride;
3827 stride = (1 << size) * nregs;
3828 } else {
3829 /* Single element. */
3830 pass = (insn >> 7) & 1;
3831 switch (size) {
3832 case 0:
3833 shift = ((insn >> 5) & 3) * 8;
3834 stride = 1;
3835 break;
3836 case 1:
3837 shift = ((insn >> 6) & 1) * 16;
3838 stride = (insn & (1 << 5)) ? 2 : 1;
3839 break;
3840 case 2:
3841 shift = 0;
3842 stride = (insn & (1 << 6)) ? 2 : 1;
3843 break;
3844 default:
3845 abort();
3847 nregs = ((insn >> 8) & 3) + 1;
3848 gen_movl_T1_reg(s, rn);
3849 for (reg = 0; reg < nregs; reg++) {
3850 if (load) {
3851 switch (size) {
3852 case 0:
3853 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3854 break;
3855 case 1:
3856 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3857 break;
3858 case 2:
3859 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3860 break;
3861 default: /* Avoid compiler warnings. */
3862 abort();
3864 if (size != 2) {
3865 tmp2 = neon_load_reg(rd, pass);
3866 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3867 dead_tmp(tmp2);
3869 neon_store_reg(rd, pass, tmp);
3870 } else { /* Store */
3871 tmp = neon_load_reg(rd, pass);
3872 if (shift)
3873 tcg_gen_shri_i32(tmp, tmp, shift);
3874 switch (size) {
3875 case 0:
3876 gen_st8(tmp, cpu_T[1], IS_USER(s));
3877 break;
3878 case 1:
3879 gen_st16(tmp, cpu_T[1], IS_USER(s));
3880 break;
3881 case 2:
3882 gen_st32(tmp, cpu_T[1], IS_USER(s));
3883 break;
3886 rd += stride;
3887 gen_op_addl_T1_im(1 << size);
3889 stride = nregs * (1 << size);
3892 if (rm != 15) {
3893 TCGv base;
3895 base = load_reg(s, rn);
3896 if (rm == 13) {
3897 tcg_gen_addi_i32(base, base, stride);
3898 } else {
3899 TCGv index;
3900 index = load_reg(s, rm);
3901 tcg_gen_add_i32(base, base, index);
3902 dead_tmp(index);
3904 store_reg(s, rn, base);
3906 return 0;
3909 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3910 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3912 tcg_gen_and_i32(t, t, c);
3913 tcg_gen_bic_i32(f, f, c);
3914 tcg_gen_or_i32(dest, t, f);
3917 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3919 switch (size) {
3920 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3921 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3922 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3923 default: abort();
3927 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3929 switch (size) {
3930 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3931 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3932 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3933 default: abort();
3937 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3939 switch (size) {
3940 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3941 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3942 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3943 default: abort();
3947 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3948 int q, int u)
3950 if (q) {
3951 if (u) {
3952 switch (size) {
3953 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3954 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3955 default: abort();
3957 } else {
3958 switch (size) {
3959 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3960 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3961 default: abort();
3964 } else {
3965 if (u) {
3966 switch (size) {
3967 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3968 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3969 default: abort();
3971 } else {
3972 switch (size) {
3973 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3974 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3975 default: abort();
3981 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3983 if (u) {
3984 switch (size) {
3985 case 0: gen_helper_neon_widen_u8(dest, src); break;
3986 case 1: gen_helper_neon_widen_u16(dest, src); break;
3987 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3988 default: abort();
3990 } else {
3991 switch (size) {
3992 case 0: gen_helper_neon_widen_s8(dest, src); break;
3993 case 1: gen_helper_neon_widen_s16(dest, src); break;
3994 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3995 default: abort();
3998 dead_tmp(src);
4001 static inline void gen_neon_addl(int size)
4003 switch (size) {
4004 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4005 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4006 case 2: tcg_gen_add_i64(CPU_V001); break;
4007 default: abort();
4011 static inline void gen_neon_subl(int size)
4013 switch (size) {
4014 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4015 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4016 case 2: tcg_gen_sub_i64(CPU_V001); break;
4017 default: abort();
4021 static inline void gen_neon_negl(TCGv_i64 var, int size)
4023 switch (size) {
4024 case 0: gen_helper_neon_negl_u16(var, var); break;
4025 case 1: gen_helper_neon_negl_u32(var, var); break;
4026 case 2: gen_helper_neon_negl_u64(var, var); break;
4027 default: abort();
4031 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4033 switch (size) {
4034 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4035 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4036 default: abort();
4040 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4042 TCGv_i64 tmp;
4044 switch ((size << 1) | u) {
4045 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4046 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4047 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4048 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4049 case 4:
4050 tmp = gen_muls_i64_i32(a, b);
4051 tcg_gen_mov_i64(dest, tmp);
4052 break;
4053 case 5:
4054 tmp = gen_mulu_i64_i32(a, b);
4055 tcg_gen_mov_i64(dest, tmp);
4056 break;
4057 default: abort();
4059 if (size < 2) {
4060 dead_tmp(b);
4061 dead_tmp(a);
4065 /* Translate a NEON data processing instruction. Return nonzero if the
4066 instruction is invalid.
4067 We process data in a mixture of 32-bit and 64-bit chunks.
4068 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4070 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4072 int op;
4073 int q;
4074 int rd, rn, rm;
4075 int size;
4076 int shift;
4077 int pass;
4078 int count;
4079 int pairwise;
4080 int u;
4081 int n;
4082 uint32_t imm;
4083 TCGv tmp;
4084 TCGv tmp2;
4085 TCGv tmp3;
4086 TCGv_i64 tmp64;
4088 if (!vfp_enabled(env))
4089 return 1;
4090 q = (insn & (1 << 6)) != 0;
4091 u = (insn >> 24) & 1;
4092 VFP_DREG_D(rd, insn);
4093 VFP_DREG_N(rn, insn);
4094 VFP_DREG_M(rm, insn);
4095 size = (insn >> 20) & 3;
4096 if ((insn & (1 << 23)) == 0) {
4097 /* Three register same length. */
4098 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4099 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4100 || op == 10 || op == 11 || op == 16)) {
4101 /* 64-bit element instructions. */
4102 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4103 neon_load_reg64(cpu_V0, rn + pass);
4104 neon_load_reg64(cpu_V1, rm + pass);
4105 switch (op) {
4106 case 1: /* VQADD */
4107 if (u) {
4108 gen_helper_neon_add_saturate_u64(CPU_V001);
4109 } else {
4110 gen_helper_neon_add_saturate_s64(CPU_V001);
4112 break;
4113 case 5: /* VQSUB */
4114 if (u) {
4115 gen_helper_neon_sub_saturate_u64(CPU_V001);
4116 } else {
4117 gen_helper_neon_sub_saturate_s64(CPU_V001);
4119 break;
4120 case 8: /* VSHL */
4121 if (u) {
4122 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4123 } else {
4124 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4126 break;
4127 case 9: /* VQSHL */
4128 if (u) {
4129 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4130 cpu_V0, cpu_V0);
4131 } else {
4132 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4133 cpu_V1, cpu_V0);
4135 break;
4136 case 10: /* VRSHL */
4137 if (u) {
4138 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4139 } else {
4140 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4142 break;
4143 case 11: /* VQRSHL */
4144 if (u) {
4145 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4146 cpu_V1, cpu_V0);
4147 } else {
4148 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4149 cpu_V1, cpu_V0);
4151 break;
4152 case 16:
4153 if (u) {
4154 tcg_gen_sub_i64(CPU_V001);
4155 } else {
4156 tcg_gen_add_i64(CPU_V001);
4158 break;
4159 default:
4160 abort();
4162 neon_store_reg64(cpu_V0, rd + pass);
4164 return 0;
4166 switch (op) {
4167 case 8: /* VSHL */
4168 case 9: /* VQSHL */
4169 case 10: /* VRSHL */
4170 case 11: /* VQRSHL */
4172 int rtmp;
4173 /* Shift instruction operands are reversed. */
4174 rtmp = rn;
4175 rn = rm;
4176 rm = rtmp;
4177 pairwise = 0;
4179 break;
4180 case 20: /* VPMAX */
4181 case 21: /* VPMIN */
4182 case 23: /* VPADD */
4183 pairwise = 1;
4184 break;
4185 case 26: /* VPADD (float) */
4186 pairwise = (u && size < 2);
4187 break;
4188 case 30: /* VPMIN/VPMAX (float) */
4189 pairwise = u;
4190 break;
4191 default:
4192 pairwise = 0;
4193 break;
4195 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4197 if (pairwise) {
4198 /* Pairwise. */
4199 if (q)
4200 n = (pass & 1) * 2;
4201 else
4202 n = 0;
4203 if (pass < q + 1) {
4204 NEON_GET_REG(T0, rn, n);
4205 NEON_GET_REG(T1, rn, n + 1);
4206 } else {
4207 NEON_GET_REG(T0, rm, n);
4208 NEON_GET_REG(T1, rm, n + 1);
4210 } else {
4211 /* Elementwise. */
4212 NEON_GET_REG(T0, rn, pass);
4213 NEON_GET_REG(T1, rm, pass);
4215 switch (op) {
4216 case 0: /* VHADD */
4217 GEN_NEON_INTEGER_OP(hadd);
4218 break;
4219 case 1: /* VQADD */
4220 GEN_NEON_INTEGER_OP_ENV(qadd);
4221 break;
4222 case 2: /* VRHADD */
4223 GEN_NEON_INTEGER_OP(rhadd);
4224 break;
4225 case 3: /* Logic ops. */
4226 switch ((u << 2) | size) {
4227 case 0: /* VAND */
4228 gen_op_andl_T0_T1();
4229 break;
4230 case 1: /* BIC */
4231 gen_op_bicl_T0_T1();
4232 break;
4233 case 2: /* VORR */
4234 gen_op_orl_T0_T1();
4235 break;
4236 case 3: /* VORN */
4237 gen_op_notl_T1();
4238 gen_op_orl_T0_T1();
4239 break;
4240 case 4: /* VEOR */
4241 gen_op_xorl_T0_T1();
4242 break;
4243 case 5: /* VBSL */
4244 tmp = neon_load_reg(rd, pass);
4245 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4246 dead_tmp(tmp);
4247 break;
4248 case 6: /* VBIT */
4249 tmp = neon_load_reg(rd, pass);
4250 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4251 dead_tmp(tmp);
4252 break;
4253 case 7: /* VBIF */
4254 tmp = neon_load_reg(rd, pass);
4255 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4256 dead_tmp(tmp);
4257 break;
4259 break;
4260 case 4: /* VHSUB */
4261 GEN_NEON_INTEGER_OP(hsub);
4262 break;
4263 case 5: /* VQSUB */
4264 GEN_NEON_INTEGER_OP_ENV(qsub);
4265 break;
4266 case 6: /* VCGT */
4267 GEN_NEON_INTEGER_OP(cgt);
4268 break;
4269 case 7: /* VCGE */
4270 GEN_NEON_INTEGER_OP(cge);
4271 break;
4272 case 8: /* VSHL */
4273 GEN_NEON_INTEGER_OP(shl);
4274 break;
4275 case 9: /* VQSHL */
4276 GEN_NEON_INTEGER_OP_ENV(qshl);
4277 break;
4278 case 10: /* VRSHL */
4279 GEN_NEON_INTEGER_OP(rshl);
4280 break;
4281 case 11: /* VQRSHL */
4282 GEN_NEON_INTEGER_OP_ENV(qrshl);
4283 break;
4284 case 12: /* VMAX */
4285 GEN_NEON_INTEGER_OP(max);
4286 break;
4287 case 13: /* VMIN */
4288 GEN_NEON_INTEGER_OP(min);
4289 break;
4290 case 14: /* VABD */
4291 GEN_NEON_INTEGER_OP(abd);
4292 break;
4293 case 15: /* VABA */
4294 GEN_NEON_INTEGER_OP(abd);
4295 NEON_GET_REG(T1, rd, pass);
4296 gen_neon_add(size);
4297 break;
4298 case 16:
4299 if (!u) { /* VADD */
4300 if (gen_neon_add(size))
4301 return 1;
4302 } else { /* VSUB */
4303 switch (size) {
4304 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4305 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4306 case 2: gen_op_subl_T0_T1(); break;
4307 default: return 1;
4310 break;
4311 case 17:
4312 if (!u) { /* VTST */
4313 switch (size) {
4314 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4315 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4316 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4317 default: return 1;
4319 } else { /* VCEQ */
4320 switch (size) {
4321 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4322 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4323 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4324 default: return 1;
4327 break;
4328 case 18: /* Multiply. */
4329 switch (size) {
4330 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4331 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4332 case 2: gen_op_mul_T0_T1(); break;
4333 default: return 1;
4335 NEON_GET_REG(T1, rd, pass);
4336 if (u) { /* VMLS */
4337 gen_neon_rsb(size);
4338 } else { /* VMLA */
4339 gen_neon_add(size);
4341 break;
4342 case 19: /* VMUL */
4343 if (u) { /* polynomial */
4344 gen_helper_neon_mul_p8(CPU_T001);
4345 } else { /* Integer */
4346 switch (size) {
4347 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4348 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4349 case 2: gen_op_mul_T0_T1(); break;
4350 default: return 1;
4353 break;
4354 case 20: /* VPMAX */
4355 GEN_NEON_INTEGER_OP(pmax);
4356 break;
4357 case 21: /* VPMIN */
4358 GEN_NEON_INTEGER_OP(pmin);
4359 break;
4360 case 22: /* Hultiply high. */
4361 if (!u) { /* VQDMULH */
4362 switch (size) {
4363 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4364 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4365 default: return 1;
4367 } else { /* VQRDHMUL */
4368 switch (size) {
4369 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4370 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4371 default: return 1;
4374 break;
4375 case 23: /* VPADD */
4376 if (u)
4377 return 1;
4378 switch (size) {
4379 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4380 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4381 case 2: gen_op_addl_T0_T1(); break;
4382 default: return 1;
4384 break;
4385 case 26: /* Floating point arithnetic. */
4386 switch ((u << 2) | size) {
4387 case 0: /* VADD */
4388 gen_helper_neon_add_f32(CPU_T001);
4389 break;
4390 case 2: /* VSUB */
4391 gen_helper_neon_sub_f32(CPU_T001);
4392 break;
4393 case 4: /* VPADD */
4394 gen_helper_neon_add_f32(CPU_T001);
4395 break;
4396 case 6: /* VABD */
4397 gen_helper_neon_abd_f32(CPU_T001);
4398 break;
4399 default:
4400 return 1;
4402 break;
4403 case 27: /* Float multiply. */
4404 gen_helper_neon_mul_f32(CPU_T001);
4405 if (!u) {
4406 NEON_GET_REG(T1, rd, pass);
4407 if (size == 0) {
4408 gen_helper_neon_add_f32(CPU_T001);
4409 } else {
4410 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4413 break;
4414 case 28: /* Float compare. */
4415 if (!u) {
4416 gen_helper_neon_ceq_f32(CPU_T001);
4417 } else {
4418 if (size == 0)
4419 gen_helper_neon_cge_f32(CPU_T001);
4420 else
4421 gen_helper_neon_cgt_f32(CPU_T001);
4423 break;
4424 case 29: /* Float compare absolute. */
4425 if (!u)
4426 return 1;
4427 if (size == 0)
4428 gen_helper_neon_acge_f32(CPU_T001);
4429 else
4430 gen_helper_neon_acgt_f32(CPU_T001);
4431 break;
4432 case 30: /* Float min/max. */
4433 if (size == 0)
4434 gen_helper_neon_max_f32(CPU_T001);
4435 else
4436 gen_helper_neon_min_f32(CPU_T001);
4437 break;
4438 case 31:
4439 if (size == 0)
4440 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4441 else
4442 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4443 break;
4444 default:
4445 abort();
4447 /* Save the result. For elementwise operations we can put it
4448 straight into the destination register. For pairwise operations
4449 we have to be careful to avoid clobbering the source operands. */
4450 if (pairwise && rd == rm) {
4451 gen_neon_movl_scratch_T0(pass);
4452 } else {
4453 NEON_SET_REG(T0, rd, pass);
4456 } /* for pass */
4457 if (pairwise && rd == rm) {
4458 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4459 gen_neon_movl_T0_scratch(pass);
4460 NEON_SET_REG(T0, rd, pass);
4463 /* End of 3 register same size operations. */
4464 } else if (insn & (1 << 4)) {
4465 if ((insn & 0x00380080) != 0) {
4466 /* Two registers and shift. */
4467 op = (insn >> 8) & 0xf;
4468 if (insn & (1 << 7)) {
4469 /* 64-bit shift. */
4470 size = 3;
4471 } else {
4472 size = 2;
4473 while ((insn & (1 << (size + 19))) == 0)
4474 size--;
4476 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4477 /* To avoid excessive dumplication of ops we implement shift
4478 by immediate using the variable shift operations. */
4479 if (op < 8) {
4480 /* Shift by immediate:
4481 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4482 /* Right shifts are encoded as N - shift, where N is the
4483 element size in bits. */
4484 if (op <= 4)
4485 shift = shift - (1 << (size + 3));
4486 if (size == 3) {
4487 count = q + 1;
4488 } else {
4489 count = q ? 4: 2;
4491 switch (size) {
4492 case 0:
4493 imm = (uint8_t) shift;
4494 imm |= imm << 8;
4495 imm |= imm << 16;
4496 break;
4497 case 1:
4498 imm = (uint16_t) shift;
4499 imm |= imm << 16;
4500 break;
4501 case 2:
4502 case 3:
4503 imm = shift;
4504 break;
4505 default:
4506 abort();
4509 for (pass = 0; pass < count; pass++) {
4510 if (size == 3) {
4511 neon_load_reg64(cpu_V0, rm + pass);
4512 tcg_gen_movi_i64(cpu_V1, imm);
4513 switch (op) {
4514 case 0: /* VSHR */
4515 case 1: /* VSRA */
4516 if (u)
4517 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4518 else
4519 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4520 break;
4521 case 2: /* VRSHR */
4522 case 3: /* VRSRA */
4523 if (u)
4524 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4525 else
4526 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4527 break;
4528 case 4: /* VSRI */
4529 if (!u)
4530 return 1;
4531 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4532 break;
4533 case 5: /* VSHL, VSLI */
4534 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4535 break;
4536 case 6: /* VQSHL */
4537 if (u)
4538 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4539 else
4540 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4541 break;
4542 case 7: /* VQSHLU */
4543 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4544 break;
4546 if (op == 1 || op == 3) {
4547 /* Accumulate. */
4548 neon_load_reg64(cpu_V0, rd + pass);
4549 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4550 } else if (op == 4 || (op == 5 && u)) {
4551 /* Insert */
4552 cpu_abort(env, "VS[LR]I.64 not implemented");
4554 neon_store_reg64(cpu_V0, rd + pass);
4555 } else { /* size < 3 */
4556 /* Operands in T0 and T1. */
4557 gen_op_movl_T1_im(imm);
4558 NEON_GET_REG(T0, rm, pass);
4559 switch (op) {
4560 case 0: /* VSHR */
4561 case 1: /* VSRA */
4562 GEN_NEON_INTEGER_OP(shl);
4563 break;
4564 case 2: /* VRSHR */
4565 case 3: /* VRSRA */
4566 GEN_NEON_INTEGER_OP(rshl);
4567 break;
4568 case 4: /* VSRI */
4569 if (!u)
4570 return 1;
4571 GEN_NEON_INTEGER_OP(shl);
4572 break;
4573 case 5: /* VSHL, VSLI */
4574 switch (size) {
4575 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4576 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4577 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4578 default: return 1;
4580 break;
4581 case 6: /* VQSHL */
4582 GEN_NEON_INTEGER_OP_ENV(qshl);
4583 break;
4584 case 7: /* VQSHLU */
4585 switch (size) {
4586 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4587 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4588 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4589 default: return 1;
4591 break;
4594 if (op == 1 || op == 3) {
4595 /* Accumulate. */
4596 NEON_GET_REG(T1, rd, pass);
4597 gen_neon_add(size);
4598 } else if (op == 4 || (op == 5 && u)) {
4599 /* Insert */
4600 switch (size) {
4601 case 0:
4602 if (op == 4)
4603 imm = 0xff >> -shift;
4604 else
4605 imm = (uint8_t)(0xff << shift);
4606 imm |= imm << 8;
4607 imm |= imm << 16;
4608 break;
4609 case 1:
4610 if (op == 4)
4611 imm = 0xffff >> -shift;
4612 else
4613 imm = (uint16_t)(0xffff << shift);
4614 imm |= imm << 16;
4615 break;
4616 case 2:
4617 if (op == 4)
4618 imm = 0xffffffffu >> -shift;
4619 else
4620 imm = 0xffffffffu << shift;
4621 break;
4622 default:
4623 abort();
4625 tmp = neon_load_reg(rd, pass);
4626 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4627 tcg_gen_andi_i32(tmp, tmp, ~imm);
4628 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4630 NEON_SET_REG(T0, rd, pass);
4632 } /* for pass */
4633 } else if (op < 10) {
4634 /* Shift by immediate and narrow:
4635 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4636 shift = shift - (1 << (size + 3));
4637 size++;
4638 switch (size) {
4639 case 1:
4640 imm = (uint16_t)shift;
4641 imm |= imm << 16;
4642 tmp2 = tcg_const_i32(imm);
4643 TCGV_UNUSED_I64(tmp64);
4644 break;
4645 case 2:
4646 imm = (uint32_t)shift;
4647 tmp2 = tcg_const_i32(imm);
4648 TCGV_UNUSED_I64(tmp64);
4649 break;
4650 case 3:
4651 tmp64 = tcg_const_i64(shift);
4652 TCGV_UNUSED(tmp2);
4653 break;
4654 default:
4655 abort();
4658 for (pass = 0; pass < 2; pass++) {
4659 if (size == 3) {
4660 neon_load_reg64(cpu_V0, rm + pass);
4661 if (q) {
4662 if (u)
4663 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4664 else
4665 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4666 } else {
4667 if (u)
4668 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4669 else
4670 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4672 } else {
4673 tmp = neon_load_reg(rm + pass, 0);
4674 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4675 tmp3 = neon_load_reg(rm + pass, 1);
4676 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4677 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4678 dead_tmp(tmp);
4679 dead_tmp(tmp3);
4681 tmp = new_tmp();
4682 if (op == 8 && !u) {
4683 gen_neon_narrow(size - 1, tmp, cpu_V0);
4684 } else {
4685 if (op == 8)
4686 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4687 else
4688 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4690 if (pass == 0) {
4691 tmp2 = tmp;
4692 } else {
4693 neon_store_reg(rd, 0, tmp2);
4694 neon_store_reg(rd, 1, tmp);
4696 } /* for pass */
4697 } else if (op == 10) {
4698 /* VSHLL */
4699 if (q || size == 3)
4700 return 1;
4701 tmp = neon_load_reg(rm, 0);
4702 tmp2 = neon_load_reg(rm, 1);
4703 for (pass = 0; pass < 2; pass++) {
4704 if (pass == 1)
4705 tmp = tmp2;
4707 gen_neon_widen(cpu_V0, tmp, size, u);
4709 if (shift != 0) {
4710 /* The shift is less than the width of the source
4711 type, so we can just shift the whole register. */
4712 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4713 if (size < 2 || !u) {
4714 uint64_t imm64;
4715 if (size == 0) {
4716 imm = (0xffu >> (8 - shift));
4717 imm |= imm << 16;
4718 } else {
4719 imm = 0xffff >> (16 - shift);
4721 imm64 = imm | (((uint64_t)imm) << 32);
4722 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4725 neon_store_reg64(cpu_V0, rd + pass);
4727 } else if (op == 15 || op == 16) {
4728 /* VCVT fixed-point. */
4729 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4730 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4731 if (op & 1) {
4732 if (u)
4733 gen_vfp_ulto(0, shift);
4734 else
4735 gen_vfp_slto(0, shift);
4736 } else {
4737 if (u)
4738 gen_vfp_toul(0, shift);
4739 else
4740 gen_vfp_tosl(0, shift);
4742 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4744 } else {
4745 return 1;
4747 } else { /* (insn & 0x00380080) == 0 */
4748 int invert;
4750 op = (insn >> 8) & 0xf;
4751 /* One register and immediate. */
4752 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4753 invert = (insn & (1 << 5)) != 0;
4754 switch (op) {
4755 case 0: case 1:
4756 /* no-op */
4757 break;
4758 case 2: case 3:
4759 imm <<= 8;
4760 break;
4761 case 4: case 5:
4762 imm <<= 16;
4763 break;
4764 case 6: case 7:
4765 imm <<= 24;
4766 break;
4767 case 8: case 9:
4768 imm |= imm << 16;
4769 break;
4770 case 10: case 11:
4771 imm = (imm << 8) | (imm << 24);
4772 break;
4773 case 12:
4774 imm = (imm < 8) | 0xff;
4775 break;
4776 case 13:
4777 imm = (imm << 16) | 0xffff;
4778 break;
4779 case 14:
4780 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4781 if (invert)
4782 imm = ~imm;
4783 break;
4784 case 15:
4785 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4786 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4787 break;
4789 if (invert)
4790 imm = ~imm;
4792 if (op != 14 || !invert)
4793 gen_op_movl_T1_im(imm);
4795 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4796 if (op & 1 && op < 12) {
4797 tmp = neon_load_reg(rd, pass);
4798 if (invert) {
4799 /* The immediate value has already been inverted, so
4800 BIC becomes AND. */
4801 tcg_gen_andi_i32(tmp, tmp, imm);
4802 } else {
4803 tcg_gen_ori_i32(tmp, tmp, imm);
4805 } else {
4806 /* VMOV, VMVN. */
4807 tmp = new_tmp();
4808 if (op == 14 && invert) {
4809 uint32_t val;
4810 val = 0;
4811 for (n = 0; n < 4; n++) {
4812 if (imm & (1 << (n + (pass & 1) * 4)))
4813 val |= 0xff << (n * 8);
4815 tcg_gen_movi_i32(tmp, val);
4816 } else {
4817 tcg_gen_movi_i32(tmp, imm);
4820 neon_store_reg(rd, pass, tmp);
4823 } else { /* (insn & 0x00800010 == 0x00800000) */
4824 if (size != 3) {
4825 op = (insn >> 8) & 0xf;
4826 if ((insn & (1 << 6)) == 0) {
4827 /* Three registers of different lengths. */
4828 int src1_wide;
4829 int src2_wide;
4830 int prewiden;
4831 /* prewiden, src1_wide, src2_wide */
4832 static const int neon_3reg_wide[16][3] = {
4833 {1, 0, 0}, /* VADDL */
4834 {1, 1, 0}, /* VADDW */
4835 {1, 0, 0}, /* VSUBL */
4836 {1, 1, 0}, /* VSUBW */
4837 {0, 1, 1}, /* VADDHN */
4838 {0, 0, 0}, /* VABAL */
4839 {0, 1, 1}, /* VSUBHN */
4840 {0, 0, 0}, /* VABDL */
4841 {0, 0, 0}, /* VMLAL */
4842 {0, 0, 0}, /* VQDMLAL */
4843 {0, 0, 0}, /* VMLSL */
4844 {0, 0, 0}, /* VQDMLSL */
4845 {0, 0, 0}, /* Integer VMULL */
4846 {0, 0, 0}, /* VQDMULL */
4847 {0, 0, 0} /* Polynomial VMULL */
4850 prewiden = neon_3reg_wide[op][0];
4851 src1_wide = neon_3reg_wide[op][1];
4852 src2_wide = neon_3reg_wide[op][2];
4854 if (size == 0 && (op == 9 || op == 11 || op == 13))
4855 return 1;
4857 /* Avoid overlapping operands. Wide source operands are
4858 always aligned so will never overlap with wide
4859 destinations in problematic ways. */
4860 if (rd == rm && !src2_wide) {
4861 NEON_GET_REG(T0, rm, 1);
4862 gen_neon_movl_scratch_T0(2);
4863 } else if (rd == rn && !src1_wide) {
4864 NEON_GET_REG(T0, rn, 1);
4865 gen_neon_movl_scratch_T0(2);
4867 TCGV_UNUSED(tmp3);
4868 for (pass = 0; pass < 2; pass++) {
4869 if (src1_wide) {
4870 neon_load_reg64(cpu_V0, rn + pass);
4871 TCGV_UNUSED(tmp);
4872 } else {
4873 if (pass == 1 && rd == rn) {
4874 gen_neon_movl_T0_scratch(2);
4875 tmp = new_tmp();
4876 tcg_gen_mov_i32(tmp, cpu_T[0]);
4877 } else {
4878 tmp = neon_load_reg(rn, pass);
4880 if (prewiden) {
4881 gen_neon_widen(cpu_V0, tmp, size, u);
4884 if (src2_wide) {
4885 neon_load_reg64(cpu_V1, rm + pass);
4886 TCGV_UNUSED(tmp2);
4887 } else {
4888 if (pass == 1 && rd == rm) {
4889 gen_neon_movl_T0_scratch(2);
4890 tmp2 = new_tmp();
4891 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4892 } else {
4893 tmp2 = neon_load_reg(rm, pass);
4895 if (prewiden) {
4896 gen_neon_widen(cpu_V1, tmp2, size, u);
4899 switch (op) {
4900 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4901 gen_neon_addl(size);
4902 break;
4903 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4904 gen_neon_subl(size);
4905 break;
4906 case 5: case 7: /* VABAL, VABDL */
4907 switch ((size << 1) | u) {
4908 case 0:
4909 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4910 break;
4911 case 1:
4912 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4913 break;
4914 case 2:
4915 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4916 break;
4917 case 3:
4918 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4919 break;
4920 case 4:
4921 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4922 break;
4923 case 5:
4924 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4925 break;
4926 default: abort();
4928 dead_tmp(tmp2);
4929 dead_tmp(tmp);
4930 break;
4931 case 8: case 9: case 10: case 11: case 12: case 13:
4932 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4933 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4934 break;
4935 case 14: /* Polynomial VMULL */
4936 cpu_abort(env, "Polynomial VMULL not implemented");
4938 default: /* 15 is RESERVED. */
4939 return 1;
4941 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4942 /* Accumulate. */
4943 if (op == 10 || op == 11) {
4944 gen_neon_negl(cpu_V0, size);
4947 if (op != 13) {
4948 neon_load_reg64(cpu_V1, rd + pass);
4951 switch (op) {
4952 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4953 gen_neon_addl(size);
4954 break;
4955 case 9: case 11: /* VQDMLAL, VQDMLSL */
4956 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4957 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4958 break;
4959 /* Fall through. */
4960 case 13: /* VQDMULL */
4961 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4962 break;
4963 default:
4964 abort();
4966 neon_store_reg64(cpu_V0, rd + pass);
4967 } else if (op == 4 || op == 6) {
4968 /* Narrowing operation. */
4969 tmp = new_tmp();
4970 if (u) {
4971 switch (size) {
4972 case 0:
4973 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4974 break;
4975 case 1:
4976 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4977 break;
4978 case 2:
4979 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4980 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4981 break;
4982 default: abort();
4984 } else {
4985 switch (size) {
4986 case 0:
4987 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4988 break;
4989 case 1:
4990 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4991 break;
4992 case 2:
4993 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4994 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4995 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4996 break;
4997 default: abort();
5000 if (pass == 0) {
5001 tmp3 = tmp;
5002 } else {
5003 neon_store_reg(rd, 0, tmp3);
5004 neon_store_reg(rd, 1, tmp);
5006 } else {
5007 /* Write back the result. */
5008 neon_store_reg64(cpu_V0, rd + pass);
5011 } else {
5012 /* Two registers and a scalar. */
5013 switch (op) {
5014 case 0: /* Integer VMLA scalar */
5015 case 1: /* Float VMLA scalar */
5016 case 4: /* Integer VMLS scalar */
5017 case 5: /* Floating point VMLS scalar */
5018 case 8: /* Integer VMUL scalar */
5019 case 9: /* Floating point VMUL scalar */
5020 case 12: /* VQDMULH scalar */
5021 case 13: /* VQRDMULH scalar */
5022 gen_neon_get_scalar(size, rm);
5023 gen_neon_movl_scratch_T0(0);
5024 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5025 if (pass != 0)
5026 gen_neon_movl_T0_scratch(0);
5027 NEON_GET_REG(T1, rn, pass);
5028 if (op == 12) {
5029 if (size == 1) {
5030 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5031 } else {
5032 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5034 } else if (op == 13) {
5035 if (size == 1) {
5036 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5037 } else {
5038 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5040 } else if (op & 1) {
5041 gen_helper_neon_mul_f32(CPU_T001);
5042 } else {
5043 switch (size) {
5044 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5045 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5046 case 2: gen_op_mul_T0_T1(); break;
5047 default: return 1;
5050 if (op < 8) {
5051 /* Accumulate. */
5052 NEON_GET_REG(T1, rd, pass);
5053 switch (op) {
5054 case 0:
5055 gen_neon_add(size);
5056 break;
5057 case 1:
5058 gen_helper_neon_add_f32(CPU_T001);
5059 break;
5060 case 4:
5061 gen_neon_rsb(size);
5062 break;
5063 case 5:
5064 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5065 break;
5066 default:
5067 abort();
5070 NEON_SET_REG(T0, rd, pass);
5072 break;
5073 case 2: /* VMLAL sclar */
5074 case 3: /* VQDMLAL scalar */
5075 case 6: /* VMLSL scalar */
5076 case 7: /* VQDMLSL scalar */
5077 case 10: /* VMULL scalar */
5078 case 11: /* VQDMULL scalar */
5079 if (size == 0 && (op == 3 || op == 7 || op == 11))
5080 return 1;
5082 gen_neon_get_scalar(size, rm);
5083 NEON_GET_REG(T1, rn, 1);
5085 for (pass = 0; pass < 2; pass++) {
5086 if (pass == 0) {
5087 tmp = neon_load_reg(rn, 0);
5088 } else {
5089 tmp = new_tmp();
5090 tcg_gen_mov_i32(tmp, cpu_T[1]);
5092 tmp2 = new_tmp();
5093 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5094 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5095 if (op == 6 || op == 7) {
5096 gen_neon_negl(cpu_V0, size);
5098 if (op != 11) {
5099 neon_load_reg64(cpu_V1, rd + pass);
5101 switch (op) {
5102 case 2: case 6:
5103 gen_neon_addl(size);
5104 break;
5105 case 3: case 7:
5106 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5107 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5108 break;
5109 case 10:
5110 /* no-op */
5111 break;
5112 case 11:
5113 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5114 break;
5115 default:
5116 abort();
5118 neon_store_reg64(cpu_V0, rd + pass);
5120 break;
5121 default: /* 14 and 15 are RESERVED */
5122 return 1;
5125 } else { /* size == 3 */
5126 if (!u) {
5127 /* Extract. */
5128 imm = (insn >> 8) & 0xf;
5129 count = q + 1;
5131 if (imm > 7 && !q)
5132 return 1;
5134 if (imm == 0) {
5135 neon_load_reg64(cpu_V0, rn);
5136 if (q) {
5137 neon_load_reg64(cpu_V1, rn + 1);
5139 } else if (imm == 8) {
5140 neon_load_reg64(cpu_V0, rn + 1);
5141 if (q) {
5142 neon_load_reg64(cpu_V1, rm);
5144 } else if (q) {
5145 tmp64 = tcg_temp_new_i64();
5146 if (imm < 8) {
5147 neon_load_reg64(cpu_V0, rn);
5148 neon_load_reg64(tmp64, rn + 1);
5149 } else {
5150 neon_load_reg64(cpu_V0, rn + 1);
5151 neon_load_reg64(tmp64, rm);
5153 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5154 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5155 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5156 if (imm < 8) {
5157 neon_load_reg64(cpu_V1, rm);
5158 } else {
5159 neon_load_reg64(cpu_V1, rm + 1);
5160 imm -= 8;
5162 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5163 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5164 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5165 } else {
5166 /* BUGFIX */
5167 neon_load_reg64(cpu_V0, rn);
5168 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5169 neon_load_reg64(cpu_V1, rm);
5170 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5171 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5173 neon_store_reg64(cpu_V0, rd);
5174 if (q) {
5175 neon_store_reg64(cpu_V1, rd + 1);
5177 } else if ((insn & (1 << 11)) == 0) {
5178 /* Two register misc. */
5179 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5180 size = (insn >> 18) & 3;
5181 switch (op) {
5182 case 0: /* VREV64 */
5183 if (size == 3)
5184 return 1;
5185 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5186 NEON_GET_REG(T0, rm, pass * 2);
5187 NEON_GET_REG(T1, rm, pass * 2 + 1);
5188 switch (size) {
5189 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5190 case 1: gen_swap_half(cpu_T[0]); break;
5191 case 2: /* no-op */ break;
5192 default: abort();
5194 NEON_SET_REG(T0, rd, pass * 2 + 1);
5195 if (size == 2) {
5196 NEON_SET_REG(T1, rd, pass * 2);
5197 } else {
5198 gen_op_movl_T0_T1();
5199 switch (size) {
5200 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5201 case 1: gen_swap_half(cpu_T[0]); break;
5202 default: abort();
5204 NEON_SET_REG(T0, rd, pass * 2);
5207 break;
5208 case 4: case 5: /* VPADDL */
5209 case 12: case 13: /* VPADAL */
5210 if (size == 3)
5211 return 1;
5212 for (pass = 0; pass < q + 1; pass++) {
5213 tmp = neon_load_reg(rm, pass * 2);
5214 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5215 tmp = neon_load_reg(rm, pass * 2 + 1);
5216 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5217 switch (size) {
5218 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5219 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5220 case 2: tcg_gen_add_i64(CPU_V001); break;
5221 default: abort();
5223 if (op >= 12) {
5224 /* Accumulate. */
5225 neon_load_reg64(cpu_V1, rd + pass);
5226 gen_neon_addl(size);
5228 neon_store_reg64(cpu_V0, rd + pass);
5230 break;
5231 case 33: /* VTRN */
5232 if (size == 2) {
5233 for (n = 0; n < (q ? 4 : 2); n += 2) {
5234 NEON_GET_REG(T0, rm, n);
5235 NEON_GET_REG(T1, rd, n + 1);
5236 NEON_SET_REG(T1, rm, n);
5237 NEON_SET_REG(T0, rd, n + 1);
5239 } else {
5240 goto elementwise;
5242 break;
5243 case 34: /* VUZP */
5244 /* Reg Before After
5245 Rd A3 A2 A1 A0 B2 B0 A2 A0
5246 Rm B3 B2 B1 B0 B3 B1 A3 A1
5248 if (size == 3)
5249 return 1;
5250 gen_neon_unzip(rd, q, 0, size);
5251 gen_neon_unzip(rm, q, 4, size);
5252 if (q) {
5253 static int unzip_order_q[8] =
5254 {0, 2, 4, 6, 1, 3, 5, 7};
5255 for (n = 0; n < 8; n++) {
5256 int reg = (n < 4) ? rd : rm;
5257 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5258 NEON_SET_REG(T0, reg, n % 4);
5260 } else {
5261 static int unzip_order[4] =
5262 {0, 4, 1, 5};
5263 for (n = 0; n < 4; n++) {
5264 int reg = (n < 2) ? rd : rm;
5265 gen_neon_movl_T0_scratch(unzip_order[n]);
5266 NEON_SET_REG(T0, reg, n % 2);
5269 break;
5270 case 35: /* VZIP */
5271 /* Reg Before After
5272 Rd A3 A2 A1 A0 B1 A1 B0 A0
5273 Rm B3 B2 B1 B0 B3 A3 B2 A2
5275 if (size == 3)
5276 return 1;
5277 count = (q ? 4 : 2);
5278 for (n = 0; n < count; n++) {
5279 NEON_GET_REG(T0, rd, n);
5280 NEON_GET_REG(T1, rd, n);
5281 switch (size) {
5282 case 0: gen_helper_neon_zip_u8(); break;
5283 case 1: gen_helper_neon_zip_u16(); break;
5284 case 2: /* no-op */; break;
5285 default: abort();
5287 gen_neon_movl_scratch_T0(n * 2);
5288 gen_neon_movl_scratch_T1(n * 2 + 1);
5290 for (n = 0; n < count * 2; n++) {
5291 int reg = (n < count) ? rd : rm;
5292 gen_neon_movl_T0_scratch(n);
5293 NEON_SET_REG(T0, reg, n % count);
5295 break;
5296 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5297 if (size == 3)
5298 return 1;
5299 TCGV_UNUSED(tmp2);
5300 for (pass = 0; pass < 2; pass++) {
5301 neon_load_reg64(cpu_V0, rm + pass);
5302 tmp = new_tmp();
5303 if (op == 36 && q == 0) {
5304 gen_neon_narrow(size, tmp, cpu_V0);
5305 } else if (q) {
5306 gen_neon_narrow_satu(size, tmp, cpu_V0);
5307 } else {
5308 gen_neon_narrow_sats(size, tmp, cpu_V0);
5310 if (pass == 0) {
5311 tmp2 = tmp;
5312 } else {
5313 neon_store_reg(rd, 0, tmp2);
5314 neon_store_reg(rd, 1, tmp);
5317 break;
5318 case 38: /* VSHLL */
5319 if (q || size == 3)
5320 return 1;
5321 tmp = neon_load_reg(rm, 0);
5322 tmp2 = neon_load_reg(rm, 1);
5323 for (pass = 0; pass < 2; pass++) {
5324 if (pass == 1)
5325 tmp = tmp2;
5326 gen_neon_widen(cpu_V0, tmp, size, 1);
5327 neon_store_reg64(cpu_V0, rd + pass);
5329 break;
5330 default:
5331 elementwise:
5332 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5333 if (op == 30 || op == 31 || op >= 58) {
5334 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5335 neon_reg_offset(rm, pass));
5336 } else {
5337 NEON_GET_REG(T0, rm, pass);
5339 switch (op) {
5340 case 1: /* VREV32 */
5341 switch (size) {
5342 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5343 case 1: gen_swap_half(cpu_T[0]); break;
5344 default: return 1;
5346 break;
5347 case 2: /* VREV16 */
5348 if (size != 0)
5349 return 1;
5350 gen_rev16(cpu_T[0]);
5351 break;
5352 case 8: /* CLS */
5353 switch (size) {
5354 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5355 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5356 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5357 default: return 1;
5359 break;
5360 case 9: /* CLZ */
5361 switch (size) {
5362 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5363 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5364 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5365 default: return 1;
5367 break;
5368 case 10: /* CNT */
5369 if (size != 0)
5370 return 1;
5371 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5372 break;
5373 case 11: /* VNOT */
5374 if (size != 0)
5375 return 1;
5376 gen_op_notl_T0();
5377 break;
5378 case 14: /* VQABS */
5379 switch (size) {
5380 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5381 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5382 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5383 default: return 1;
5385 break;
5386 case 15: /* VQNEG */
5387 switch (size) {
5388 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5389 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5390 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5391 default: return 1;
5393 break;
5394 case 16: case 19: /* VCGT #0, VCLE #0 */
5395 gen_op_movl_T1_im(0);
5396 switch(size) {
5397 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5398 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5399 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5400 default: return 1;
5402 if (op == 19)
5403 gen_op_notl_T0();
5404 break;
5405 case 17: case 20: /* VCGE #0, VCLT #0 */
5406 gen_op_movl_T1_im(0);
5407 switch(size) {
5408 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5409 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5410 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5411 default: return 1;
5413 if (op == 20)
5414 gen_op_notl_T0();
5415 break;
5416 case 18: /* VCEQ #0 */
5417 gen_op_movl_T1_im(0);
5418 switch(size) {
5419 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5420 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5421 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5422 default: return 1;
5424 break;
5425 case 22: /* VABS */
5426 switch(size) {
5427 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5428 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5429 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5430 default: return 1;
5432 break;
5433 case 23: /* VNEG */
5434 gen_op_movl_T1_im(0);
5435 if (size == 3)
5436 return 1;
5437 gen_neon_rsb(size);
5438 break;
5439 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5440 gen_op_movl_T1_im(0);
5441 gen_helper_neon_cgt_f32(CPU_T001);
5442 if (op == 27)
5443 gen_op_notl_T0();
5444 break;
5445 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5446 gen_op_movl_T1_im(0);
5447 gen_helper_neon_cge_f32(CPU_T001);
5448 if (op == 28)
5449 gen_op_notl_T0();
5450 break;
5451 case 26: /* Float VCEQ #0 */
5452 gen_op_movl_T1_im(0);
5453 gen_helper_neon_ceq_f32(CPU_T001);
5454 break;
5455 case 30: /* Float VABS */
5456 gen_vfp_abs(0);
5457 break;
5458 case 31: /* Float VNEG */
5459 gen_vfp_neg(0);
5460 break;
5461 case 32: /* VSWP */
5462 NEON_GET_REG(T1, rd, pass);
5463 NEON_SET_REG(T1, rm, pass);
5464 break;
5465 case 33: /* VTRN */
5466 NEON_GET_REG(T1, rd, pass);
5467 switch (size) {
5468 case 0: gen_helper_neon_trn_u8(); break;
5469 case 1: gen_helper_neon_trn_u16(); break;
5470 case 2: abort();
5471 default: return 1;
5473 NEON_SET_REG(T1, rm, pass);
5474 break;
5475 case 56: /* Integer VRECPE */
5476 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5477 break;
5478 case 57: /* Integer VRSQRTE */
5479 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5480 break;
5481 case 58: /* Float VRECPE */
5482 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5483 break;
5484 case 59: /* Float VRSQRTE */
5485 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5486 break;
5487 case 60: /* VCVT.F32.S32 */
5488 gen_vfp_tosiz(0);
5489 break;
5490 case 61: /* VCVT.F32.U32 */
5491 gen_vfp_touiz(0);
5492 break;
5493 case 62: /* VCVT.S32.F32 */
5494 gen_vfp_sito(0);
5495 break;
5496 case 63: /* VCVT.U32.F32 */
5497 gen_vfp_uito(0);
5498 break;
5499 default:
5500 /* Reserved: 21, 29, 39-56 */
5501 return 1;
5503 if (op == 30 || op == 31 || op >= 58) {
5504 tcg_gen_st_f32(cpu_F0s, cpu_env,
5505 neon_reg_offset(rd, pass));
5506 } else {
5507 NEON_SET_REG(T0, rd, pass);
5510 break;
5512 } else if ((insn & (1 << 10)) == 0) {
5513 /* VTBL, VTBX. */
5514 n = ((insn >> 5) & 0x18) + 8;
5515 if (insn & (1 << 6)) {
5516 tmp = neon_load_reg(rd, 0);
5517 } else {
5518 tmp = new_tmp();
5519 tcg_gen_movi_i32(tmp, 0);
5521 tmp2 = neon_load_reg(rm, 0);
5522 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5523 tcg_const_i32(n));
5524 dead_tmp(tmp);
5525 if (insn & (1 << 6)) {
5526 tmp = neon_load_reg(rd, 1);
5527 } else {
5528 tmp = new_tmp();
5529 tcg_gen_movi_i32(tmp, 0);
5531 tmp3 = neon_load_reg(rm, 1);
5532 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5533 tcg_const_i32(n));
5534 neon_store_reg(rd, 0, tmp2);
5535 neon_store_reg(rd, 1, tmp3);
5536 dead_tmp(tmp);
5537 } else if ((insn & 0x380) == 0) {
5538 /* VDUP */
5539 if (insn & (1 << 19)) {
5540 NEON_SET_REG(T0, rm, 1);
5541 } else {
5542 NEON_SET_REG(T0, rm, 0);
5544 if (insn & (1 << 16)) {
5545 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5546 } else if (insn & (1 << 17)) {
5547 if ((insn >> 18) & 1)
5548 gen_neon_dup_high16(cpu_T[0]);
5549 else
5550 gen_neon_dup_low16(cpu_T[0]);
5552 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5553 NEON_SET_REG(T0, rd, pass);
5555 } else {
5556 return 1;
5560 return 0;
5563 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5565 int crn = (insn >> 16) & 0xf;
5566 int crm = insn & 0xf;
5567 int op1 = (insn >> 21) & 7;
5568 int op2 = (insn >> 5) & 7;
5569 int rt = (insn >> 12) & 0xf;
5570 TCGv tmp;
5572 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5573 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5574 /* TEECR */
5575 if (IS_USER(s))
5576 return 1;
5577 tmp = load_cpu_field(teecr);
5578 store_reg(s, rt, tmp);
5579 return 0;
5581 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5582 /* TEEHBR */
5583 if (IS_USER(s) && (env->teecr & 1))
5584 return 1;
5585 tmp = load_cpu_field(teehbr);
5586 store_reg(s, rt, tmp);
5587 return 0;
5590 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5591 op1, crn, crm, op2);
5592 return 1;
5595 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5597 int crn = (insn >> 16) & 0xf;
5598 int crm = insn & 0xf;
5599 int op1 = (insn >> 21) & 7;
5600 int op2 = (insn >> 5) & 7;
5601 int rt = (insn >> 12) & 0xf;
5602 TCGv tmp;
5604 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5605 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5606 /* TEECR */
5607 if (IS_USER(s))
5608 return 1;
5609 tmp = load_reg(s, rt);
5610 gen_helper_set_teecr(cpu_env, tmp);
5611 dead_tmp(tmp);
5612 return 0;
5614 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5615 /* TEEHBR */
5616 if (IS_USER(s) && (env->teecr & 1))
5617 return 1;
5618 tmp = load_reg(s, rt);
5619 store_cpu_field(tmp, teehbr);
5620 return 0;
5623 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5624 op1, crn, crm, op2);
5625 return 1;
5628 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5630 int cpnum;
5632 cpnum = (insn >> 8) & 0xf;
5633 if (arm_feature(env, ARM_FEATURE_XSCALE)
5634 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5635 return 1;
5637 switch (cpnum) {
5638 case 0:
5639 case 1:
5640 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5641 return disas_iwmmxt_insn(env, s, insn);
5642 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5643 return disas_dsp_insn(env, s, insn);
5645 return 1;
5646 case 10:
5647 case 11:
5648 return disas_vfp_insn (env, s, insn);
5649 case 14:
5650 /* Coprocessors 7-15 are architecturally reserved by ARM.
5651 Unfortunately Intel decided to ignore this. */
5652 if (arm_feature(env, ARM_FEATURE_XSCALE))
5653 goto board;
5654 if (insn & (1 << 20))
5655 return disas_cp14_read(env, s, insn);
5656 else
5657 return disas_cp14_write(env, s, insn);
5658 case 15:
5659 return disas_cp15_insn (env, s, insn);
5660 default:
5661 board:
5662 /* Unknown coprocessor. See if the board has hooked it. */
5663 return disas_cp_insn (env, s, insn);
5668 /* Store a 64-bit value to a register pair. Clobbers val. */
5669 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5671 TCGv tmp;
5672 tmp = new_tmp();
5673 tcg_gen_trunc_i64_i32(tmp, val);
5674 store_reg(s, rlow, tmp);
5675 tmp = new_tmp();
5676 tcg_gen_shri_i64(val, val, 32);
5677 tcg_gen_trunc_i64_i32(tmp, val);
5678 store_reg(s, rhigh, tmp);
5681 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5682 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5684 TCGv_i64 tmp;
5685 TCGv tmp2;
5687 /* Load value and extend to 64 bits. */
5688 tmp = tcg_temp_new_i64();
5689 tmp2 = load_reg(s, rlow);
5690 tcg_gen_extu_i32_i64(tmp, tmp2);
5691 dead_tmp(tmp2);
5692 tcg_gen_add_i64(val, val, tmp);
5695 /* load and add a 64-bit value from a register pair. */
5696 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5698 TCGv_i64 tmp;
5699 TCGv tmpl;
5700 TCGv tmph;
5702 /* Load 64-bit value rd:rn. */
5703 tmpl = load_reg(s, rlow);
5704 tmph = load_reg(s, rhigh);
5705 tmp = tcg_temp_new_i64();
5706 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5707 dead_tmp(tmpl);
5708 dead_tmp(tmph);
5709 tcg_gen_add_i64(val, val, tmp);
5712 /* Set N and Z flags from a 64-bit value. */
5713 static void gen_logicq_cc(TCGv_i64 val)
5715 TCGv tmp = new_tmp();
5716 gen_helper_logicq_cc(tmp, val);
5717 gen_logic_CC(tmp);
5718 dead_tmp(tmp);
5721 static void disas_arm_insn(CPUState * env, DisasContext *s)
5723 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5724 TCGv tmp;
5725 TCGv tmp2;
5726 TCGv tmp3;
5727 TCGv addr;
5728 TCGv_i64 tmp64;
5730 insn = ldl_code(s->pc);
5731 s->pc += 4;
5733 /* M variants do not implement ARM mode. */
5734 if (IS_M(env))
5735 goto illegal_op;
5736 cond = insn >> 28;
5737 if (cond == 0xf){
5738 /* Unconditional instructions. */
5739 if (((insn >> 25) & 7) == 1) {
5740 /* NEON Data processing. */
5741 if (!arm_feature(env, ARM_FEATURE_NEON))
5742 goto illegal_op;
5744 if (disas_neon_data_insn(env, s, insn))
5745 goto illegal_op;
5746 return;
5748 if ((insn & 0x0f100000) == 0x04000000) {
5749 /* NEON load/store. */
5750 if (!arm_feature(env, ARM_FEATURE_NEON))
5751 goto illegal_op;
5753 if (disas_neon_ls_insn(env, s, insn))
5754 goto illegal_op;
5755 return;
5757 if ((insn & 0x0d70f000) == 0x0550f000)
5758 return; /* PLD */
5759 else if ((insn & 0x0ffffdff) == 0x01010000) {
5760 ARCH(6);
5761 /* setend */
5762 if (insn & (1 << 9)) {
5763 /* BE8 mode not implemented. */
5764 goto illegal_op;
5766 return;
5767 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5768 switch ((insn >> 4) & 0xf) {
5769 case 1: /* clrex */
5770 ARCH(6K);
5771 gen_helper_clrex(cpu_env);
5772 return;
5773 case 4: /* dsb */
5774 case 5: /* dmb */
5775 case 6: /* isb */
5776 ARCH(7);
5777 /* We don't emulate caches so these are a no-op. */
5778 return;
5779 default:
5780 goto illegal_op;
5782 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5783 /* srs */
5784 uint32_t offset;
5785 if (IS_USER(s))
5786 goto illegal_op;
5787 ARCH(6);
5788 op1 = (insn & 0x1f);
5789 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5790 addr = load_reg(s, 13);
5791 } else {
5792 addr = new_tmp();
5793 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5795 i = (insn >> 23) & 3;
5796 switch (i) {
5797 case 0: offset = -4; break; /* DA */
5798 case 1: offset = -8; break; /* DB */
5799 case 2: offset = 0; break; /* IA */
5800 case 3: offset = 4; break; /* IB */
5801 default: abort();
5803 if (offset)
5804 tcg_gen_addi_i32(addr, addr, offset);
5805 tmp = load_reg(s, 14);
5806 gen_st32(tmp, addr, 0);
5807 tmp = new_tmp();
5808 gen_helper_cpsr_read(tmp);
5809 tcg_gen_addi_i32(addr, addr, 4);
5810 gen_st32(tmp, addr, 0);
5811 if (insn & (1 << 21)) {
5812 /* Base writeback. */
5813 switch (i) {
5814 case 0: offset = -8; break;
5815 case 1: offset = -4; break;
5816 case 2: offset = 4; break;
5817 case 3: offset = 0; break;
5818 default: abort();
5820 if (offset)
5821 tcg_gen_addi_i32(addr, tmp, offset);
5822 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5823 gen_movl_reg_T1(s, 13);
5824 } else {
5825 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5827 } else {
5828 dead_tmp(addr);
5830 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5831 /* rfe */
5832 uint32_t offset;
5833 if (IS_USER(s))
5834 goto illegal_op;
5835 ARCH(6);
5836 rn = (insn >> 16) & 0xf;
5837 addr = load_reg(s, rn);
5838 i = (insn >> 23) & 3;
5839 switch (i) {
5840 case 0: offset = -4; break; /* DA */
5841 case 1: offset = -8; break; /* DB */
5842 case 2: offset = 0; break; /* IA */
5843 case 3: offset = 4; break; /* IB */
5844 default: abort();
5846 if (offset)
5847 tcg_gen_addi_i32(addr, addr, offset);
5848 /* Load PC into tmp and CPSR into tmp2. */
5849 tmp = gen_ld32(addr, 0);
5850 tcg_gen_addi_i32(addr, addr, 4);
5851 tmp2 = gen_ld32(addr, 0);
5852 if (insn & (1 << 21)) {
5853 /* Base writeback. */
5854 switch (i) {
5855 case 0: offset = -8; break;
5856 case 1: offset = -4; break;
5857 case 2: offset = 4; break;
5858 case 3: offset = 0; break;
5859 default: abort();
5861 if (offset)
5862 tcg_gen_addi_i32(addr, addr, offset);
5863 store_reg(s, rn, addr);
5864 } else {
5865 dead_tmp(addr);
5867 gen_rfe(s, tmp, tmp2);
5868 } else if ((insn & 0x0e000000) == 0x0a000000) {
5869 /* branch link and change to thumb (blx <offset>) */
5870 int32_t offset;
5872 val = (uint32_t)s->pc;
5873 tmp = new_tmp();
5874 tcg_gen_movi_i32(tmp, val);
5875 store_reg(s, 14, tmp);
5876 /* Sign-extend the 24-bit offset */
5877 offset = (((int32_t)insn) << 8) >> 8;
5878 /* offset * 4 + bit24 * 2 + (thumb bit) */
5879 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5880 /* pipeline offset */
5881 val += 4;
5882 gen_bx_im(s, val);
5883 return;
5884 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5885 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5886 /* iWMMXt register transfer. */
5887 if (env->cp15.c15_cpar & (1 << 1))
5888 if (!disas_iwmmxt_insn(env, s, insn))
5889 return;
5891 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5892 /* Coprocessor double register transfer. */
5893 } else if ((insn & 0x0f000010) == 0x0e000010) {
5894 /* Additional coprocessor register transfer. */
5895 } else if ((insn & 0x0ff10020) == 0x01000000) {
5896 uint32_t mask;
5897 uint32_t val;
5898 /* cps (privileged) */
5899 if (IS_USER(s))
5900 return;
5901 mask = val = 0;
5902 if (insn & (1 << 19)) {
5903 if (insn & (1 << 8))
5904 mask |= CPSR_A;
5905 if (insn & (1 << 7))
5906 mask |= CPSR_I;
5907 if (insn & (1 << 6))
5908 mask |= CPSR_F;
5909 if (insn & (1 << 18))
5910 val |= mask;
5912 if (insn & (1 << 17)) {
5913 mask |= CPSR_M;
5914 val |= (insn & 0x1f);
5916 if (mask) {
5917 gen_op_movl_T0_im(val);
5918 gen_set_psr_T0(s, mask, 0);
5920 return;
5922 goto illegal_op;
5924 if (cond != 0xe) {
5925 /* if not always execute, we generate a conditional jump to
5926 next instruction */
5927 s->condlabel = gen_new_label();
5928 gen_test_cc(cond ^ 1, s->condlabel);
5929 s->condjmp = 1;
5931 if ((insn & 0x0f900000) == 0x03000000) {
5932 if ((insn & (1 << 21)) == 0) {
5933 ARCH(6T2);
5934 rd = (insn >> 12) & 0xf;
5935 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5936 if ((insn & (1 << 22)) == 0) {
5937 /* MOVW */
5938 tmp = new_tmp();
5939 tcg_gen_movi_i32(tmp, val);
5940 } else {
5941 /* MOVT */
5942 tmp = load_reg(s, rd);
5943 tcg_gen_ext16u_i32(tmp, tmp);
5944 tcg_gen_ori_i32(tmp, tmp, val << 16);
5946 store_reg(s, rd, tmp);
5947 } else {
5948 if (((insn >> 12) & 0xf) != 0xf)
5949 goto illegal_op;
5950 if (((insn >> 16) & 0xf) == 0) {
5951 gen_nop_hint(s, insn & 0xff);
5952 } else {
5953 /* CPSR = immediate */
5954 val = insn & 0xff;
5955 shift = ((insn >> 8) & 0xf) * 2;
5956 if (shift)
5957 val = (val >> shift) | (val << (32 - shift));
5958 gen_op_movl_T0_im(val);
5959 i = ((insn & (1 << 22)) != 0);
5960 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5961 goto illegal_op;
5964 } else if ((insn & 0x0f900000) == 0x01000000
5965 && (insn & 0x00000090) != 0x00000090) {
5966 /* miscellaneous instructions */
5967 op1 = (insn >> 21) & 3;
5968 sh = (insn >> 4) & 0xf;
5969 rm = insn & 0xf;
5970 switch (sh) {
5971 case 0x0: /* move program status register */
5972 if (op1 & 1) {
5973 /* PSR = reg */
5974 gen_movl_T0_reg(s, rm);
5975 i = ((op1 & 2) != 0);
5976 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5977 goto illegal_op;
5978 } else {
5979 /* reg = PSR */
5980 rd = (insn >> 12) & 0xf;
5981 if (op1 & 2) {
5982 if (IS_USER(s))
5983 goto illegal_op;
5984 tmp = load_cpu_field(spsr);
5985 } else {
5986 tmp = new_tmp();
5987 gen_helper_cpsr_read(tmp);
5989 store_reg(s, rd, tmp);
5991 break;
5992 case 0x1:
5993 if (op1 == 1) {
5994 /* branch/exchange thumb (bx). */
5995 tmp = load_reg(s, rm);
5996 gen_bx(s, tmp);
5997 } else if (op1 == 3) {
5998 /* clz */
5999 rd = (insn >> 12) & 0xf;
6000 tmp = load_reg(s, rm);
6001 gen_helper_clz(tmp, tmp);
6002 store_reg(s, rd, tmp);
6003 } else {
6004 goto illegal_op;
6006 break;
6007 case 0x2:
6008 if (op1 == 1) {
6009 ARCH(5J); /* bxj */
6010 /* Trivial implementation equivalent to bx. */
6011 tmp = load_reg(s, rm);
6012 gen_bx(s, tmp);
6013 } else {
6014 goto illegal_op;
6016 break;
6017 case 0x3:
6018 if (op1 != 1)
6019 goto illegal_op;
6021 /* branch link/exchange thumb (blx) */
6022 tmp = load_reg(s, rm);
6023 tmp2 = new_tmp();
6024 tcg_gen_movi_i32(tmp2, s->pc);
6025 store_reg(s, 14, tmp2);
6026 gen_bx(s, tmp);
6027 break;
6028 case 0x5: /* saturating add/subtract */
6029 rd = (insn >> 12) & 0xf;
6030 rn = (insn >> 16) & 0xf;
6031 tmp = load_reg(s, rm);
6032 tmp2 = load_reg(s, rn);
6033 if (op1 & 2)
6034 gen_helper_double_saturate(tmp2, tmp2);
6035 if (op1 & 1)
6036 gen_helper_sub_saturate(tmp, tmp, tmp2);
6037 else
6038 gen_helper_add_saturate(tmp, tmp, tmp2);
6039 dead_tmp(tmp2);
6040 store_reg(s, rd, tmp);
6041 break;
6042 case 7: /* bkpt */
6043 gen_set_condexec(s);
6044 gen_set_pc_im(s->pc - 4);
6045 gen_exception(EXCP_BKPT);
6046 s->is_jmp = DISAS_JUMP;
6047 break;
6048 case 0x8: /* signed multiply */
6049 case 0xa:
6050 case 0xc:
6051 case 0xe:
6052 rs = (insn >> 8) & 0xf;
6053 rn = (insn >> 12) & 0xf;
6054 rd = (insn >> 16) & 0xf;
6055 if (op1 == 1) {
6056 /* (32 * 16) >> 16 */
6057 tmp = load_reg(s, rm);
6058 tmp2 = load_reg(s, rs);
6059 if (sh & 4)
6060 tcg_gen_sari_i32(tmp2, tmp2, 16);
6061 else
6062 gen_sxth(tmp2);
6063 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6064 tcg_gen_shri_i64(tmp64, tmp64, 16);
6065 tmp = new_tmp();
6066 tcg_gen_trunc_i64_i32(tmp, tmp64);
6067 if ((sh & 2) == 0) {
6068 tmp2 = load_reg(s, rn);
6069 gen_helper_add_setq(tmp, tmp, tmp2);
6070 dead_tmp(tmp2);
6072 store_reg(s, rd, tmp);
6073 } else {
6074 /* 16 * 16 */
6075 tmp = load_reg(s, rm);
6076 tmp2 = load_reg(s, rs);
6077 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6078 dead_tmp(tmp2);
6079 if (op1 == 2) {
6080 tmp64 = tcg_temp_new_i64();
6081 tcg_gen_ext_i32_i64(tmp64, tmp);
6082 dead_tmp(tmp);
6083 gen_addq(s, tmp64, rn, rd);
6084 gen_storeq_reg(s, rn, rd, tmp64);
6085 } else {
6086 if (op1 == 0) {
6087 tmp2 = load_reg(s, rn);
6088 gen_helper_add_setq(tmp, tmp, tmp2);
6089 dead_tmp(tmp2);
6091 store_reg(s, rd, tmp);
6094 break;
6095 default:
6096 goto illegal_op;
6098 } else if (((insn & 0x0e000000) == 0 &&
6099 (insn & 0x00000090) != 0x90) ||
6100 ((insn & 0x0e000000) == (1 << 25))) {
6101 int set_cc, logic_cc, shiftop;
6103 op1 = (insn >> 21) & 0xf;
6104 set_cc = (insn >> 20) & 1;
6105 logic_cc = table_logic_cc[op1] & set_cc;
6107 /* data processing instruction */
6108 if (insn & (1 << 25)) {
6109 /* immediate operand */
6110 val = insn & 0xff;
6111 shift = ((insn >> 8) & 0xf) * 2;
6112 if (shift) {
6113 val = (val >> shift) | (val << (32 - shift));
6115 tmp2 = new_tmp();
6116 tcg_gen_movi_i32(tmp2, val);
6117 if (logic_cc && shift) {
6118 gen_set_CF_bit31(tmp2);
6120 } else {
6121 /* register */
6122 rm = (insn) & 0xf;
6123 tmp2 = load_reg(s, rm);
6124 shiftop = (insn >> 5) & 3;
6125 if (!(insn & (1 << 4))) {
6126 shift = (insn >> 7) & 0x1f;
6127 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6128 } else {
6129 rs = (insn >> 8) & 0xf;
6130 tmp = load_reg(s, rs);
6131 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6134 if (op1 != 0x0f && op1 != 0x0d) {
6135 rn = (insn >> 16) & 0xf;
6136 tmp = load_reg(s, rn);
6137 } else {
6138 TCGV_UNUSED(tmp);
6140 rd = (insn >> 12) & 0xf;
6141 switch(op1) {
6142 case 0x00:
6143 tcg_gen_and_i32(tmp, tmp, tmp2);
6144 if (logic_cc) {
6145 gen_logic_CC(tmp);
6147 store_reg_bx(env, s, rd, tmp);
6148 break;
6149 case 0x01:
6150 tcg_gen_xor_i32(tmp, tmp, tmp2);
6151 if (logic_cc) {
6152 gen_logic_CC(tmp);
6154 store_reg_bx(env, s, rd, tmp);
6155 break;
6156 case 0x02:
6157 if (set_cc && rd == 15) {
6158 /* SUBS r15, ... is used for exception return. */
6159 if (IS_USER(s)) {
6160 goto illegal_op;
6162 gen_helper_sub_cc(tmp, tmp, tmp2);
6163 gen_exception_return(s, tmp);
6164 } else {
6165 if (set_cc) {
6166 gen_helper_sub_cc(tmp, tmp, tmp2);
6167 } else {
6168 tcg_gen_sub_i32(tmp, tmp, tmp2);
6170 store_reg_bx(env, s, rd, tmp);
6172 break;
6173 case 0x03:
6174 if (set_cc) {
6175 gen_helper_sub_cc(tmp, tmp2, tmp);
6176 } else {
6177 tcg_gen_sub_i32(tmp, tmp2, tmp);
6179 store_reg_bx(env, s, rd, tmp);
6180 break;
6181 case 0x04:
6182 if (set_cc) {
6183 gen_helper_add_cc(tmp, tmp, tmp2);
6184 } else {
6185 tcg_gen_add_i32(tmp, tmp, tmp2);
6187 store_reg_bx(env, s, rd, tmp);
6188 break;
6189 case 0x05:
6190 if (set_cc) {
6191 gen_helper_adc_cc(tmp, tmp, tmp2);
6192 } else {
6193 gen_add_carry(tmp, tmp, tmp2);
6195 store_reg_bx(env, s, rd, tmp);
6196 break;
6197 case 0x06:
6198 if (set_cc) {
6199 gen_helper_sbc_cc(tmp, tmp, tmp2);
6200 } else {
6201 gen_sub_carry(tmp, tmp, tmp2);
6203 store_reg_bx(env, s, rd, tmp);
6204 break;
6205 case 0x07:
6206 if (set_cc) {
6207 gen_helper_sbc_cc(tmp, tmp2, tmp);
6208 } else {
6209 gen_sub_carry(tmp, tmp2, tmp);
6211 store_reg_bx(env, s, rd, tmp);
6212 break;
6213 case 0x08:
6214 if (set_cc) {
6215 tcg_gen_and_i32(tmp, tmp, tmp2);
6216 gen_logic_CC(tmp);
6218 dead_tmp(tmp);
6219 break;
6220 case 0x09:
6221 if (set_cc) {
6222 tcg_gen_xor_i32(tmp, tmp, tmp2);
6223 gen_logic_CC(tmp);
6225 dead_tmp(tmp);
6226 break;
6227 case 0x0a:
6228 if (set_cc) {
6229 gen_helper_sub_cc(tmp, tmp, tmp2);
6231 dead_tmp(tmp);
6232 break;
6233 case 0x0b:
6234 if (set_cc) {
6235 gen_helper_add_cc(tmp, tmp, tmp2);
6237 dead_tmp(tmp);
6238 break;
6239 case 0x0c:
6240 tcg_gen_or_i32(tmp, tmp, tmp2);
6241 if (logic_cc) {
6242 gen_logic_CC(tmp);
6244 store_reg_bx(env, s, rd, tmp);
6245 break;
6246 case 0x0d:
6247 if (logic_cc && rd == 15) {
6248 /* MOVS r15, ... is used for exception return. */
6249 if (IS_USER(s)) {
6250 goto illegal_op;
6252 gen_exception_return(s, tmp2);
6253 } else {
6254 if (logic_cc) {
6255 gen_logic_CC(tmp2);
6257 store_reg_bx(env, s, rd, tmp2);
6259 break;
6260 case 0x0e:
6261 tcg_gen_bic_i32(tmp, tmp, tmp2);
6262 if (logic_cc) {
6263 gen_logic_CC(tmp);
6265 store_reg_bx(env, s, rd, tmp);
6266 break;
6267 default:
6268 case 0x0f:
6269 tcg_gen_not_i32(tmp2, tmp2);
6270 if (logic_cc) {
6271 gen_logic_CC(tmp2);
6273 store_reg_bx(env, s, rd, tmp2);
6274 break;
6276 if (op1 != 0x0f && op1 != 0x0d) {
6277 dead_tmp(tmp2);
6279 } else {
6280 /* other instructions */
6281 op1 = (insn >> 24) & 0xf;
6282 switch(op1) {
6283 case 0x0:
6284 case 0x1:
6285 /* multiplies, extra load/stores */
6286 sh = (insn >> 5) & 3;
6287 if (sh == 0) {
6288 if (op1 == 0x0) {
6289 rd = (insn >> 16) & 0xf;
6290 rn = (insn >> 12) & 0xf;
6291 rs = (insn >> 8) & 0xf;
6292 rm = (insn) & 0xf;
6293 op1 = (insn >> 20) & 0xf;
6294 switch (op1) {
6295 case 0: case 1: case 2: case 3: case 6:
6296 /* 32 bit mul */
6297 tmp = load_reg(s, rs);
6298 tmp2 = load_reg(s, rm);
6299 tcg_gen_mul_i32(tmp, tmp, tmp2);
6300 dead_tmp(tmp2);
6301 if (insn & (1 << 22)) {
6302 /* Subtract (mls) */
6303 ARCH(6T2);
6304 tmp2 = load_reg(s, rn);
6305 tcg_gen_sub_i32(tmp, tmp2, tmp);
6306 dead_tmp(tmp2);
6307 } else if (insn & (1 << 21)) {
6308 /* Add */
6309 tmp2 = load_reg(s, rn);
6310 tcg_gen_add_i32(tmp, tmp, tmp2);
6311 dead_tmp(tmp2);
6313 if (insn & (1 << 20))
6314 gen_logic_CC(tmp);
6315 store_reg(s, rd, tmp);
6316 break;
6317 default:
6318 /* 64 bit mul */
6319 tmp = load_reg(s, rs);
6320 tmp2 = load_reg(s, rm);
6321 if (insn & (1 << 22))
6322 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6323 else
6324 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6325 if (insn & (1 << 21)) /* mult accumulate */
6326 gen_addq(s, tmp64, rn, rd);
6327 if (!(insn & (1 << 23))) { /* double accumulate */
6328 ARCH(6);
6329 gen_addq_lo(s, tmp64, rn);
6330 gen_addq_lo(s, tmp64, rd);
6332 if (insn & (1 << 20))
6333 gen_logicq_cc(tmp64);
6334 gen_storeq_reg(s, rn, rd, tmp64);
6335 break;
6337 } else {
6338 rn = (insn >> 16) & 0xf;
6339 rd = (insn >> 12) & 0xf;
6340 if (insn & (1 << 23)) {
6341 /* load/store exclusive */
6342 op1 = (insn >> 21) & 0x3;
6343 if (op1)
6344 ARCH(6K);
6345 else
6346 ARCH(6);
6347 gen_movl_T1_reg(s, rn);
6348 addr = cpu_T[1];
6349 if (insn & (1 << 20)) {
6350 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6351 switch (op1) {
6352 case 0: /* ldrex */
6353 tmp = gen_ld32(addr, IS_USER(s));
6354 break;
6355 case 1: /* ldrexd */
6356 tmp = gen_ld32(addr, IS_USER(s));
6357 store_reg(s, rd, tmp);
6358 tcg_gen_addi_i32(addr, addr, 4);
6359 tmp = gen_ld32(addr, IS_USER(s));
6360 rd++;
6361 break;
6362 case 2: /* ldrexb */
6363 tmp = gen_ld8u(addr, IS_USER(s));
6364 break;
6365 case 3: /* ldrexh */
6366 tmp = gen_ld16u(addr, IS_USER(s));
6367 break;
6368 default:
6369 abort();
6371 store_reg(s, rd, tmp);
6372 } else {
6373 int label = gen_new_label();
6374 rm = insn & 0xf;
6375 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6376 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6377 0, label);
6378 tmp = load_reg(s,rm);
6379 switch (op1) {
6380 case 0: /* strex */
6381 gen_st32(tmp, addr, IS_USER(s));
6382 break;
6383 case 1: /* strexd */
6384 gen_st32(tmp, addr, IS_USER(s));
6385 tcg_gen_addi_i32(addr, addr, 4);
6386 tmp = load_reg(s, rm + 1);
6387 gen_st32(tmp, addr, IS_USER(s));
6388 break;
6389 case 2: /* strexb */
6390 gen_st8(tmp, addr, IS_USER(s));
6391 break;
6392 case 3: /* strexh */
6393 gen_st16(tmp, addr, IS_USER(s));
6394 break;
6395 default:
6396 abort();
6398 gen_set_label(label);
6399 gen_movl_reg_T0(s, rd);
6401 } else {
6402 /* SWP instruction */
6403 rm = (insn) & 0xf;
6405 /* ??? This is not really atomic. However we know
6406 we never have multiple CPUs running in parallel,
6407 so it is good enough. */
6408 addr = load_reg(s, rn);
6409 tmp = load_reg(s, rm);
6410 if (insn & (1 << 22)) {
6411 tmp2 = gen_ld8u(addr, IS_USER(s));
6412 gen_st8(tmp, addr, IS_USER(s));
6413 } else {
6414 tmp2 = gen_ld32(addr, IS_USER(s));
6415 gen_st32(tmp, addr, IS_USER(s));
6417 dead_tmp(addr);
6418 store_reg(s, rd, tmp2);
6421 } else {
6422 int address_offset;
6423 int load;
6424 /* Misc load/store */
6425 rn = (insn >> 16) & 0xf;
6426 rd = (insn >> 12) & 0xf;
6427 addr = load_reg(s, rn);
6428 if (insn & (1 << 24))
6429 gen_add_datah_offset(s, insn, 0, addr);
6430 address_offset = 0;
6431 if (insn & (1 << 20)) {
6432 /* load */
6433 switch(sh) {
6434 case 1:
6435 tmp = gen_ld16u(addr, IS_USER(s));
6436 break;
6437 case 2:
6438 tmp = gen_ld8s(addr, IS_USER(s));
6439 break;
6440 default:
6441 case 3:
6442 tmp = gen_ld16s(addr, IS_USER(s));
6443 break;
6445 load = 1;
6446 } else if (sh & 2) {
6447 /* doubleword */
6448 if (sh & 1) {
6449 /* store */
6450 tmp = load_reg(s, rd);
6451 gen_st32(tmp, addr, IS_USER(s));
6452 tcg_gen_addi_i32(addr, addr, 4);
6453 tmp = load_reg(s, rd + 1);
6454 gen_st32(tmp, addr, IS_USER(s));
6455 load = 0;
6456 } else {
6457 /* load */
6458 tmp = gen_ld32(addr, IS_USER(s));
6459 store_reg(s, rd, tmp);
6460 tcg_gen_addi_i32(addr, addr, 4);
6461 tmp = gen_ld32(addr, IS_USER(s));
6462 rd++;
6463 load = 1;
6465 address_offset = -4;
6466 } else {
6467 /* store */
6468 tmp = load_reg(s, rd);
6469 gen_st16(tmp, addr, IS_USER(s));
6470 load = 0;
6472 /* Perform base writeback before the loaded value to
6473 ensure correct behavior with overlapping index registers.
6474 ldrd with base writeback is is undefined if the
6475 destination and index registers overlap. */
6476 if (!(insn & (1 << 24))) {
6477 gen_add_datah_offset(s, insn, address_offset, addr);
6478 store_reg(s, rn, addr);
6479 } else if (insn & (1 << 21)) {
6480 if (address_offset)
6481 tcg_gen_addi_i32(addr, addr, address_offset);
6482 store_reg(s, rn, addr);
6483 } else {
6484 dead_tmp(addr);
6486 if (load) {
6487 /* Complete the load. */
6488 store_reg(s, rd, tmp);
6491 break;
6492 case 0x4:
6493 case 0x5:
6494 goto do_ldst;
6495 case 0x6:
6496 case 0x7:
6497 if (insn & (1 << 4)) {
6498 ARCH(6);
6499 /* Armv6 Media instructions. */
6500 rm = insn & 0xf;
6501 rn = (insn >> 16) & 0xf;
6502 rd = (insn >> 12) & 0xf;
6503 rs = (insn >> 8) & 0xf;
6504 switch ((insn >> 23) & 3) {
6505 case 0: /* Parallel add/subtract. */
6506 op1 = (insn >> 20) & 7;
6507 tmp = load_reg(s, rn);
6508 tmp2 = load_reg(s, rm);
6509 sh = (insn >> 5) & 7;
6510 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6511 goto illegal_op;
6512 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6513 dead_tmp(tmp2);
6514 store_reg(s, rd, tmp);
6515 break;
6516 case 1:
6517 if ((insn & 0x00700020) == 0) {
6518 /* Halfword pack. */
6519 tmp = load_reg(s, rn);
6520 tmp2 = load_reg(s, rm);
6521 shift = (insn >> 7) & 0x1f;
6522 if (insn & (1 << 6)) {
6523 /* pkhtb */
6524 if (shift == 0)
6525 shift = 31;
6526 tcg_gen_sari_i32(tmp2, tmp2, shift);
6527 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6528 tcg_gen_ext16u_i32(tmp2, tmp2);
6529 } else {
6530 /* pkhbt */
6531 if (shift)
6532 tcg_gen_shli_i32(tmp2, tmp2, shift);
6533 tcg_gen_ext16u_i32(tmp, tmp);
6534 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6536 tcg_gen_or_i32(tmp, tmp, tmp2);
6537 dead_tmp(tmp2);
6538 store_reg(s, rd, tmp);
6539 } else if ((insn & 0x00200020) == 0x00200000) {
6540 /* [us]sat */
6541 tmp = load_reg(s, rm);
6542 shift = (insn >> 7) & 0x1f;
6543 if (insn & (1 << 6)) {
6544 if (shift == 0)
6545 shift = 31;
6546 tcg_gen_sari_i32(tmp, tmp, shift);
6547 } else {
6548 tcg_gen_shli_i32(tmp, tmp, shift);
6550 sh = (insn >> 16) & 0x1f;
6551 if (sh != 0) {
6552 if (insn & (1 << 22))
6553 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6554 else
6555 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6557 store_reg(s, rd, tmp);
6558 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6559 /* [us]sat16 */
6560 tmp = load_reg(s, rm);
6561 sh = (insn >> 16) & 0x1f;
6562 if (sh != 0) {
6563 if (insn & (1 << 22))
6564 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6565 else
6566 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6568 store_reg(s, rd, tmp);
6569 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6570 /* Select bytes. */
6571 tmp = load_reg(s, rn);
6572 tmp2 = load_reg(s, rm);
6573 tmp3 = new_tmp();
6574 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6575 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6576 dead_tmp(tmp3);
6577 dead_tmp(tmp2);
6578 store_reg(s, rd, tmp);
6579 } else if ((insn & 0x000003e0) == 0x00000060) {
6580 tmp = load_reg(s, rm);
6581 shift = (insn >> 10) & 3;
6582 /* ??? In many cases it's not neccessary to do a
6583 rotate, a shift is sufficient. */
6584 if (shift != 0)
6585 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6586 op1 = (insn >> 20) & 7;
6587 switch (op1) {
6588 case 0: gen_sxtb16(tmp); break;
6589 case 2: gen_sxtb(tmp); break;
6590 case 3: gen_sxth(tmp); break;
6591 case 4: gen_uxtb16(tmp); break;
6592 case 6: gen_uxtb(tmp); break;
6593 case 7: gen_uxth(tmp); break;
6594 default: goto illegal_op;
6596 if (rn != 15) {
6597 tmp2 = load_reg(s, rn);
6598 if ((op1 & 3) == 0) {
6599 gen_add16(tmp, tmp2);
6600 } else {
6601 tcg_gen_add_i32(tmp, tmp, tmp2);
6602 dead_tmp(tmp2);
6605 store_reg(s, rd, tmp);
6606 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6607 /* rev */
6608 tmp = load_reg(s, rm);
6609 if (insn & (1 << 22)) {
6610 if (insn & (1 << 7)) {
6611 gen_revsh(tmp);
6612 } else {
6613 ARCH(6T2);
6614 gen_helper_rbit(tmp, tmp);
6616 } else {
6617 if (insn & (1 << 7))
6618 gen_rev16(tmp);
6619 else
6620 tcg_gen_bswap32_i32(tmp, tmp);
6622 store_reg(s, rd, tmp);
6623 } else {
6624 goto illegal_op;
6626 break;
6627 case 2: /* Multiplies (Type 3). */
6628 tmp = load_reg(s, rm);
6629 tmp2 = load_reg(s, rs);
6630 if (insn & (1 << 20)) {
6631 /* Signed multiply most significant [accumulate]. */
6632 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6633 if (insn & (1 << 5))
6634 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6635 tcg_gen_shri_i64(tmp64, tmp64, 32);
6636 tmp = new_tmp();
6637 tcg_gen_trunc_i64_i32(tmp, tmp64);
6638 if (rd != 15) {
6639 tmp2 = load_reg(s, rd);
6640 if (insn & (1 << 6)) {
6641 tcg_gen_sub_i32(tmp, tmp, tmp2);
6642 } else {
6643 tcg_gen_add_i32(tmp, tmp, tmp2);
6645 dead_tmp(tmp2);
6647 store_reg(s, rn, tmp);
6648 } else {
6649 if (insn & (1 << 5))
6650 gen_swap_half(tmp2);
6651 gen_smul_dual(tmp, tmp2);
6652 /* This addition cannot overflow. */
6653 if (insn & (1 << 6)) {
6654 tcg_gen_sub_i32(tmp, tmp, tmp2);
6655 } else {
6656 tcg_gen_add_i32(tmp, tmp, tmp2);
6658 dead_tmp(tmp2);
6659 if (insn & (1 << 22)) {
6660 /* smlald, smlsld */
6661 tmp64 = tcg_temp_new_i64();
6662 tcg_gen_ext_i32_i64(tmp64, tmp);
6663 dead_tmp(tmp);
6664 gen_addq(s, tmp64, rd, rn);
6665 gen_storeq_reg(s, rd, rn, tmp64);
6666 } else {
6667 /* smuad, smusd, smlad, smlsd */
6668 if (rd != 15)
6670 tmp2 = load_reg(s, rd);
6671 gen_helper_add_setq(tmp, tmp, tmp2);
6672 dead_tmp(tmp2);
6674 store_reg(s, rn, tmp);
6677 break;
6678 case 3:
6679 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6680 switch (op1) {
6681 case 0: /* Unsigned sum of absolute differences. */
6682 ARCH(6);
6683 tmp = load_reg(s, rm);
6684 tmp2 = load_reg(s, rs);
6685 gen_helper_usad8(tmp, tmp, tmp2);
6686 dead_tmp(tmp2);
6687 if (rd != 15) {
6688 tmp2 = load_reg(s, rd);
6689 tcg_gen_add_i32(tmp, tmp, tmp2);
6690 dead_tmp(tmp2);
6692 store_reg(s, rn, tmp);
6693 break;
6694 case 0x20: case 0x24: case 0x28: case 0x2c:
6695 /* Bitfield insert/clear. */
6696 ARCH(6T2);
6697 shift = (insn >> 7) & 0x1f;
6698 i = (insn >> 16) & 0x1f;
6699 i = i + 1 - shift;
6700 if (rm == 15) {
6701 tmp = new_tmp();
6702 tcg_gen_movi_i32(tmp, 0);
6703 } else {
6704 tmp = load_reg(s, rm);
6706 if (i != 32) {
6707 tmp2 = load_reg(s, rd);
6708 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6709 dead_tmp(tmp2);
6711 store_reg(s, rd, tmp);
6712 break;
6713 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6714 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6715 ARCH(6T2);
6716 tmp = load_reg(s, rm);
6717 shift = (insn >> 7) & 0x1f;
6718 i = ((insn >> 16) & 0x1f) + 1;
6719 if (shift + i > 32)
6720 goto illegal_op;
6721 if (i < 32) {
6722 if (op1 & 0x20) {
6723 gen_ubfx(tmp, shift, (1u << i) - 1);
6724 } else {
6725 gen_sbfx(tmp, shift, i);
6728 store_reg(s, rd, tmp);
6729 break;
6730 default:
6731 goto illegal_op;
6733 break;
6735 break;
6737 do_ldst:
6738 /* Check for undefined extension instructions
6739 * per the ARM Bible IE:
6740 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6742 sh = (0xf << 20) | (0xf << 4);
6743 if (op1 == 0x7 && ((insn & sh) == sh))
6745 goto illegal_op;
6747 /* load/store byte/word */
6748 rn = (insn >> 16) & 0xf;
6749 rd = (insn >> 12) & 0xf;
6750 tmp2 = load_reg(s, rn);
6751 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6752 if (insn & (1 << 24))
6753 gen_add_data_offset(s, insn, tmp2);
6754 if (insn & (1 << 20)) {
6755 /* load */
6756 if (insn & (1 << 22)) {
6757 tmp = gen_ld8u(tmp2, i);
6758 } else {
6759 tmp = gen_ld32(tmp2, i);
6761 } else {
6762 /* store */
6763 tmp = load_reg(s, rd);
6764 if (insn & (1 << 22))
6765 gen_st8(tmp, tmp2, i);
6766 else
6767 gen_st32(tmp, tmp2, i);
6769 if (!(insn & (1 << 24))) {
6770 gen_add_data_offset(s, insn, tmp2);
6771 store_reg(s, rn, tmp2);
6772 } else if (insn & (1 << 21)) {
6773 store_reg(s, rn, tmp2);
6774 } else {
6775 dead_tmp(tmp2);
6777 if (insn & (1 << 20)) {
6778 /* Complete the load. */
6779 if (rd == 15)
6780 gen_bx(s, tmp);
6781 else
6782 store_reg(s, rd, tmp);
6784 break;
6785 case 0x08:
6786 case 0x09:
6788 int j, n, user, loaded_base;
6789 TCGv loaded_var;
6790 /* load/store multiple words */
6791 /* XXX: store correct base if write back */
6792 user = 0;
6793 if (insn & (1 << 22)) {
6794 if (IS_USER(s))
6795 goto illegal_op; /* only usable in supervisor mode */
6797 if ((insn & (1 << 15)) == 0)
6798 user = 1;
6800 rn = (insn >> 16) & 0xf;
6801 addr = load_reg(s, rn);
6803 /* compute total size */
6804 loaded_base = 0;
6805 TCGV_UNUSED(loaded_var);
6806 n = 0;
6807 for(i=0;i<16;i++) {
6808 if (insn & (1 << i))
6809 n++;
6811 /* XXX: test invalid n == 0 case ? */
6812 if (insn & (1 << 23)) {
6813 if (insn & (1 << 24)) {
6814 /* pre increment */
6815 tcg_gen_addi_i32(addr, addr, 4);
6816 } else {
6817 /* post increment */
6819 } else {
6820 if (insn & (1 << 24)) {
6821 /* pre decrement */
6822 tcg_gen_addi_i32(addr, addr, -(n * 4));
6823 } else {
6824 /* post decrement */
6825 if (n != 1)
6826 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6829 j = 0;
6830 for(i=0;i<16;i++) {
6831 if (insn & (1 << i)) {
6832 if (insn & (1 << 20)) {
6833 /* load */
6834 tmp = gen_ld32(addr, IS_USER(s));
6835 if (i == 15) {
6836 gen_bx(s, tmp);
6837 } else if (user) {
6838 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6839 dead_tmp(tmp);
6840 } else if (i == rn) {
6841 loaded_var = tmp;
6842 loaded_base = 1;
6843 } else {
6844 store_reg(s, i, tmp);
6846 } else {
6847 /* store */
6848 if (i == 15) {
6849 /* special case: r15 = PC + 8 */
6850 val = (long)s->pc + 4;
6851 tmp = new_tmp();
6852 tcg_gen_movi_i32(tmp, val);
6853 } else if (user) {
6854 tmp = new_tmp();
6855 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6856 } else {
6857 tmp = load_reg(s, i);
6859 gen_st32(tmp, addr, IS_USER(s));
6861 j++;
6862 /* no need to add after the last transfer */
6863 if (j != n)
6864 tcg_gen_addi_i32(addr, addr, 4);
6867 if (insn & (1 << 21)) {
6868 /* write back */
6869 if (insn & (1 << 23)) {
6870 if (insn & (1 << 24)) {
6871 /* pre increment */
6872 } else {
6873 /* post increment */
6874 tcg_gen_addi_i32(addr, addr, 4);
6876 } else {
6877 if (insn & (1 << 24)) {
6878 /* pre decrement */
6879 if (n != 1)
6880 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6881 } else {
6882 /* post decrement */
6883 tcg_gen_addi_i32(addr, addr, -(n * 4));
6886 store_reg(s, rn, addr);
6887 } else {
6888 dead_tmp(addr);
6890 if (loaded_base) {
6891 store_reg(s, rn, loaded_var);
6893 if ((insn & (1 << 22)) && !user) {
6894 /* Restore CPSR from SPSR. */
6895 tmp = load_cpu_field(spsr);
6896 gen_set_cpsr(tmp, 0xffffffff);
6897 dead_tmp(tmp);
6898 s->is_jmp = DISAS_UPDATE;
6901 break;
6902 case 0xa:
6903 case 0xb:
6905 int32_t offset;
6907 /* branch (and link) */
6908 val = (int32_t)s->pc;
6909 if (insn & (1 << 24)) {
6910 tmp = new_tmp();
6911 tcg_gen_movi_i32(tmp, val);
6912 store_reg(s, 14, tmp);
6914 offset = (((int32_t)insn << 8) >> 8);
6915 val += (offset << 2) + 4;
6916 gen_jmp(s, val);
6918 break;
6919 case 0xc:
6920 case 0xd:
6921 case 0xe:
6922 /* Coprocessor. */
6923 if (disas_coproc_insn(env, s, insn))
6924 goto illegal_op;
6925 break;
6926 case 0xf:
6927 /* swi */
6928 gen_set_pc_im(s->pc);
6929 s->is_jmp = DISAS_SWI;
6930 break;
6931 default:
6932 illegal_op:
6933 gen_set_condexec(s);
6934 gen_set_pc_im(s->pc - 4);
6935 gen_exception(EXCP_UDEF);
6936 s->is_jmp = DISAS_JUMP;
6937 break;
6942 /* Return true if this is a Thumb-2 logical op. */
6943 static int
6944 thumb2_logic_op(int op)
6946 return (op < 8);
6949 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6950 then set condition code flags based on the result of the operation.
6951 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6952 to the high bit of T1.
6953 Returns zero if the opcode is valid. */
6955 static int
6956 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6958 int logic_cc;
6960 logic_cc = 0;
6961 switch (op) {
6962 case 0: /* and */
6963 gen_op_andl_T0_T1();
6964 logic_cc = conds;
6965 break;
6966 case 1: /* bic */
6967 gen_op_bicl_T0_T1();
6968 logic_cc = conds;
6969 break;
6970 case 2: /* orr */
6971 gen_op_orl_T0_T1();
6972 logic_cc = conds;
6973 break;
6974 case 3: /* orn */
6975 gen_op_notl_T1();
6976 gen_op_orl_T0_T1();
6977 logic_cc = conds;
6978 break;
6979 case 4: /* eor */
6980 gen_op_xorl_T0_T1();
6981 logic_cc = conds;
6982 break;
6983 case 8: /* add */
6984 if (conds)
6985 gen_op_addl_T0_T1_cc();
6986 else
6987 gen_op_addl_T0_T1();
6988 break;
6989 case 10: /* adc */
6990 if (conds)
6991 gen_op_adcl_T0_T1_cc();
6992 else
6993 gen_adc_T0_T1();
6994 break;
6995 case 11: /* sbc */
6996 if (conds)
6997 gen_op_sbcl_T0_T1_cc();
6998 else
6999 gen_sbc_T0_T1();
7000 break;
7001 case 13: /* sub */
7002 if (conds)
7003 gen_op_subl_T0_T1_cc();
7004 else
7005 gen_op_subl_T0_T1();
7006 break;
7007 case 14: /* rsb */
7008 if (conds)
7009 gen_op_rsbl_T0_T1_cc();
7010 else
7011 gen_op_rsbl_T0_T1();
7012 break;
7013 default: /* 5, 6, 7, 9, 12, 15. */
7014 return 1;
7016 if (logic_cc) {
7017 gen_op_logic_T0_cc();
7018 if (shifter_out)
7019 gen_set_CF_bit31(cpu_T[1]);
7021 return 0;
7024 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7025 is not legal. */
7026 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7028 uint32_t insn, imm, shift, offset;
7029 uint32_t rd, rn, rm, rs;
7030 TCGv tmp;
7031 TCGv tmp2;
7032 TCGv tmp3;
7033 TCGv addr;
7034 TCGv_i64 tmp64;
7035 int op;
7036 int shiftop;
7037 int conds;
7038 int logic_cc;
7040 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7041 || arm_feature (env, ARM_FEATURE_M))) {
7042 /* Thumb-1 cores may need to treat bl and blx as a pair of
7043 16-bit instructions to get correct prefetch abort behavior. */
7044 insn = insn_hw1;
7045 if ((insn & (1 << 12)) == 0) {
7046 /* Second half of blx. */
7047 offset = ((insn & 0x7ff) << 1);
7048 tmp = load_reg(s, 14);
7049 tcg_gen_addi_i32(tmp, tmp, offset);
7050 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7052 tmp2 = new_tmp();
7053 tcg_gen_movi_i32(tmp2, s->pc | 1);
7054 store_reg(s, 14, tmp2);
7055 gen_bx(s, tmp);
7056 return 0;
7058 if (insn & (1 << 11)) {
7059 /* Second half of bl. */
7060 offset = ((insn & 0x7ff) << 1) | 1;
7061 tmp = load_reg(s, 14);
7062 tcg_gen_addi_i32(tmp, tmp, offset);
7064 tmp2 = new_tmp();
7065 tcg_gen_movi_i32(tmp2, s->pc | 1);
7066 store_reg(s, 14, tmp2);
7067 gen_bx(s, tmp);
7068 return 0;
7070 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7071 /* Instruction spans a page boundary. Implement it as two
7072 16-bit instructions in case the second half causes an
7073 prefetch abort. */
7074 offset = ((int32_t)insn << 21) >> 9;
7075 gen_op_movl_T0_im(s->pc + 2 + offset);
7076 gen_movl_reg_T0(s, 14);
7077 return 0;
7079 /* Fall through to 32-bit decode. */
7082 insn = lduw_code(s->pc);
7083 s->pc += 2;
7084 insn |= (uint32_t)insn_hw1 << 16;
7086 if ((insn & 0xf800e800) != 0xf000e800) {
7087 ARCH(6T2);
7090 rn = (insn >> 16) & 0xf;
7091 rs = (insn >> 12) & 0xf;
7092 rd = (insn >> 8) & 0xf;
7093 rm = insn & 0xf;
7094 switch ((insn >> 25) & 0xf) {
7095 case 0: case 1: case 2: case 3:
7096 /* 16-bit instructions. Should never happen. */
7097 abort();
7098 case 4:
7099 if (insn & (1 << 22)) {
7100 /* Other load/store, table branch. */
7101 if (insn & 0x01200000) {
7102 /* Load/store doubleword. */
7103 if (rn == 15) {
7104 addr = new_tmp();
7105 tcg_gen_movi_i32(addr, s->pc & ~3);
7106 } else {
7107 addr = load_reg(s, rn);
7109 offset = (insn & 0xff) * 4;
7110 if ((insn & (1 << 23)) == 0)
7111 offset = -offset;
7112 if (insn & (1 << 24)) {
7113 tcg_gen_addi_i32(addr, addr, offset);
7114 offset = 0;
7116 if (insn & (1 << 20)) {
7117 /* ldrd */
7118 tmp = gen_ld32(addr, IS_USER(s));
7119 store_reg(s, rs, tmp);
7120 tcg_gen_addi_i32(addr, addr, 4);
7121 tmp = gen_ld32(addr, IS_USER(s));
7122 store_reg(s, rd, tmp);
7123 } else {
7124 /* strd */
7125 tmp = load_reg(s, rs);
7126 gen_st32(tmp, addr, IS_USER(s));
7127 tcg_gen_addi_i32(addr, addr, 4);
7128 tmp = load_reg(s, rd);
7129 gen_st32(tmp, addr, IS_USER(s));
7131 if (insn & (1 << 21)) {
7132 /* Base writeback. */
7133 if (rn == 15)
7134 goto illegal_op;
7135 tcg_gen_addi_i32(addr, addr, offset - 4);
7136 store_reg(s, rn, addr);
7137 } else {
7138 dead_tmp(addr);
7140 } else if ((insn & (1 << 23)) == 0) {
7141 /* Load/store exclusive word. */
7142 gen_movl_T1_reg(s, rn);
7143 addr = cpu_T[1];
7144 if (insn & (1 << 20)) {
7145 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
7146 tmp = gen_ld32(addr, IS_USER(s));
7147 store_reg(s, rd, tmp);
7148 } else {
7149 int label = gen_new_label();
7150 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7151 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7152 0, label);
7153 tmp = load_reg(s, rs);
7154 gen_st32(tmp, cpu_T[1], IS_USER(s));
7155 gen_set_label(label);
7156 gen_movl_reg_T0(s, rd);
7158 } else if ((insn & (1 << 6)) == 0) {
7159 /* Table Branch. */
7160 if (rn == 15) {
7161 addr = new_tmp();
7162 tcg_gen_movi_i32(addr, s->pc);
7163 } else {
7164 addr = load_reg(s, rn);
7166 tmp = load_reg(s, rm);
7167 tcg_gen_add_i32(addr, addr, tmp);
7168 if (insn & (1 << 4)) {
7169 /* tbh */
7170 tcg_gen_add_i32(addr, addr, tmp);
7171 dead_tmp(tmp);
7172 tmp = gen_ld16u(addr, IS_USER(s));
7173 } else { /* tbb */
7174 dead_tmp(tmp);
7175 tmp = gen_ld8u(addr, IS_USER(s));
7177 dead_tmp(addr);
7178 tcg_gen_shli_i32(tmp, tmp, 1);
7179 tcg_gen_addi_i32(tmp, tmp, s->pc);
7180 store_reg(s, 15, tmp);
7181 } else {
7182 /* Load/store exclusive byte/halfword/doubleword. */
7183 /* ??? These are not really atomic. However we know
7184 we never have multiple CPUs running in parallel,
7185 so it is good enough. */
7186 op = (insn >> 4) & 0x3;
7187 /* Must use a global reg for the address because we have
7188 a conditional branch in the store instruction. */
7189 gen_movl_T1_reg(s, rn);
7190 addr = cpu_T[1];
7191 if (insn & (1 << 20)) {
7192 gen_helper_mark_exclusive(cpu_env, addr);
7193 switch (op) {
7194 case 0:
7195 tmp = gen_ld8u(addr, IS_USER(s));
7196 break;
7197 case 1:
7198 tmp = gen_ld16u(addr, IS_USER(s));
7199 break;
7200 case 3:
7201 tmp = gen_ld32(addr, IS_USER(s));
7202 tcg_gen_addi_i32(addr, addr, 4);
7203 tmp2 = gen_ld32(addr, IS_USER(s));
7204 store_reg(s, rd, tmp2);
7205 break;
7206 default:
7207 goto illegal_op;
7209 store_reg(s, rs, tmp);
7210 } else {
7211 int label = gen_new_label();
7212 /* Must use a global that is not killed by the branch. */
7213 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7214 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
7215 tmp = load_reg(s, rs);
7216 switch (op) {
7217 case 0:
7218 gen_st8(tmp, addr, IS_USER(s));
7219 break;
7220 case 1:
7221 gen_st16(tmp, addr, IS_USER(s));
7222 break;
7223 case 3:
7224 gen_st32(tmp, addr, IS_USER(s));
7225 tcg_gen_addi_i32(addr, addr, 4);
7226 tmp = load_reg(s, rd);
7227 gen_st32(tmp, addr, IS_USER(s));
7228 break;
7229 default:
7230 goto illegal_op;
7232 gen_set_label(label);
7233 gen_movl_reg_T0(s, rm);
7236 } else {
7237 /* Load/store multiple, RFE, SRS. */
7238 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7239 /* Not available in user mode. */
7240 if (IS_USER(s))
7241 goto illegal_op;
7242 if (insn & (1 << 20)) {
7243 /* rfe */
7244 addr = load_reg(s, rn);
7245 if ((insn & (1 << 24)) == 0)
7246 tcg_gen_addi_i32(addr, addr, -8);
7247 /* Load PC into tmp and CPSR into tmp2. */
7248 tmp = gen_ld32(addr, 0);
7249 tcg_gen_addi_i32(addr, addr, 4);
7250 tmp2 = gen_ld32(addr, 0);
7251 if (insn & (1 << 21)) {
7252 /* Base writeback. */
7253 if (insn & (1 << 24)) {
7254 tcg_gen_addi_i32(addr, addr, 4);
7255 } else {
7256 tcg_gen_addi_i32(addr, addr, -4);
7258 store_reg(s, rn, addr);
7259 } else {
7260 dead_tmp(addr);
7262 gen_rfe(s, tmp, tmp2);
7263 } else {
7264 /* srs */
7265 op = (insn & 0x1f);
7266 if (op == (env->uncached_cpsr & CPSR_M)) {
7267 addr = load_reg(s, 13);
7268 } else {
7269 addr = new_tmp();
7270 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7272 if ((insn & (1 << 24)) == 0) {
7273 tcg_gen_addi_i32(addr, addr, -8);
7275 tmp = load_reg(s, 14);
7276 gen_st32(tmp, addr, 0);
7277 tcg_gen_addi_i32(addr, addr, 4);
7278 tmp = new_tmp();
7279 gen_helper_cpsr_read(tmp);
7280 gen_st32(tmp, addr, 0);
7281 if (insn & (1 << 21)) {
7282 if ((insn & (1 << 24)) == 0) {
7283 tcg_gen_addi_i32(addr, addr, -4);
7284 } else {
7285 tcg_gen_addi_i32(addr, addr, 4);
7287 if (op == (env->uncached_cpsr & CPSR_M)) {
7288 store_reg(s, 13, addr);
7289 } else {
7290 gen_helper_set_r13_banked(cpu_env,
7291 tcg_const_i32(op), addr);
7293 } else {
7294 dead_tmp(addr);
7297 } else {
7298 int i;
7299 /* Load/store multiple. */
7300 addr = load_reg(s, rn);
7301 offset = 0;
7302 for (i = 0; i < 16; i++) {
7303 if (insn & (1 << i))
7304 offset += 4;
7306 if (insn & (1 << 24)) {
7307 tcg_gen_addi_i32(addr, addr, -offset);
7310 for (i = 0; i < 16; i++) {
7311 if ((insn & (1 << i)) == 0)
7312 continue;
7313 if (insn & (1 << 20)) {
7314 /* Load. */
7315 tmp = gen_ld32(addr, IS_USER(s));
7316 if (i == 15) {
7317 gen_bx(s, tmp);
7318 } else {
7319 store_reg(s, i, tmp);
7321 } else {
7322 /* Store. */
7323 tmp = load_reg(s, i);
7324 gen_st32(tmp, addr, IS_USER(s));
7326 tcg_gen_addi_i32(addr, addr, 4);
7328 if (insn & (1 << 21)) {
7329 /* Base register writeback. */
7330 if (insn & (1 << 24)) {
7331 tcg_gen_addi_i32(addr, addr, -offset);
7333 /* Fault if writeback register is in register list. */
7334 if (insn & (1 << rn))
7335 goto illegal_op;
7336 store_reg(s, rn, addr);
7337 } else {
7338 dead_tmp(addr);
7342 break;
7343 case 5: /* Data processing register constant shift. */
7344 if (rn == 15)
7345 gen_op_movl_T0_im(0);
7346 else
7347 gen_movl_T0_reg(s, rn);
7348 gen_movl_T1_reg(s, rm);
7349 op = (insn >> 21) & 0xf;
7350 shiftop = (insn >> 4) & 3;
7351 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7352 conds = (insn & (1 << 20)) != 0;
7353 logic_cc = (conds && thumb2_logic_op(op));
7354 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7355 if (gen_thumb2_data_op(s, op, conds, 0))
7356 goto illegal_op;
7357 if (rd != 15)
7358 gen_movl_reg_T0(s, rd);
7359 break;
7360 case 13: /* Misc data processing. */
7361 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7362 if (op < 4 && (insn & 0xf000) != 0xf000)
7363 goto illegal_op;
7364 switch (op) {
7365 case 0: /* Register controlled shift. */
7366 tmp = load_reg(s, rn);
7367 tmp2 = load_reg(s, rm);
7368 if ((insn & 0x70) != 0)
7369 goto illegal_op;
7370 op = (insn >> 21) & 3;
7371 logic_cc = (insn & (1 << 20)) != 0;
7372 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7373 if (logic_cc)
7374 gen_logic_CC(tmp);
7375 store_reg_bx(env, s, rd, tmp);
7376 break;
7377 case 1: /* Sign/zero extend. */
7378 tmp = load_reg(s, rm);
7379 shift = (insn >> 4) & 3;
7380 /* ??? In many cases it's not neccessary to do a
7381 rotate, a shift is sufficient. */
7382 if (shift != 0)
7383 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7384 op = (insn >> 20) & 7;
7385 switch (op) {
7386 case 0: gen_sxth(tmp); break;
7387 case 1: gen_uxth(tmp); break;
7388 case 2: gen_sxtb16(tmp); break;
7389 case 3: gen_uxtb16(tmp); break;
7390 case 4: gen_sxtb(tmp); break;
7391 case 5: gen_uxtb(tmp); break;
7392 default: goto illegal_op;
7394 if (rn != 15) {
7395 tmp2 = load_reg(s, rn);
7396 if ((op >> 1) == 1) {
7397 gen_add16(tmp, tmp2);
7398 } else {
7399 tcg_gen_add_i32(tmp, tmp, tmp2);
7400 dead_tmp(tmp2);
7403 store_reg(s, rd, tmp);
7404 break;
7405 case 2: /* SIMD add/subtract. */
7406 op = (insn >> 20) & 7;
7407 shift = (insn >> 4) & 7;
7408 if ((op & 3) == 3 || (shift & 3) == 3)
7409 goto illegal_op;
7410 tmp = load_reg(s, rn);
7411 tmp2 = load_reg(s, rm);
7412 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7413 dead_tmp(tmp2);
7414 store_reg(s, rd, tmp);
7415 break;
7416 case 3: /* Other data processing. */
7417 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7418 if (op < 4) {
7419 /* Saturating add/subtract. */
7420 tmp = load_reg(s, rn);
7421 tmp2 = load_reg(s, rm);
7422 if (op & 2)
7423 gen_helper_double_saturate(tmp, tmp);
7424 if (op & 1)
7425 gen_helper_sub_saturate(tmp, tmp2, tmp);
7426 else
7427 gen_helper_add_saturate(tmp, tmp, tmp2);
7428 dead_tmp(tmp2);
7429 } else {
7430 tmp = load_reg(s, rn);
7431 switch (op) {
7432 case 0x0a: /* rbit */
7433 gen_helper_rbit(tmp, tmp);
7434 break;
7435 case 0x08: /* rev */
7436 tcg_gen_bswap32_i32(tmp, tmp);
7437 break;
7438 case 0x09: /* rev16 */
7439 gen_rev16(tmp);
7440 break;
7441 case 0x0b: /* revsh */
7442 gen_revsh(tmp);
7443 break;
7444 case 0x10: /* sel */
7445 tmp2 = load_reg(s, rm);
7446 tmp3 = new_tmp();
7447 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7448 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7449 dead_tmp(tmp3);
7450 dead_tmp(tmp2);
7451 break;
7452 case 0x18: /* clz */
7453 gen_helper_clz(tmp, tmp);
7454 break;
7455 default:
7456 goto illegal_op;
7459 store_reg(s, rd, tmp);
7460 break;
7461 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7462 op = (insn >> 4) & 0xf;
7463 tmp = load_reg(s, rn);
7464 tmp2 = load_reg(s, rm);
7465 switch ((insn >> 20) & 7) {
7466 case 0: /* 32 x 32 -> 32 */
7467 tcg_gen_mul_i32(tmp, tmp, tmp2);
7468 dead_tmp(tmp2);
7469 if (rs != 15) {
7470 tmp2 = load_reg(s, rs);
7471 if (op)
7472 tcg_gen_sub_i32(tmp, tmp2, tmp);
7473 else
7474 tcg_gen_add_i32(tmp, tmp, tmp2);
7475 dead_tmp(tmp2);
7477 break;
7478 case 1: /* 16 x 16 -> 32 */
7479 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7480 dead_tmp(tmp2);
7481 if (rs != 15) {
7482 tmp2 = load_reg(s, rs);
7483 gen_helper_add_setq(tmp, tmp, tmp2);
7484 dead_tmp(tmp2);
7486 break;
7487 case 2: /* Dual multiply add. */
7488 case 4: /* Dual multiply subtract. */
7489 if (op)
7490 gen_swap_half(tmp2);
7491 gen_smul_dual(tmp, tmp2);
7492 /* This addition cannot overflow. */
7493 if (insn & (1 << 22)) {
7494 tcg_gen_sub_i32(tmp, tmp, tmp2);
7495 } else {
7496 tcg_gen_add_i32(tmp, tmp, tmp2);
7498 dead_tmp(tmp2);
7499 if (rs != 15)
7501 tmp2 = load_reg(s, rs);
7502 gen_helper_add_setq(tmp, tmp, tmp2);
7503 dead_tmp(tmp2);
7505 break;
7506 case 3: /* 32 * 16 -> 32msb */
7507 if (op)
7508 tcg_gen_sari_i32(tmp2, tmp2, 16);
7509 else
7510 gen_sxth(tmp2);
7511 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7512 tcg_gen_shri_i64(tmp64, tmp64, 16);
7513 tmp = new_tmp();
7514 tcg_gen_trunc_i64_i32(tmp, tmp64);
7515 if (rs != 15)
7517 tmp2 = load_reg(s, rs);
7518 gen_helper_add_setq(tmp, tmp, tmp2);
7519 dead_tmp(tmp2);
7521 break;
7522 case 5: case 6: /* 32 * 32 -> 32msb */
7523 gen_imull(tmp, tmp2);
7524 if (insn & (1 << 5)) {
7525 gen_roundqd(tmp, tmp2);
7526 dead_tmp(tmp2);
7527 } else {
7528 dead_tmp(tmp);
7529 tmp = tmp2;
7531 if (rs != 15) {
7532 tmp2 = load_reg(s, rs);
7533 if (insn & (1 << 21)) {
7534 tcg_gen_add_i32(tmp, tmp, tmp2);
7535 } else {
7536 tcg_gen_sub_i32(tmp, tmp2, tmp);
7538 dead_tmp(tmp2);
7540 break;
7541 case 7: /* Unsigned sum of absolute differences. */
7542 gen_helper_usad8(tmp, tmp, tmp2);
7543 dead_tmp(tmp2);
7544 if (rs != 15) {
7545 tmp2 = load_reg(s, rs);
7546 tcg_gen_add_i32(tmp, tmp, tmp2);
7547 dead_tmp(tmp2);
7549 break;
7551 store_reg(s, rd, tmp);
7552 break;
7553 case 6: case 7: /* 64-bit multiply, Divide. */
7554 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7555 tmp = load_reg(s, rn);
7556 tmp2 = load_reg(s, rm);
7557 if ((op & 0x50) == 0x10) {
7558 /* sdiv, udiv */
7559 if (!arm_feature(env, ARM_FEATURE_DIV))
7560 goto illegal_op;
7561 if (op & 0x20)
7562 gen_helper_udiv(tmp, tmp, tmp2);
7563 else
7564 gen_helper_sdiv(tmp, tmp, tmp2);
7565 dead_tmp(tmp2);
7566 store_reg(s, rd, tmp);
7567 } else if ((op & 0xe) == 0xc) {
7568 /* Dual multiply accumulate long. */
7569 if (op & 1)
7570 gen_swap_half(tmp2);
7571 gen_smul_dual(tmp, tmp2);
7572 if (op & 0x10) {
7573 tcg_gen_sub_i32(tmp, tmp, tmp2);
7574 } else {
7575 tcg_gen_add_i32(tmp, tmp, tmp2);
7577 dead_tmp(tmp2);
7578 /* BUGFIX */
7579 tmp64 = tcg_temp_new_i64();
7580 tcg_gen_ext_i32_i64(tmp64, tmp);
7581 dead_tmp(tmp);
7582 gen_addq(s, tmp64, rs, rd);
7583 gen_storeq_reg(s, rs, rd, tmp64);
7584 } else {
7585 if (op & 0x20) {
7586 /* Unsigned 64-bit multiply */
7587 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7588 } else {
7589 if (op & 8) {
7590 /* smlalxy */
7591 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7592 dead_tmp(tmp2);
7593 tmp64 = tcg_temp_new_i64();
7594 tcg_gen_ext_i32_i64(tmp64, tmp);
7595 dead_tmp(tmp);
7596 } else {
7597 /* Signed 64-bit multiply */
7598 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7601 if (op & 4) {
7602 /* umaal */
7603 gen_addq_lo(s, tmp64, rs);
7604 gen_addq_lo(s, tmp64, rd);
7605 } else if (op & 0x40) {
7606 /* 64-bit accumulate. */
7607 gen_addq(s, tmp64, rs, rd);
7609 gen_storeq_reg(s, rs, rd, tmp64);
7611 break;
7613 break;
7614 case 6: case 7: case 14: case 15:
7615 /* Coprocessor. */
7616 if (((insn >> 24) & 3) == 3) {
7617 /* Translate into the equivalent ARM encoding. */
7618 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7619 if (disas_neon_data_insn(env, s, insn))
7620 goto illegal_op;
7621 } else {
7622 if (insn & (1 << 28))
7623 goto illegal_op;
7624 if (disas_coproc_insn (env, s, insn))
7625 goto illegal_op;
7627 break;
7628 case 8: case 9: case 10: case 11:
7629 if (insn & (1 << 15)) {
7630 /* Branches, misc control. */
7631 if (insn & 0x5000) {
7632 /* Unconditional branch. */
7633 /* signextend(hw1[10:0]) -> offset[:12]. */
7634 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7635 /* hw1[10:0] -> offset[11:1]. */
7636 offset |= (insn & 0x7ff) << 1;
7637 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7638 offset[24:22] already have the same value because of the
7639 sign extension above. */
7640 offset ^= ((~insn) & (1 << 13)) << 10;
7641 offset ^= ((~insn) & (1 << 11)) << 11;
7643 if (insn & (1 << 14)) {
7644 /* Branch and link. */
7645 gen_op_movl_T1_im(s->pc | 1);
7646 gen_movl_reg_T1(s, 14);
7649 offset += s->pc;
7650 if (insn & (1 << 12)) {
7651 /* b/bl */
7652 gen_jmp(s, offset);
7653 } else {
7654 /* blx */
7655 offset &= ~(uint32_t)2;
7656 gen_bx_im(s, offset);
7658 } else if (((insn >> 23) & 7) == 7) {
7659 /* Misc control */
7660 if (insn & (1 << 13))
7661 goto illegal_op;
7663 if (insn & (1 << 26)) {
7664 /* Secure monitor call (v6Z) */
7665 goto illegal_op; /* not implemented. */
7666 } else {
7667 op = (insn >> 20) & 7;
7668 switch (op) {
7669 case 0: /* msr cpsr. */
7670 if (IS_M(env)) {
7671 tmp = load_reg(s, rn);
7672 addr = tcg_const_i32(insn & 0xff);
7673 gen_helper_v7m_msr(cpu_env, addr, tmp);
7674 gen_lookup_tb(s);
7675 break;
7677 /* fall through */
7678 case 1: /* msr spsr. */
7679 if (IS_M(env))
7680 goto illegal_op;
7681 gen_movl_T0_reg(s, rn);
7682 if (gen_set_psr_T0(s,
7683 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7684 op == 1))
7685 goto illegal_op;
7686 break;
7687 case 2: /* cps, nop-hint. */
7688 if (((insn >> 8) & 7) == 0) {
7689 gen_nop_hint(s, insn & 0xff);
7691 /* Implemented as NOP in user mode. */
7692 if (IS_USER(s))
7693 break;
7694 offset = 0;
7695 imm = 0;
7696 if (insn & (1 << 10)) {
7697 if (insn & (1 << 7))
7698 offset |= CPSR_A;
7699 if (insn & (1 << 6))
7700 offset |= CPSR_I;
7701 if (insn & (1 << 5))
7702 offset |= CPSR_F;
7703 if (insn & (1 << 9))
7704 imm = CPSR_A | CPSR_I | CPSR_F;
7706 if (insn & (1 << 8)) {
7707 offset |= 0x1f;
7708 imm |= (insn & 0x1f);
7710 if (offset) {
7711 gen_op_movl_T0_im(imm);
7712 gen_set_psr_T0(s, offset, 0);
7714 break;
7715 case 3: /* Special control operations. */
7716 op = (insn >> 4) & 0xf;
7717 switch (op) {
7718 case 2: /* clrex */
7719 gen_helper_clrex(cpu_env);
7720 break;
7721 case 4: /* dsb */
7722 case 5: /* dmb */
7723 case 6: /* isb */
7724 /* These execute as NOPs. */
7725 ARCH(7);
7726 break;
7727 default:
7728 goto illegal_op;
7730 break;
7731 case 4: /* bxj */
7732 /* Trivial implementation equivalent to bx. */
7733 tmp = load_reg(s, rn);
7734 gen_bx(s, tmp);
7735 break;
7736 case 5: /* Exception return. */
7737 /* Unpredictable in user mode. */
7738 goto illegal_op;
7739 case 6: /* mrs cpsr. */
7740 tmp = new_tmp();
7741 if (IS_M(env)) {
7742 addr = tcg_const_i32(insn & 0xff);
7743 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7744 } else {
7745 gen_helper_cpsr_read(tmp);
7747 store_reg(s, rd, tmp);
7748 break;
7749 case 7: /* mrs spsr. */
7750 /* Not accessible in user mode. */
7751 if (IS_USER(s) || IS_M(env))
7752 goto illegal_op;
7753 tmp = load_cpu_field(spsr);
7754 store_reg(s, rd, tmp);
7755 break;
7758 } else {
7759 /* Conditional branch. */
7760 op = (insn >> 22) & 0xf;
7761 /* Generate a conditional jump to next instruction. */
7762 s->condlabel = gen_new_label();
7763 gen_test_cc(op ^ 1, s->condlabel);
7764 s->condjmp = 1;
7766 /* offset[11:1] = insn[10:0] */
7767 offset = (insn & 0x7ff) << 1;
7768 /* offset[17:12] = insn[21:16]. */
7769 offset |= (insn & 0x003f0000) >> 4;
7770 /* offset[31:20] = insn[26]. */
7771 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7772 /* offset[18] = insn[13]. */
7773 offset |= (insn & (1 << 13)) << 5;
7774 /* offset[19] = insn[11]. */
7775 offset |= (insn & (1 << 11)) << 8;
7777 /* jump to the offset */
7778 gen_jmp(s, s->pc + offset);
7780 } else {
7781 /* Data processing immediate. */
7782 if (insn & (1 << 25)) {
7783 if (insn & (1 << 24)) {
7784 if (insn & (1 << 20))
7785 goto illegal_op;
7786 /* Bitfield/Saturate. */
7787 op = (insn >> 21) & 7;
7788 imm = insn & 0x1f;
7789 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7790 if (rn == 15) {
7791 tmp = new_tmp();
7792 tcg_gen_movi_i32(tmp, 0);
7793 } else {
7794 tmp = load_reg(s, rn);
7796 switch (op) {
7797 case 2: /* Signed bitfield extract. */
7798 imm++;
7799 if (shift + imm > 32)
7800 goto illegal_op;
7801 if (imm < 32)
7802 gen_sbfx(tmp, shift, imm);
7803 break;
7804 case 6: /* Unsigned bitfield extract. */
7805 imm++;
7806 if (shift + imm > 32)
7807 goto illegal_op;
7808 if (imm < 32)
7809 gen_ubfx(tmp, shift, (1u << imm) - 1);
7810 break;
7811 case 3: /* Bitfield insert/clear. */
7812 if (imm < shift)
7813 goto illegal_op;
7814 imm = imm + 1 - shift;
7815 if (imm != 32) {
7816 tmp2 = load_reg(s, rd);
7817 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7818 dead_tmp(tmp2);
7820 break;
7821 case 7:
7822 goto illegal_op;
7823 default: /* Saturate. */
7824 if (shift) {
7825 if (op & 1)
7826 tcg_gen_sari_i32(tmp, tmp, shift);
7827 else
7828 tcg_gen_shli_i32(tmp, tmp, shift);
7830 tmp2 = tcg_const_i32(imm);
7831 if (op & 4) {
7832 /* Unsigned. */
7833 if ((op & 1) && shift == 0)
7834 gen_helper_usat16(tmp, tmp, tmp2);
7835 else
7836 gen_helper_usat(tmp, tmp, tmp2);
7837 } else {
7838 /* Signed. */
7839 if ((op & 1) && shift == 0)
7840 gen_helper_ssat16(tmp, tmp, tmp2);
7841 else
7842 gen_helper_ssat(tmp, tmp, tmp2);
7844 break;
7846 store_reg(s, rd, tmp);
7847 } else {
7848 imm = ((insn & 0x04000000) >> 15)
7849 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7850 if (insn & (1 << 22)) {
7851 /* 16-bit immediate. */
7852 imm |= (insn >> 4) & 0xf000;
7853 if (insn & (1 << 23)) {
7854 /* movt */
7855 tmp = load_reg(s, rd);
7856 tcg_gen_ext16u_i32(tmp, tmp);
7857 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7858 } else {
7859 /* movw */
7860 tmp = new_tmp();
7861 tcg_gen_movi_i32(tmp, imm);
7863 } else {
7864 /* Add/sub 12-bit immediate. */
7865 if (rn == 15) {
7866 offset = s->pc & ~(uint32_t)3;
7867 if (insn & (1 << 23))
7868 offset -= imm;
7869 else
7870 offset += imm;
7871 tmp = new_tmp();
7872 tcg_gen_movi_i32(tmp, offset);
7873 } else {
7874 tmp = load_reg(s, rn);
7875 if (insn & (1 << 23))
7876 tcg_gen_subi_i32(tmp, tmp, imm);
7877 else
7878 tcg_gen_addi_i32(tmp, tmp, imm);
7881 store_reg(s, rd, tmp);
7883 } else {
7884 int shifter_out = 0;
7885 /* modified 12-bit immediate. */
7886 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7887 imm = (insn & 0xff);
7888 switch (shift) {
7889 case 0: /* XY */
7890 /* Nothing to do. */
7891 break;
7892 case 1: /* 00XY00XY */
7893 imm |= imm << 16;
7894 break;
7895 case 2: /* XY00XY00 */
7896 imm |= imm << 16;
7897 imm <<= 8;
7898 break;
7899 case 3: /* XYXYXYXY */
7900 imm |= imm << 16;
7901 imm |= imm << 8;
7902 break;
7903 default: /* Rotated constant. */
7904 shift = (shift << 1) | (imm >> 7);
7905 imm |= 0x80;
7906 imm = imm << (32 - shift);
7907 shifter_out = 1;
7908 break;
7910 gen_op_movl_T1_im(imm);
7911 rn = (insn >> 16) & 0xf;
7912 if (rn == 15)
7913 gen_op_movl_T0_im(0);
7914 else
7915 gen_movl_T0_reg(s, rn);
7916 op = (insn >> 21) & 0xf;
7917 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7918 shifter_out))
7919 goto illegal_op;
7920 rd = (insn >> 8) & 0xf;
7921 if (rd != 15) {
7922 gen_movl_reg_T0(s, rd);
7926 break;
7927 case 12: /* Load/store single data item. */
7929 int postinc = 0;
7930 int writeback = 0;
7931 int user;
7932 if ((insn & 0x01100000) == 0x01000000) {
7933 if (disas_neon_ls_insn(env, s, insn))
7934 goto illegal_op;
7935 break;
7937 user = IS_USER(s);
7938 if (rn == 15) {
7939 addr = new_tmp();
7940 /* PC relative. */
7941 /* s->pc has already been incremented by 4. */
7942 imm = s->pc & 0xfffffffc;
7943 if (insn & (1 << 23))
7944 imm += insn & 0xfff;
7945 else
7946 imm -= insn & 0xfff;
7947 tcg_gen_movi_i32(addr, imm);
7948 } else {
7949 addr = load_reg(s, rn);
7950 if (insn & (1 << 23)) {
7951 /* Positive offset. */
7952 imm = insn & 0xfff;
7953 tcg_gen_addi_i32(addr, addr, imm);
7954 } else {
7955 op = (insn >> 8) & 7;
7956 imm = insn & 0xff;
7957 switch (op) {
7958 case 0: case 8: /* Shifted Register. */
7959 shift = (insn >> 4) & 0xf;
7960 if (shift > 3)
7961 goto illegal_op;
7962 tmp = load_reg(s, rm);
7963 if (shift)
7964 tcg_gen_shli_i32(tmp, tmp, shift);
7965 tcg_gen_add_i32(addr, addr, tmp);
7966 dead_tmp(tmp);
7967 break;
7968 case 4: /* Negative offset. */
7969 tcg_gen_addi_i32(addr, addr, -imm);
7970 break;
7971 case 6: /* User privilege. */
7972 tcg_gen_addi_i32(addr, addr, imm);
7973 user = 1;
7974 break;
7975 case 1: /* Post-decrement. */
7976 imm = -imm;
7977 /* Fall through. */
7978 case 3: /* Post-increment. */
7979 postinc = 1;
7980 writeback = 1;
7981 break;
7982 case 5: /* Pre-decrement. */
7983 imm = -imm;
7984 /* Fall through. */
7985 case 7: /* Pre-increment. */
7986 tcg_gen_addi_i32(addr, addr, imm);
7987 writeback = 1;
7988 break;
7989 default:
7990 goto illegal_op;
7994 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7995 if (insn & (1 << 20)) {
7996 /* Load. */
7997 if (rs == 15 && op != 2) {
7998 if (op & 2)
7999 goto illegal_op;
8000 /* Memory hint. Implemented as NOP. */
8001 } else {
8002 switch (op) {
8003 case 0: tmp = gen_ld8u(addr, user); break;
8004 case 4: tmp = gen_ld8s(addr, user); break;
8005 case 1: tmp = gen_ld16u(addr, user); break;
8006 case 5: tmp = gen_ld16s(addr, user); break;
8007 case 2: tmp = gen_ld32(addr, user); break;
8008 default: goto illegal_op;
8010 if (rs == 15) {
8011 gen_bx(s, tmp);
8012 } else {
8013 store_reg(s, rs, tmp);
8016 } else {
8017 /* Store. */
8018 if (rs == 15)
8019 goto illegal_op;
8020 tmp = load_reg(s, rs);
8021 switch (op) {
8022 case 0: gen_st8(tmp, addr, user); break;
8023 case 1: gen_st16(tmp, addr, user); break;
8024 case 2: gen_st32(tmp, addr, user); break;
8025 default: goto illegal_op;
8028 if (postinc)
8029 tcg_gen_addi_i32(addr, addr, imm);
8030 if (writeback) {
8031 store_reg(s, rn, addr);
8032 } else {
8033 dead_tmp(addr);
8036 break;
8037 default:
8038 goto illegal_op;
8040 return 0;
8041 illegal_op:
8042 return 1;
8045 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8047 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8048 int32_t offset;
8049 int i;
8050 TCGv tmp;
8051 TCGv tmp2;
8052 TCGv addr;
8054 if (s->condexec_mask) {
8055 cond = s->condexec_cond;
8056 s->condlabel = gen_new_label();
8057 gen_test_cc(cond ^ 1, s->condlabel);
8058 s->condjmp = 1;
8061 insn = lduw_code(s->pc);
8062 s->pc += 2;
8064 switch (insn >> 12) {
8065 case 0: case 1:
8066 rd = insn & 7;
8067 op = (insn >> 11) & 3;
8068 if (op == 3) {
8069 /* add/subtract */
8070 rn = (insn >> 3) & 7;
8071 gen_movl_T0_reg(s, rn);
8072 if (insn & (1 << 10)) {
8073 /* immediate */
8074 gen_op_movl_T1_im((insn >> 6) & 7);
8075 } else {
8076 /* reg */
8077 rm = (insn >> 6) & 7;
8078 gen_movl_T1_reg(s, rm);
8080 if (insn & (1 << 9)) {
8081 if (s->condexec_mask)
8082 gen_op_subl_T0_T1();
8083 else
8084 gen_op_subl_T0_T1_cc();
8085 } else {
8086 if (s->condexec_mask)
8087 gen_op_addl_T0_T1();
8088 else
8089 gen_op_addl_T0_T1_cc();
8091 gen_movl_reg_T0(s, rd);
8092 } else {
8093 /* shift immediate */
8094 rm = (insn >> 3) & 7;
8095 shift = (insn >> 6) & 0x1f;
8096 tmp = load_reg(s, rm);
8097 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8098 if (!s->condexec_mask)
8099 gen_logic_CC(tmp);
8100 store_reg(s, rd, tmp);
8102 break;
8103 case 2: case 3:
8104 /* arithmetic large immediate */
8105 op = (insn >> 11) & 3;
8106 rd = (insn >> 8) & 0x7;
8107 if (op == 0) {
8108 gen_op_movl_T0_im(insn & 0xff);
8109 } else {
8110 gen_movl_T0_reg(s, rd);
8111 gen_op_movl_T1_im(insn & 0xff);
8113 switch (op) {
8114 case 0: /* mov */
8115 if (!s->condexec_mask)
8116 gen_op_logic_T0_cc();
8117 break;
8118 case 1: /* cmp */
8119 gen_op_subl_T0_T1_cc();
8120 break;
8121 case 2: /* add */
8122 if (s->condexec_mask)
8123 gen_op_addl_T0_T1();
8124 else
8125 gen_op_addl_T0_T1_cc();
8126 break;
8127 case 3: /* sub */
8128 if (s->condexec_mask)
8129 gen_op_subl_T0_T1();
8130 else
8131 gen_op_subl_T0_T1_cc();
8132 break;
8134 if (op != 1)
8135 gen_movl_reg_T0(s, rd);
8136 break;
8137 case 4:
8138 if (insn & (1 << 11)) {
8139 rd = (insn >> 8) & 7;
8140 /* load pc-relative. Bit 1 of PC is ignored. */
8141 val = s->pc + 2 + ((insn & 0xff) * 4);
8142 val &= ~(uint32_t)2;
8143 addr = new_tmp();
8144 tcg_gen_movi_i32(addr, val);
8145 tmp = gen_ld32(addr, IS_USER(s));
8146 dead_tmp(addr);
8147 store_reg(s, rd, tmp);
8148 break;
8150 if (insn & (1 << 10)) {
8151 /* data processing extended or blx */
8152 rd = (insn & 7) | ((insn >> 4) & 8);
8153 rm = (insn >> 3) & 0xf;
8154 op = (insn >> 8) & 3;
8155 switch (op) {
8156 case 0: /* add */
8157 gen_movl_T0_reg(s, rd);
8158 gen_movl_T1_reg(s, rm);
8159 gen_op_addl_T0_T1();
8160 gen_movl_reg_T0(s, rd);
8161 break;
8162 case 1: /* cmp */
8163 gen_movl_T0_reg(s, rd);
8164 gen_movl_T1_reg(s, rm);
8165 gen_op_subl_T0_T1_cc();
8166 break;
8167 case 2: /* mov/cpy */
8168 gen_movl_T0_reg(s, rm);
8169 gen_movl_reg_T0(s, rd);
8170 break;
8171 case 3:/* branch [and link] exchange thumb register */
8172 tmp = load_reg(s, rm);
8173 if (insn & (1 << 7)) {
8174 val = (uint32_t)s->pc | 1;
8175 tmp2 = new_tmp();
8176 tcg_gen_movi_i32(tmp2, val);
8177 store_reg(s, 14, tmp2);
8179 gen_bx(s, tmp);
8180 break;
8182 break;
8185 /* data processing register */
8186 rd = insn & 7;
8187 rm = (insn >> 3) & 7;
8188 op = (insn >> 6) & 0xf;
8189 if (op == 2 || op == 3 || op == 4 || op == 7) {
8190 /* the shift/rotate ops want the operands backwards */
8191 val = rm;
8192 rm = rd;
8193 rd = val;
8194 val = 1;
8195 } else {
8196 val = 0;
8199 if (op == 9) /* neg */
8200 gen_op_movl_T0_im(0);
8201 else if (op != 0xf) /* mvn doesn't read its first operand */
8202 gen_movl_T0_reg(s, rd);
8204 gen_movl_T1_reg(s, rm);
8205 switch (op) {
8206 case 0x0: /* and */
8207 gen_op_andl_T0_T1();
8208 if (!s->condexec_mask)
8209 gen_op_logic_T0_cc();
8210 break;
8211 case 0x1: /* eor */
8212 gen_op_xorl_T0_T1();
8213 if (!s->condexec_mask)
8214 gen_op_logic_T0_cc();
8215 break;
8216 case 0x2: /* lsl */
8217 if (s->condexec_mask) {
8218 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8219 } else {
8220 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8221 gen_op_logic_T1_cc();
8223 break;
8224 case 0x3: /* lsr */
8225 if (s->condexec_mask) {
8226 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8227 } else {
8228 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8229 gen_op_logic_T1_cc();
8231 break;
8232 case 0x4: /* asr */
8233 if (s->condexec_mask) {
8234 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8235 } else {
8236 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8237 gen_op_logic_T1_cc();
8239 break;
8240 case 0x5: /* adc */
8241 if (s->condexec_mask)
8242 gen_adc_T0_T1();
8243 else
8244 gen_op_adcl_T0_T1_cc();
8245 break;
8246 case 0x6: /* sbc */
8247 if (s->condexec_mask)
8248 gen_sbc_T0_T1();
8249 else
8250 gen_op_sbcl_T0_T1_cc();
8251 break;
8252 case 0x7: /* ror */
8253 if (s->condexec_mask) {
8254 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8255 } else {
8256 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8257 gen_op_logic_T1_cc();
8259 break;
8260 case 0x8: /* tst */
8261 gen_op_andl_T0_T1();
8262 gen_op_logic_T0_cc();
8263 rd = 16;
8264 break;
8265 case 0x9: /* neg */
8266 if (s->condexec_mask)
8267 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
8268 else
8269 gen_op_subl_T0_T1_cc();
8270 break;
8271 case 0xa: /* cmp */
8272 gen_op_subl_T0_T1_cc();
8273 rd = 16;
8274 break;
8275 case 0xb: /* cmn */
8276 gen_op_addl_T0_T1_cc();
8277 rd = 16;
8278 break;
8279 case 0xc: /* orr */
8280 gen_op_orl_T0_T1();
8281 if (!s->condexec_mask)
8282 gen_op_logic_T0_cc();
8283 break;
8284 case 0xd: /* mul */
8285 gen_op_mull_T0_T1();
8286 if (!s->condexec_mask)
8287 gen_op_logic_T0_cc();
8288 break;
8289 case 0xe: /* bic */
8290 gen_op_bicl_T0_T1();
8291 if (!s->condexec_mask)
8292 gen_op_logic_T0_cc();
8293 break;
8294 case 0xf: /* mvn */
8295 gen_op_notl_T1();
8296 if (!s->condexec_mask)
8297 gen_op_logic_T1_cc();
8298 val = 1;
8299 rm = rd;
8300 break;
8302 if (rd != 16) {
8303 if (val)
8304 gen_movl_reg_T1(s, rm);
8305 else
8306 gen_movl_reg_T0(s, rd);
8308 break;
8310 case 5:
8311 /* load/store register offset. */
8312 rd = insn & 7;
8313 rn = (insn >> 3) & 7;
8314 rm = (insn >> 6) & 7;
8315 op = (insn >> 9) & 7;
8316 addr = load_reg(s, rn);
8317 tmp = load_reg(s, rm);
8318 tcg_gen_add_i32(addr, addr, tmp);
8319 dead_tmp(tmp);
8321 if (op < 3) /* store */
8322 tmp = load_reg(s, rd);
8324 switch (op) {
8325 case 0: /* str */
8326 gen_st32(tmp, addr, IS_USER(s));
8327 break;
8328 case 1: /* strh */
8329 gen_st16(tmp, addr, IS_USER(s));
8330 break;
8331 case 2: /* strb */
8332 gen_st8(tmp, addr, IS_USER(s));
8333 break;
8334 case 3: /* ldrsb */
8335 tmp = gen_ld8s(addr, IS_USER(s));
8336 break;
8337 case 4: /* ldr */
8338 tmp = gen_ld32(addr, IS_USER(s));
8339 break;
8340 case 5: /* ldrh */
8341 tmp = gen_ld16u(addr, IS_USER(s));
8342 break;
8343 case 6: /* ldrb */
8344 tmp = gen_ld8u(addr, IS_USER(s));
8345 break;
8346 case 7: /* ldrsh */
8347 tmp = gen_ld16s(addr, IS_USER(s));
8348 break;
8350 if (op >= 3) /* load */
8351 store_reg(s, rd, tmp);
8352 dead_tmp(addr);
8353 break;
8355 case 6:
8356 /* load/store word immediate offset */
8357 rd = insn & 7;
8358 rn = (insn >> 3) & 7;
8359 addr = load_reg(s, rn);
8360 val = (insn >> 4) & 0x7c;
8361 tcg_gen_addi_i32(addr, addr, val);
8363 if (insn & (1 << 11)) {
8364 /* load */
8365 tmp = gen_ld32(addr, IS_USER(s));
8366 store_reg(s, rd, tmp);
8367 } else {
8368 /* store */
8369 tmp = load_reg(s, rd);
8370 gen_st32(tmp, addr, IS_USER(s));
8372 dead_tmp(addr);
8373 break;
8375 case 7:
8376 /* load/store byte immediate offset */
8377 rd = insn & 7;
8378 rn = (insn >> 3) & 7;
8379 addr = load_reg(s, rn);
8380 val = (insn >> 6) & 0x1f;
8381 tcg_gen_addi_i32(addr, addr, val);
8383 if (insn & (1 << 11)) {
8384 /* load */
8385 tmp = gen_ld8u(addr, IS_USER(s));
8386 store_reg(s, rd, tmp);
8387 } else {
8388 /* store */
8389 tmp = load_reg(s, rd);
8390 gen_st8(tmp, addr, IS_USER(s));
8392 dead_tmp(addr);
8393 break;
8395 case 8:
8396 /* load/store halfword immediate offset */
8397 rd = insn & 7;
8398 rn = (insn >> 3) & 7;
8399 addr = load_reg(s, rn);
8400 val = (insn >> 5) & 0x3e;
8401 tcg_gen_addi_i32(addr, addr, val);
8403 if (insn & (1 << 11)) {
8404 /* load */
8405 tmp = gen_ld16u(addr, IS_USER(s));
8406 store_reg(s, rd, tmp);
8407 } else {
8408 /* store */
8409 tmp = load_reg(s, rd);
8410 gen_st16(tmp, addr, IS_USER(s));
8412 dead_tmp(addr);
8413 break;
8415 case 9:
8416 /* load/store from stack */
8417 rd = (insn >> 8) & 7;
8418 addr = load_reg(s, 13);
8419 val = (insn & 0xff) * 4;
8420 tcg_gen_addi_i32(addr, addr, val);
8422 if (insn & (1 << 11)) {
8423 /* load */
8424 tmp = gen_ld32(addr, IS_USER(s));
8425 store_reg(s, rd, tmp);
8426 } else {
8427 /* store */
8428 tmp = load_reg(s, rd);
8429 gen_st32(tmp, addr, IS_USER(s));
8431 dead_tmp(addr);
8432 break;
8434 case 10:
8435 /* add to high reg */
8436 rd = (insn >> 8) & 7;
8437 if (insn & (1 << 11)) {
8438 /* SP */
8439 tmp = load_reg(s, 13);
8440 } else {
8441 /* PC. bit 1 is ignored. */
8442 tmp = new_tmp();
8443 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8445 val = (insn & 0xff) * 4;
8446 tcg_gen_addi_i32(tmp, tmp, val);
8447 store_reg(s, rd, tmp);
8448 break;
8450 case 11:
8451 /* misc */
8452 op = (insn >> 8) & 0xf;
8453 switch (op) {
8454 case 0:
8455 /* adjust stack pointer */
8456 tmp = load_reg(s, 13);
8457 val = (insn & 0x7f) * 4;
8458 if (insn & (1 << 7))
8459 val = -(int32_t)val;
8460 tcg_gen_addi_i32(tmp, tmp, val);
8461 store_reg(s, 13, tmp);
8462 break;
8464 case 2: /* sign/zero extend. */
8465 ARCH(6);
8466 rd = insn & 7;
8467 rm = (insn >> 3) & 7;
8468 tmp = load_reg(s, rm);
8469 switch ((insn >> 6) & 3) {
8470 case 0: gen_sxth(tmp); break;
8471 case 1: gen_sxtb(tmp); break;
8472 case 2: gen_uxth(tmp); break;
8473 case 3: gen_uxtb(tmp); break;
8475 store_reg(s, rd, tmp);
8476 break;
8477 case 4: case 5: case 0xc: case 0xd:
8478 /* push/pop */
8479 addr = load_reg(s, 13);
8480 if (insn & (1 << 8))
8481 offset = 4;
8482 else
8483 offset = 0;
8484 for (i = 0; i < 8; i++) {
8485 if (insn & (1 << i))
8486 offset += 4;
8488 if ((insn & (1 << 11)) == 0) {
8489 tcg_gen_addi_i32(addr, addr, -offset);
8491 for (i = 0; i < 8; i++) {
8492 if (insn & (1 << i)) {
8493 if (insn & (1 << 11)) {
8494 /* pop */
8495 tmp = gen_ld32(addr, IS_USER(s));
8496 store_reg(s, i, tmp);
8497 } else {
8498 /* push */
8499 tmp = load_reg(s, i);
8500 gen_st32(tmp, addr, IS_USER(s));
8502 /* advance to the next address. */
8503 tcg_gen_addi_i32(addr, addr, 4);
8506 TCGV_UNUSED(tmp);
8507 if (insn & (1 << 8)) {
8508 if (insn & (1 << 11)) {
8509 /* pop pc */
8510 tmp = gen_ld32(addr, IS_USER(s));
8511 /* don't set the pc until the rest of the instruction
8512 has completed */
8513 } else {
8514 /* push lr */
8515 tmp = load_reg(s, 14);
8516 gen_st32(tmp, addr, IS_USER(s));
8518 tcg_gen_addi_i32(addr, addr, 4);
8520 if ((insn & (1 << 11)) == 0) {
8521 tcg_gen_addi_i32(addr, addr, -offset);
8523 /* write back the new stack pointer */
8524 store_reg(s, 13, addr);
8525 /* set the new PC value */
8526 if ((insn & 0x0900) == 0x0900)
8527 gen_bx(s, tmp);
8528 break;
8530 case 1: case 3: case 9: case 11: /* czb */
8531 rm = insn & 7;
8532 tmp = load_reg(s, rm);
8533 s->condlabel = gen_new_label();
8534 s->condjmp = 1;
8535 if (insn & (1 << 11))
8536 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8537 else
8538 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8539 dead_tmp(tmp);
8540 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8541 val = (uint32_t)s->pc + 2;
8542 val += offset;
8543 gen_jmp(s, val);
8544 break;
8546 case 15: /* IT, nop-hint. */
8547 if ((insn & 0xf) == 0) {
8548 gen_nop_hint(s, (insn >> 4) & 0xf);
8549 break;
8551 /* If Then. */
8552 s->condexec_cond = (insn >> 4) & 0xe;
8553 s->condexec_mask = insn & 0x1f;
8554 /* No actual code generated for this insn, just setup state. */
8555 break;
8557 case 0xe: /* bkpt */
8558 gen_set_condexec(s);
8559 gen_set_pc_im(s->pc - 2);
8560 gen_exception(EXCP_BKPT);
8561 s->is_jmp = DISAS_JUMP;
8562 break;
8564 case 0xa: /* rev */
8565 ARCH(6);
8566 rn = (insn >> 3) & 0x7;
8567 rd = insn & 0x7;
8568 tmp = load_reg(s, rn);
8569 switch ((insn >> 6) & 3) {
8570 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8571 case 1: gen_rev16(tmp); break;
8572 case 3: gen_revsh(tmp); break;
8573 default: goto illegal_op;
8575 store_reg(s, rd, tmp);
8576 break;
8578 case 6: /* cps */
8579 ARCH(6);
8580 if (IS_USER(s))
8581 break;
8582 if (IS_M(env)) {
8583 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8584 /* PRIMASK */
8585 if (insn & 1) {
8586 addr = tcg_const_i32(16);
8587 gen_helper_v7m_msr(cpu_env, addr, tmp);
8589 /* FAULTMASK */
8590 if (insn & 2) {
8591 addr = tcg_const_i32(17);
8592 gen_helper_v7m_msr(cpu_env, addr, tmp);
8594 gen_lookup_tb(s);
8595 } else {
8596 if (insn & (1 << 4))
8597 shift = CPSR_A | CPSR_I | CPSR_F;
8598 else
8599 shift = 0;
8601 val = ((insn & 7) << 6) & shift;
8602 gen_op_movl_T0_im(val);
8603 gen_set_psr_T0(s, shift, 0);
8605 break;
8607 default:
8608 goto undef;
8610 break;
8612 case 12:
8613 /* load/store multiple */
8614 rn = (insn >> 8) & 0x7;
8615 addr = load_reg(s, rn);
8616 for (i = 0; i < 8; i++) {
8617 if (insn & (1 << i)) {
8618 if (insn & (1 << 11)) {
8619 /* load */
8620 tmp = gen_ld32(addr, IS_USER(s));
8621 store_reg(s, i, tmp);
8622 } else {
8623 /* store */
8624 tmp = load_reg(s, i);
8625 gen_st32(tmp, addr, IS_USER(s));
8627 /* advance to the next address */
8628 tcg_gen_addi_i32(addr, addr, 4);
8631 /* Base register writeback. */
8632 if ((insn & (1 << rn)) == 0) {
8633 store_reg(s, rn, addr);
8634 } else {
8635 dead_tmp(addr);
8637 break;
8639 case 13:
8640 /* conditional branch or swi */
8641 cond = (insn >> 8) & 0xf;
8642 if (cond == 0xe)
8643 goto undef;
8645 if (cond == 0xf) {
8646 /* swi */
8647 gen_set_condexec(s);
8648 gen_set_pc_im(s->pc);
8649 s->is_jmp = DISAS_SWI;
8650 break;
8652 /* generate a conditional jump to next instruction */
8653 s->condlabel = gen_new_label();
8654 gen_test_cc(cond ^ 1, s->condlabel);
8655 s->condjmp = 1;
8656 gen_movl_T1_reg(s, 15);
8658 /* jump to the offset */
8659 val = (uint32_t)s->pc + 2;
8660 offset = ((int32_t)insn << 24) >> 24;
8661 val += offset << 1;
8662 gen_jmp(s, val);
8663 break;
8665 case 14:
8666 if (insn & (1 << 11)) {
8667 if (disas_thumb2_insn(env, s, insn))
8668 goto undef32;
8669 break;
8671 /* unconditional branch */
8672 val = (uint32_t)s->pc;
8673 offset = ((int32_t)insn << 21) >> 21;
8674 val += (offset << 1) + 2;
8675 gen_jmp(s, val);
8676 break;
8678 case 15:
8679 if (disas_thumb2_insn(env, s, insn))
8680 goto undef32;
8681 break;
8683 return;
8684 undef32:
8685 gen_set_condexec(s);
8686 gen_set_pc_im(s->pc - 4);
8687 gen_exception(EXCP_UDEF);
8688 s->is_jmp = DISAS_JUMP;
8689 return;
8690 illegal_op:
8691 undef:
8692 gen_set_condexec(s);
8693 gen_set_pc_im(s->pc - 2);
8694 gen_exception(EXCP_UDEF);
8695 s->is_jmp = DISAS_JUMP;
8698 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8699 basic block 'tb'. If search_pc is TRUE, also generate PC
8700 information for each intermediate instruction. */
8701 static inline void gen_intermediate_code_internal(CPUState *env,
8702 TranslationBlock *tb,
8703 int search_pc)
8705 DisasContext dc1, *dc = &dc1;
8706 CPUBreakpoint *bp;
8707 uint16_t *gen_opc_end;
8708 int j, lj;
8709 target_ulong pc_start;
8710 uint32_t next_page_start;
8711 int num_insns;
8712 int max_insns;
8714 /* generate intermediate code */
8715 num_temps = 0;
8716 memset(temps, 0, sizeof(temps));
8718 pc_start = tb->pc;
8720 dc->tb = tb;
8722 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8724 dc->is_jmp = DISAS_NEXT;
8725 dc->pc = pc_start;
8726 dc->singlestep_enabled = env->singlestep_enabled;
8727 dc->condjmp = 0;
8728 dc->thumb = env->thumb;
8729 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8730 dc->condexec_cond = env->condexec_bits >> 4;
8731 #if !defined(CONFIG_USER_ONLY)
8732 if (IS_M(env)) {
8733 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8734 } else {
8735 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8737 #endif
8738 cpu_F0s = tcg_temp_new_i32();
8739 cpu_F1s = tcg_temp_new_i32();
8740 cpu_F0d = tcg_temp_new_i64();
8741 cpu_F1d = tcg_temp_new_i64();
8742 cpu_V0 = cpu_F0d;
8743 cpu_V1 = cpu_F1d;
8744 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8745 cpu_M0 = tcg_temp_new_i64();
8746 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8747 lj = -1;
8748 num_insns = 0;
8749 max_insns = tb->cflags & CF_COUNT_MASK;
8750 if (max_insns == 0)
8751 max_insns = CF_COUNT_MASK;
8753 gen_icount_start();
8754 /* Reset the conditional execution bits immediately. This avoids
8755 complications trying to do it at the end of the block. */
8756 if (env->condexec_bits)
8758 TCGv tmp = new_tmp();
8759 tcg_gen_movi_i32(tmp, 0);
8760 store_cpu_field(tmp, condexec_bits);
8762 do {
8763 #ifdef CONFIG_USER_ONLY
8764 /* Intercept jump to the magic kernel page. */
8765 if (dc->pc >= 0xffff0000) {
8766 /* We always get here via a jump, so know we are not in a
8767 conditional execution block. */
8768 gen_exception(EXCP_KERNEL_TRAP);
8769 dc->is_jmp = DISAS_UPDATE;
8770 break;
8772 #else
8773 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8774 /* We always get here via a jump, so know we are not in a
8775 conditional execution block. */
8776 gen_exception(EXCP_EXCEPTION_EXIT);
8777 dc->is_jmp = DISAS_UPDATE;
8778 break;
8780 #endif
8782 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8783 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8784 if (bp->pc == dc->pc) {
8785 gen_set_condexec(dc);
8786 gen_set_pc_im(dc->pc);
8787 gen_exception(EXCP_DEBUG);
8788 dc->is_jmp = DISAS_JUMP;
8789 /* Advance PC so that clearing the breakpoint will
8790 invalidate this TB. */
8791 dc->pc += 2;
8792 goto done_generating;
8793 break;
8797 if (search_pc) {
8798 j = gen_opc_ptr - gen_opc_buf;
8799 if (lj < j) {
8800 lj++;
8801 while (lj < j)
8802 gen_opc_instr_start[lj++] = 0;
8804 gen_opc_pc[lj] = dc->pc;
8805 gen_opc_instr_start[lj] = 1;
8806 gen_opc_icount[lj] = num_insns;
8809 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8810 gen_io_start();
8812 if (env->thumb) {
8813 disas_thumb_insn(env, dc);
8814 if (dc->condexec_mask) {
8815 dc->condexec_cond = (dc->condexec_cond & 0xe)
8816 | ((dc->condexec_mask >> 4) & 1);
8817 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8818 if (dc->condexec_mask == 0) {
8819 dc->condexec_cond = 0;
8822 } else {
8823 disas_arm_insn(env, dc);
8825 if (num_temps) {
8826 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8827 num_temps = 0;
8830 if (dc->condjmp && !dc->is_jmp) {
8831 gen_set_label(dc->condlabel);
8832 dc->condjmp = 0;
8834 /* Translation stops when a conditional branch is encountered.
8835 * Otherwise the subsequent code could get translated several times.
8836 * Also stop translation when a page boundary is reached. This
8837 * ensures prefetch aborts occur at the right place. */
8838 num_insns ++;
8839 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8840 !env->singlestep_enabled &&
8841 !singlestep &&
8842 dc->pc < next_page_start &&
8843 num_insns < max_insns);
8845 if (tb->cflags & CF_LAST_IO) {
8846 if (dc->condjmp) {
8847 /* FIXME: This can theoretically happen with self-modifying
8848 code. */
8849 cpu_abort(env, "IO on conditional branch instruction");
8851 gen_io_end();
8854 /* At this stage dc->condjmp will only be set when the skipped
8855 instruction was a conditional branch or trap, and the PC has
8856 already been written. */
8857 if (unlikely(env->singlestep_enabled)) {
8858 /* Make sure the pc is updated, and raise a debug exception. */
8859 if (dc->condjmp) {
8860 gen_set_condexec(dc);
8861 if (dc->is_jmp == DISAS_SWI) {
8862 gen_exception(EXCP_SWI);
8863 } else {
8864 gen_exception(EXCP_DEBUG);
8866 gen_set_label(dc->condlabel);
8868 if (dc->condjmp || !dc->is_jmp) {
8869 gen_set_pc_im(dc->pc);
8870 dc->condjmp = 0;
8872 gen_set_condexec(dc);
8873 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8874 gen_exception(EXCP_SWI);
8875 } else {
8876 /* FIXME: Single stepping a WFI insn will not halt
8877 the CPU. */
8878 gen_exception(EXCP_DEBUG);
8880 } else {
8881 /* While branches must always occur at the end of an IT block,
8882 there are a few other things that can cause us to terminate
8883 the TB in the middel of an IT block:
8884 - Exception generating instructions (bkpt, swi, undefined).
8885 - Page boundaries.
8886 - Hardware watchpoints.
8887 Hardware breakpoints have already been handled and skip this code.
8889 gen_set_condexec(dc);
8890 switch(dc->is_jmp) {
8891 case DISAS_NEXT:
8892 gen_goto_tb(dc, 1, dc->pc);
8893 break;
8894 default:
8895 case DISAS_JUMP:
8896 case DISAS_UPDATE:
8897 /* indicate that the hash table must be used to find the next TB */
8898 tcg_gen_exit_tb(0);
8899 break;
8900 case DISAS_TB_JUMP:
8901 /* nothing more to generate */
8902 break;
8903 case DISAS_WFI:
8904 gen_helper_wfi();
8905 break;
8906 case DISAS_SWI:
8907 gen_exception(EXCP_SWI);
8908 break;
8910 if (dc->condjmp) {
8911 gen_set_label(dc->condlabel);
8912 gen_set_condexec(dc);
8913 gen_goto_tb(dc, 1, dc->pc);
8914 dc->condjmp = 0;
8918 done_generating:
8919 gen_icount_end(tb, num_insns);
8920 *gen_opc_ptr = INDEX_op_end;
8922 #ifdef DEBUG_DISAS
8923 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8924 qemu_log("----------------\n");
8925 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8926 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8927 qemu_log("\n");
8929 #endif
8930 if (search_pc) {
8931 j = gen_opc_ptr - gen_opc_buf;
8932 lj++;
8933 while (lj <= j)
8934 gen_opc_instr_start[lj++] = 0;
8935 } else {
8936 tb->size = dc->pc - pc_start;
8937 tb->icount = num_insns;
8941 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8943 gen_intermediate_code_internal(env, tb, 0);
8946 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8948 gen_intermediate_code_internal(env, tb, 1);
8951 static const char *cpu_mode_names[16] = {
8952 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8953 "???", "???", "???", "und", "???", "???", "???", "sys"
8956 void cpu_dump_state(CPUState *env, FILE *f,
8957 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8958 int flags)
8960 int i;
8961 #if 0
8962 union {
8963 uint32_t i;
8964 float s;
8965 } s0, s1;
8966 CPU_DoubleU d;
8967 /* ??? This assumes float64 and double have the same layout.
8968 Oh well, it's only debug dumps. */
8969 union {
8970 float64 f64;
8971 double d;
8972 } d0;
8973 #endif
8974 uint32_t psr;
8976 for(i=0;i<16;i++) {
8977 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8978 if ((i % 4) == 3)
8979 cpu_fprintf(f, "\n");
8980 else
8981 cpu_fprintf(f, " ");
8983 psr = cpsr_read(env);
8984 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8985 psr,
8986 psr & (1 << 31) ? 'N' : '-',
8987 psr & (1 << 30) ? 'Z' : '-',
8988 psr & (1 << 29) ? 'C' : '-',
8989 psr & (1 << 28) ? 'V' : '-',
8990 psr & CPSR_T ? 'T' : 'A',
8991 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8993 #if 0
8994 for (i = 0; i < 16; i++) {
8995 d.d = env->vfp.regs[i];
8996 s0.i = d.l.lower;
8997 s1.i = d.l.upper;
8998 d0.f64 = d.d;
8999 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9000 i * 2, (int)s0.i, s0.s,
9001 i * 2 + 1, (int)s1.i, s1.s,
9002 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9003 d0.d);
9005 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9006 #endif
9009 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9010 unsigned long searched_pc, int pc_pos, void *puc)
9012 env->regs[15] = gen_opc_pc[pc_pos];