Display TCGCond name in tcg dumper (original patch by Tristan Gingold)
[qemu/mini2440.git] / target-arm / translate.c
blob8381bccd6611ef4003242aa0d93d0a77f6f14ee8
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #define GEN_HELPER 1
35 #include "helpers.h"
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 int is_mem;
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 cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv 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, cpu_F0d, cpu_F1d;
84 #define ICOUNT_TEMP cpu_T[0]
85 #include "gen-icount.h"
87 /* initialize TCG globals. */
88 void arm_translate_init(void)
90 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
92 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
93 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
96 /* The code generator doesn't like lots of temporaries, so maintain our own
97 cache for reuse within a function. */
98 #define MAX_TEMPS 8
99 static int num_temps;
100 static TCGv temps[MAX_TEMPS];
102 /* Allocate a temporary variable. */
103 static TCGv new_tmp(void)
105 TCGv tmp;
106 if (num_temps == MAX_TEMPS)
107 abort();
109 if (GET_TCGV(temps[num_temps]))
110 return temps[num_temps++];
112 tmp = tcg_temp_new(TCG_TYPE_I32);
113 temps[num_temps++] = tmp;
114 return tmp;
117 /* Release a temporary variable. */
118 static void dead_tmp(TCGv tmp)
120 int i;
121 num_temps--;
122 i = num_temps;
123 if (GET_TCGV(temps[i]) == GET_TCGV(tmp))
124 return;
126 /* Shuffle this temp to the last slot. */
127 while (GET_TCGV(temps[i]) != GET_TCGV(tmp))
128 i--;
129 while (i < num_temps) {
130 temps[i] = temps[i + 1];
131 i++;
133 temps[i] = tmp;
136 static inline TCGv load_cpu_offset(int offset)
138 TCGv tmp = new_tmp();
139 tcg_gen_ld_i32(tmp, cpu_env, offset);
140 return tmp;
143 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
145 static inline void store_cpu_offset(TCGv var, int offset)
147 tcg_gen_st_i32(var, cpu_env, offset);
148 dead_tmp(var);
151 #define store_cpu_field(var, name) \
152 store_cpu_offset(var, offsetof(CPUState, name))
154 /* Set a variable to the value of a CPU register. */
155 static void load_reg_var(DisasContext *s, TCGv var, int reg)
157 if (reg == 15) {
158 uint32_t addr;
159 /* normaly, since we updated PC, we need only to add one insn */
160 if (s->thumb)
161 addr = (long)s->pc + 2;
162 else
163 addr = (long)s->pc + 4;
164 tcg_gen_movi_i32(var, addr);
165 } else {
166 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
170 /* Create a new temporary and set it to the value of a CPU register. */
171 static inline TCGv load_reg(DisasContext *s, int reg)
173 TCGv tmp = new_tmp();
174 load_reg_var(s, tmp, reg);
175 return tmp;
178 /* Set a CPU register. The source must be a temporary and will be
179 marked as dead. */
180 static void store_reg(DisasContext *s, int reg, TCGv var)
182 if (reg == 15) {
183 tcg_gen_andi_i32(var, var, ~1);
184 s->is_jmp = DISAS_JUMP;
186 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
187 dead_tmp(var);
191 /* Basic operations. */
192 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
193 #define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
194 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
195 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
197 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
198 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
199 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
200 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
202 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
203 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
204 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
205 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
207 #define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
209 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
210 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
213 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
214 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
215 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
217 #define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
218 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
219 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
220 #define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
221 #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
223 /* Value extensions. */
224 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
225 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
226 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
227 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
229 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
230 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
232 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
234 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
235 /* Set NZCV flags from the high 4 bits of var. */
236 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
238 static void gen_exception(int excp)
240 TCGv tmp = new_tmp();
241 tcg_gen_movi_i32(tmp, excp);
242 gen_helper_exception(tmp);
243 dead_tmp(tmp);
246 static void gen_smul_dual(TCGv a, TCGv b)
248 TCGv tmp1 = new_tmp();
249 TCGv tmp2 = new_tmp();
250 tcg_gen_ext16s_i32(tmp1, a);
251 tcg_gen_ext16s_i32(tmp2, b);
252 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
253 dead_tmp(tmp2);
254 tcg_gen_sari_i32(a, a, 16);
255 tcg_gen_sari_i32(b, b, 16);
256 tcg_gen_mul_i32(b, b, a);
257 tcg_gen_mov_i32(a, tmp1);
258 dead_tmp(tmp1);
261 /* Byteswap each halfword. */
262 static void gen_rev16(TCGv var)
264 TCGv tmp = new_tmp();
265 tcg_gen_shri_i32(tmp, var, 8);
266 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
267 tcg_gen_shli_i32(var, var, 8);
268 tcg_gen_andi_i32(var, var, 0xff00ff00);
269 tcg_gen_or_i32(var, var, tmp);
270 dead_tmp(tmp);
273 /* Byteswap low halfword and sign extend. */
274 static void gen_revsh(TCGv var)
276 TCGv tmp = new_tmp();
277 tcg_gen_shri_i32(tmp, var, 8);
278 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
279 tcg_gen_shli_i32(var, var, 8);
280 tcg_gen_ext8s_i32(var, var);
281 tcg_gen_or_i32(var, var, tmp);
282 dead_tmp(tmp);
285 /* Unsigned bitfield extract. */
286 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
288 if (shift)
289 tcg_gen_shri_i32(var, var, shift);
290 tcg_gen_andi_i32(var, var, mask);
293 /* Signed bitfield extract. */
294 static void gen_sbfx(TCGv var, int shift, int width)
296 uint32_t signbit;
298 if (shift)
299 tcg_gen_sari_i32(var, var, shift);
300 if (shift + width < 32) {
301 signbit = 1u << (width - 1);
302 tcg_gen_andi_i32(var, var, (1u << width) - 1);
303 tcg_gen_xori_i32(var, var, signbit);
304 tcg_gen_subi_i32(var, var, signbit);
308 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
309 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
311 tcg_gen_andi_i32(val, val, mask);
312 tcg_gen_shli_i32(val, val, shift);
313 tcg_gen_andi_i32(base, base, ~(mask << shift));
314 tcg_gen_or_i32(dest, base, val);
317 /* Round the top 32 bits of a 64-bit value. */
318 static void gen_roundqd(TCGv a, TCGv b)
320 tcg_gen_shri_i32(a, a, 31);
321 tcg_gen_add_i32(a, a, b);
324 /* FIXME: Most targets have native widening multiplication.
325 It would be good to use that instead of a full wide multiply. */
326 /* 32x32->64 multiply. Marks inputs as dead. */
327 static TCGv gen_mulu_i64_i32(TCGv a, TCGv b)
329 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
330 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
332 tcg_gen_extu_i32_i64(tmp1, a);
333 dead_tmp(a);
334 tcg_gen_extu_i32_i64(tmp2, b);
335 dead_tmp(b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 return tmp1;
340 static TCGv gen_muls_i64_i32(TCGv a, TCGv b)
342 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
343 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
345 tcg_gen_ext_i32_i64(tmp1, a);
346 dead_tmp(a);
347 tcg_gen_ext_i32_i64(tmp2, b);
348 dead_tmp(b);
349 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
350 return tmp1;
353 /* Unsigned 32x32->64 multiply. */
354 static void gen_op_mull_T0_T1(void)
356 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
357 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
359 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
360 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
361 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
362 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
363 tcg_gen_shri_i64(tmp1, tmp1, 32);
364 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
367 /* Signed 32x32->64 multiply. */
368 static void gen_imull(TCGv a, TCGv b)
370 TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
371 TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
373 tcg_gen_ext_i32_i64(tmp1, a);
374 tcg_gen_ext_i32_i64(tmp2, b);
375 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
376 tcg_gen_trunc_i64_i32(a, tmp1);
377 tcg_gen_shri_i64(tmp1, tmp1, 32);
378 tcg_gen_trunc_i64_i32(b, tmp1);
380 #define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
382 /* Swap low and high halfwords. */
383 static void gen_swap_half(TCGv var)
385 TCGv tmp = new_tmp();
386 tcg_gen_shri_i32(tmp, var, 16);
387 tcg_gen_shli_i32(var, var, 16);
388 tcg_gen_or_i32(var, var, tmp);
389 dead_tmp(tmp);
392 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
393 tmp = (t0 ^ t1) & 0x8000;
394 t0 &= ~0x8000;
395 t1 &= ~0x8000;
396 t0 = (t0 + t1) ^ tmp;
399 static void gen_add16(TCGv t0, TCGv t1)
401 TCGv tmp = new_tmp();
402 tcg_gen_xor_i32(tmp, t0, t1);
403 tcg_gen_andi_i32(tmp, tmp, 0x8000);
404 tcg_gen_andi_i32(t0, t0, ~0x8000);
405 tcg_gen_andi_i32(t1, t1, ~0x8000);
406 tcg_gen_add_i32(t0, t0, t1);
407 tcg_gen_xor_i32(t0, t0, tmp);
408 dead_tmp(tmp);
409 dead_tmp(t1);
412 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
414 /* Set CF to the top bit of var. */
415 static void gen_set_CF_bit31(TCGv var)
417 TCGv tmp = new_tmp();
418 tcg_gen_shri_i32(tmp, var, 31);
419 gen_set_CF(var);
420 dead_tmp(tmp);
423 /* Set N and Z flags from var. */
424 static inline void gen_logic_CC(TCGv var)
426 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
427 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
430 /* T0 += T1 + CF. */
431 static void gen_adc_T0_T1(void)
433 TCGv tmp;
434 gen_op_addl_T0_T1();
435 tmp = load_cpu_field(CF);
436 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
437 dead_tmp(tmp);
440 /* dest = T0 - T1 + CF - 1. */
441 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
443 TCGv tmp;
444 tcg_gen_sub_i32(dest, t0, t1);
445 tmp = load_cpu_field(CF);
446 tcg_gen_add_i32(dest, dest, tmp);
447 tcg_gen_subi_i32(dest, dest, 1);
448 dead_tmp(tmp);
451 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
452 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
454 /* T0 &= ~T1. Clobbers T1. */
455 /* FIXME: Implement bic natively. */
456 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
458 TCGv tmp = new_tmp();
459 tcg_gen_not_i32(tmp, t1);
460 tcg_gen_and_i32(dest, t0, tmp);
461 dead_tmp(tmp);
463 static inline void gen_op_bicl_T0_T1(void)
465 gen_op_notl_T1();
466 gen_op_andl_T0_T1();
469 /* FIXME: Implement this natively. */
470 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
472 /* FIXME: Implement this natively. */
473 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
475 TCGv tmp;
477 if (i == 0)
478 return;
480 tmp = new_tmp();
481 tcg_gen_shri_i32(tmp, t1, i);
482 tcg_gen_shli_i32(t1, t1, 32 - i);
483 tcg_gen_or_i32(t0, t1, tmp);
484 dead_tmp(tmp);
487 static void shifter_out_im(TCGv var, int shift)
489 TCGv tmp = new_tmp();
490 if (shift == 0) {
491 tcg_gen_andi_i32(tmp, var, 1);
492 } else {
493 tcg_gen_shri_i32(tmp, var, shift);
494 if (shift != 31);
495 tcg_gen_andi_i32(tmp, tmp, 1);
497 gen_set_CF(tmp);
498 dead_tmp(tmp);
501 /* Shift by immediate. Includes special handling for shift == 0. */
502 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
504 switch (shiftop) {
505 case 0: /* LSL */
506 if (shift != 0) {
507 if (flags)
508 shifter_out_im(var, 32 - shift);
509 tcg_gen_shli_i32(var, var, shift);
511 break;
512 case 1: /* LSR */
513 if (shift == 0) {
514 if (flags) {
515 tcg_gen_shri_i32(var, var, 31);
516 gen_set_CF(var);
518 tcg_gen_movi_i32(var, 0);
519 } else {
520 if (flags)
521 shifter_out_im(var, shift - 1);
522 tcg_gen_shri_i32(var, var, shift);
524 break;
525 case 2: /* ASR */
526 if (shift == 0)
527 shift = 32;
528 if (flags)
529 shifter_out_im(var, shift - 1);
530 if (shift == 32)
531 shift = 31;
532 tcg_gen_sari_i32(var, var, shift);
533 break;
534 case 3: /* ROR/RRX */
535 if (shift != 0) {
536 if (flags)
537 shifter_out_im(var, shift - 1);
538 tcg_gen_rori_i32(var, var, shift); break;
539 } else {
540 TCGv tmp = load_cpu_field(CF);
541 if (flags)
542 shifter_out_im(var, 0);
543 tcg_gen_shri_i32(var, var, 1);
544 tcg_gen_shli_i32(tmp, tmp, 31);
545 tcg_gen_or_i32(var, var, tmp);
546 dead_tmp(tmp);
551 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
552 TCGv shift, int flags)
554 if (flags) {
555 switch (shiftop) {
556 case 0: gen_helper_shl_cc(var, var, shift); break;
557 case 1: gen_helper_shr_cc(var, var, shift); break;
558 case 2: gen_helper_sar_cc(var, var, shift); break;
559 case 3: gen_helper_ror_cc(var, var, shift); break;
561 } else {
562 switch (shiftop) {
563 case 0: gen_helper_shl(var, var, shift); break;
564 case 1: gen_helper_shr(var, var, shift); break;
565 case 2: gen_helper_sar(var, var, shift); break;
566 case 3: gen_helper_ror(var, var, shift); break;
569 dead_tmp(shift);
572 #define PAS_OP(pfx) \
573 switch (op2) { \
574 case 0: gen_pas_helper(glue(pfx,add16)); break; \
575 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
576 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
577 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
578 case 4: gen_pas_helper(glue(pfx,add8)); break; \
579 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
581 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
583 TCGv tmp;
585 switch (op1) {
586 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
587 case 1:
588 tmp = tcg_temp_new(TCG_TYPE_PTR);
589 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
590 PAS_OP(s)
591 break;
592 case 5:
593 tmp = tcg_temp_new(TCG_TYPE_PTR);
594 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
595 PAS_OP(u)
596 break;
597 #undef gen_pas_helper
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
599 case 2:
600 PAS_OP(q);
601 break;
602 case 3:
603 PAS_OP(sh);
604 break;
605 case 6:
606 PAS_OP(uq);
607 break;
608 case 7:
609 PAS_OP(uh);
610 break;
611 #undef gen_pas_helper
614 #undef PAS_OP
616 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
617 #define PAS_OP(pfx) \
618 switch (op2) { \
619 case 0: gen_pas_helper(glue(pfx,add8)); break; \
620 case 1: gen_pas_helper(glue(pfx,add16)); break; \
621 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
622 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
623 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
624 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
626 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
628 TCGv tmp;
630 switch (op1) {
631 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
632 case 0:
633 tmp = tcg_temp_new(TCG_TYPE_PTR);
634 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
635 PAS_OP(s)
636 break;
637 case 4:
638 tmp = tcg_temp_new(TCG_TYPE_PTR);
639 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
640 PAS_OP(u)
641 break;
642 #undef gen_pas_helper
643 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
644 case 1:
645 PAS_OP(q);
646 break;
647 case 2:
648 PAS_OP(sh);
649 break;
650 case 5:
651 PAS_OP(uq);
652 break;
653 case 6:
654 PAS_OP(uh);
655 break;
656 #undef gen_pas_helper
659 #undef PAS_OP
661 static void gen_test_cc(int cc, int label)
663 TCGv tmp;
664 TCGv tmp2;
665 int inv;
667 switch (cc) {
668 case 0: /* eq: Z */
669 tmp = load_cpu_field(ZF);
670 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
671 break;
672 case 1: /* ne: !Z */
673 tmp = load_cpu_field(ZF);
674 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
675 break;
676 case 2: /* cs: C */
677 tmp = load_cpu_field(CF);
678 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
679 break;
680 case 3: /* cc: !C */
681 tmp = load_cpu_field(CF);
682 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
683 break;
684 case 4: /* mi: N */
685 tmp = load_cpu_field(NF);
686 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
687 break;
688 case 5: /* pl: !N */
689 tmp = load_cpu_field(NF);
690 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
691 break;
692 case 6: /* vs: V */
693 tmp = load_cpu_field(VF);
694 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
695 break;
696 case 7: /* vc: !V */
697 tmp = load_cpu_field(VF);
698 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
699 break;
700 case 8: /* hi: C && !Z */
701 inv = gen_new_label();
702 tmp = load_cpu_field(CF);
703 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
704 dead_tmp(tmp);
705 tmp = load_cpu_field(ZF);
706 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
707 gen_set_label(inv);
708 break;
709 case 9: /* ls: !C || Z */
710 tmp = load_cpu_field(CF);
711 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
712 dead_tmp(tmp);
713 tmp = load_cpu_field(ZF);
714 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
715 break;
716 case 10: /* ge: N == V -> N ^ V == 0 */
717 tmp = load_cpu_field(VF);
718 tmp2 = load_cpu_field(NF);
719 tcg_gen_xor_i32(tmp, tmp, tmp2);
720 dead_tmp(tmp2);
721 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
722 break;
723 case 11: /* lt: N != V -> N ^ V != 0 */
724 tmp = load_cpu_field(VF);
725 tmp2 = load_cpu_field(NF);
726 tcg_gen_xor_i32(tmp, tmp, tmp2);
727 dead_tmp(tmp2);
728 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
729 break;
730 case 12: /* gt: !Z && N == V */
731 inv = gen_new_label();
732 tmp = load_cpu_field(ZF);
733 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
734 dead_tmp(tmp);
735 tmp = load_cpu_field(VF);
736 tmp2 = load_cpu_field(NF);
737 tcg_gen_xor_i32(tmp, tmp, tmp2);
738 dead_tmp(tmp2);
739 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
740 gen_set_label(inv);
741 break;
742 case 13: /* le: Z || N != V */
743 tmp = load_cpu_field(ZF);
744 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
745 dead_tmp(tmp);
746 tmp = load_cpu_field(VF);
747 tmp2 = load_cpu_field(NF);
748 tcg_gen_xor_i32(tmp, tmp, tmp2);
749 dead_tmp(tmp2);
750 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
751 break;
752 default:
753 fprintf(stderr, "Bad condition code 0x%x\n", cc);
754 abort();
756 dead_tmp(tmp);
759 const uint8_t table_logic_cc[16] = {
760 1, /* and */
761 1, /* xor */
762 0, /* sub */
763 0, /* rsb */
764 0, /* add */
765 0, /* adc */
766 0, /* sbc */
767 0, /* rsc */
768 1, /* andl */
769 1, /* xorl */
770 0, /* cmp */
771 0, /* cmn */
772 1, /* orr */
773 1, /* mov */
774 1, /* bic */
775 1, /* mvn */
778 /* Set PC and Thumb state from an immediate address. */
779 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
781 TCGv tmp;
783 s->is_jmp = DISAS_UPDATE;
784 tmp = new_tmp();
785 if (s->thumb != (addr & 1)) {
786 tcg_gen_movi_i32(tmp, addr & 1);
787 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
789 tcg_gen_movi_i32(tmp, addr & ~1);
790 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
791 dead_tmp(tmp);
794 /* Set PC and Thumb state from var. var is marked as dead. */
795 static inline void gen_bx(DisasContext *s, TCGv var)
797 TCGv tmp;
799 s->is_jmp = DISAS_UPDATE;
800 tmp = new_tmp();
801 tcg_gen_andi_i32(tmp, var, 1);
802 store_cpu_field(tmp, thumb);
803 tcg_gen_andi_i32(var, var, ~1);
804 store_cpu_field(var, regs[15]);
807 /* TODO: This should be removed. Use gen_bx instead. */
808 static inline void gen_bx_T0(DisasContext *s)
810 TCGv tmp = new_tmp();
811 tcg_gen_mov_i32(tmp, cpu_T[0]);
812 gen_bx(s, tmp);
815 #if defined(CONFIG_USER_ONLY)
816 #define gen_ldst(name, s) gen_op_##name##_raw()
817 #else
818 #define gen_ldst(name, s) do { \
819 s->is_mem = 1; \
820 if (IS_USER(s)) \
821 gen_op_##name##_user(); \
822 else \
823 gen_op_##name##_kernel(); \
824 } while (0)
825 #endif
826 static inline TCGv gen_ld8s(TCGv addr, int index)
828 TCGv tmp = new_tmp();
829 tcg_gen_qemu_ld8s(tmp, addr, index);
830 return tmp;
832 static inline TCGv gen_ld8u(TCGv addr, int index)
834 TCGv tmp = new_tmp();
835 tcg_gen_qemu_ld8u(tmp, addr, index);
836 return tmp;
838 static inline TCGv gen_ld16s(TCGv addr, int index)
840 TCGv tmp = new_tmp();
841 tcg_gen_qemu_ld16s(tmp, addr, index);
842 return tmp;
844 static inline TCGv gen_ld16u(TCGv addr, int index)
846 TCGv tmp = new_tmp();
847 tcg_gen_qemu_ld16u(tmp, addr, index);
848 return tmp;
850 static inline TCGv gen_ld32(TCGv addr, int index)
852 TCGv tmp = new_tmp();
853 tcg_gen_qemu_ld32u(tmp, addr, index);
854 return tmp;
856 static inline void gen_st8(TCGv val, TCGv addr, int index)
858 tcg_gen_qemu_st8(val, addr, index);
859 dead_tmp(val);
861 static inline void gen_st16(TCGv val, TCGv addr, int index)
863 tcg_gen_qemu_st16(val, addr, index);
864 dead_tmp(val);
866 static inline void gen_st32(TCGv val, TCGv addr, int index)
868 tcg_gen_qemu_st32(val, addr, index);
869 dead_tmp(val);
872 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
874 load_reg_var(s, cpu_T[0], reg);
877 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
879 load_reg_var(s, cpu_T[1], reg);
882 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
884 load_reg_var(s, cpu_T[2], reg);
887 static inline void gen_set_pc_im(uint32_t val)
889 TCGv tmp = new_tmp();
890 tcg_gen_movi_i32(tmp, val);
891 store_cpu_field(tmp, regs[15]);
894 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
896 TCGv tmp;
897 if (reg == 15) {
898 tmp = new_tmp();
899 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
900 } else {
901 tmp = cpu_T[t];
903 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
904 if (reg == 15) {
905 dead_tmp(tmp);
906 s->is_jmp = DISAS_JUMP;
910 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
912 gen_movl_reg_TN(s, reg, 0);
915 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
917 gen_movl_reg_TN(s, reg, 1);
920 /* Force a TB lookup after an instruction that changes the CPU state. */
921 static inline void gen_lookup_tb(DisasContext *s)
923 gen_op_movl_T0_im(s->pc);
924 gen_movl_reg_T0(s, 15);
925 s->is_jmp = DISAS_UPDATE;
928 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
929 TCGv var)
931 int val, rm, shift, shiftop;
932 TCGv offset;
934 if (!(insn & (1 << 25))) {
935 /* immediate */
936 val = insn & 0xfff;
937 if (!(insn & (1 << 23)))
938 val = -val;
939 if (val != 0)
940 tcg_gen_addi_i32(var, var, val);
941 } else {
942 /* shift/register */
943 rm = (insn) & 0xf;
944 shift = (insn >> 7) & 0x1f;
945 shiftop = (insn >> 5) & 3;
946 offset = load_reg(s, rm);
947 gen_arm_shift_im(offset, shiftop, shift, 0);
948 if (!(insn & (1 << 23)))
949 tcg_gen_sub_i32(var, var, offset);
950 else
951 tcg_gen_add_i32(var, var, offset);
952 dead_tmp(offset);
956 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
957 int extra, TCGv var)
959 int val, rm;
960 TCGv offset;
962 if (insn & (1 << 22)) {
963 /* immediate */
964 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
965 if (!(insn & (1 << 23)))
966 val = -val;
967 val += extra;
968 if (val != 0)
969 tcg_gen_addi_i32(var, var, val);
970 } else {
971 /* register */
972 if (extra)
973 tcg_gen_addi_i32(var, var, extra);
974 rm = (insn) & 0xf;
975 offset = load_reg(s, rm);
976 if (!(insn & (1 << 23)))
977 tcg_gen_sub_i32(var, var, offset);
978 else
979 tcg_gen_add_i32(var, var, offset);
980 dead_tmp(offset);
984 #define VFP_OP2(name) \
985 static inline void gen_vfp_##name(int dp) \
987 if (dp) \
988 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
989 else \
990 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
993 #define VFP_OP1(name) \
994 static inline void gen_vfp_##name(int dp, int arg) \
996 if (dp) \
997 gen_op_vfp_##name##d(arg); \
998 else \
999 gen_op_vfp_##name##s(arg); \
1002 VFP_OP2(add)
1003 VFP_OP2(sub)
1004 VFP_OP2(mul)
1005 VFP_OP2(div)
1007 #undef VFP_OP2
1009 static inline void gen_vfp_abs(int dp)
1011 if (dp)
1012 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1013 else
1014 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1017 static inline void gen_vfp_neg(int dp)
1019 if (dp)
1020 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1021 else
1022 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1025 static inline void gen_vfp_sqrt(int dp)
1027 if (dp)
1028 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1029 else
1030 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1033 static inline void gen_vfp_cmp(int dp)
1035 if (dp)
1036 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1037 else
1038 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1041 static inline void gen_vfp_cmpe(int dp)
1043 if (dp)
1044 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1045 else
1046 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1049 static inline void gen_vfp_F1_ld0(int dp)
1051 if (dp)
1052 tcg_gen_movi_i64(cpu_F1d, 0);
1053 else
1054 tcg_gen_movi_i32(cpu_F1s, 0);
1057 static inline void gen_vfp_uito(int dp)
1059 if (dp)
1060 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1061 else
1062 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1065 static inline void gen_vfp_sito(int dp)
1067 if (dp)
1068 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1069 else
1070 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1073 static inline void gen_vfp_toui(int dp)
1075 if (dp)
1076 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1077 else
1078 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1081 static inline void gen_vfp_touiz(int dp)
1083 if (dp)
1084 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1085 else
1086 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1089 static inline void gen_vfp_tosi(int dp)
1091 if (dp)
1092 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1093 else
1094 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1097 static inline void gen_vfp_tosiz(int dp)
1099 if (dp)
1100 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1101 else
1102 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1105 #define VFP_GEN_FIX(name) \
1106 static inline void gen_vfp_##name(int dp, int shift) \
1108 if (dp) \
1109 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1110 else \
1111 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1113 VFP_GEN_FIX(tosh)
1114 VFP_GEN_FIX(tosl)
1115 VFP_GEN_FIX(touh)
1116 VFP_GEN_FIX(toul)
1117 VFP_GEN_FIX(shto)
1118 VFP_GEN_FIX(slto)
1119 VFP_GEN_FIX(uhto)
1120 VFP_GEN_FIX(ulto)
1121 #undef VFP_GEN_FIX
1123 static inline void gen_vfp_ld(DisasContext *s, int dp)
1125 if (dp)
1126 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1127 else
1128 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1131 static inline void gen_vfp_st(DisasContext *s, int dp)
1133 if (dp)
1134 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1135 else
1136 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1139 static inline long
1140 vfp_reg_offset (int dp, int reg)
1142 if (dp)
1143 return offsetof(CPUARMState, vfp.regs[reg]);
1144 else if (reg & 1) {
1145 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1146 + offsetof(CPU_DoubleU, l.upper);
1147 } else {
1148 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1149 + offsetof(CPU_DoubleU, l.lower);
1153 /* Return the offset of a 32-bit piece of a NEON register.
1154 zero is the least significant end of the register. */
1155 static inline long
1156 neon_reg_offset (int reg, int n)
1158 int sreg;
1159 sreg = reg * 2 + n;
1160 return vfp_reg_offset(0, sreg);
1163 /* FIXME: Remove these. */
1164 #define neon_T0 cpu_T[0]
1165 #define neon_T1 cpu_T[1]
1166 #define NEON_GET_REG(T, reg, n) \
1167 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1168 #define NEON_SET_REG(T, reg, n) \
1169 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1171 static TCGv neon_load_reg(int reg, int pass)
1173 TCGv tmp = new_tmp();
1174 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1175 return tmp;
1178 static void neon_store_reg(int reg, int pass, TCGv var)
1180 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1181 dead_tmp(var);
1184 static inline void neon_load_reg64(TCGv var, int reg)
1186 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1189 static inline void neon_store_reg64(TCGv var, int reg)
1191 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1194 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1195 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1196 #define tcg_gen_st_f32 tcg_gen_st_i32
1197 #define tcg_gen_st_f64 tcg_gen_st_i64
1199 static inline void gen_mov_F0_vreg(int dp, int reg)
1201 if (dp)
1202 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1203 else
1204 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1207 static inline void gen_mov_F1_vreg(int dp, int reg)
1209 if (dp)
1210 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1211 else
1212 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1215 static inline void gen_mov_vreg_F0(int dp, int reg)
1217 if (dp)
1218 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1219 else
1220 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1223 #define ARM_CP_RW_BIT (1 << 20)
1225 static inline void iwmmxt_load_reg(TCGv var, int reg)
1227 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1230 static inline void iwmmxt_store_reg(TCGv var, int reg)
1232 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1235 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1237 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1240 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1242 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1245 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1247 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1250 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1252 iwmmxt_store_reg(cpu_M0, rn);
1255 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1257 iwmmxt_load_reg(cpu_M0, rn);
1260 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1262 iwmmxt_load_reg(cpu_V1, rn);
1263 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1266 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1268 iwmmxt_load_reg(cpu_V1, rn);
1269 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1272 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1274 iwmmxt_load_reg(cpu_V1, rn);
1275 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1278 #define IWMMXT_OP(name) \
1279 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1281 iwmmxt_load_reg(cpu_V1, rn); \
1282 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1285 #define IWMMXT_OP_ENV(name) \
1286 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1288 iwmmxt_load_reg(cpu_V1, rn); \
1289 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1292 #define IWMMXT_OP_ENV_SIZE(name) \
1293 IWMMXT_OP_ENV(name##b) \
1294 IWMMXT_OP_ENV(name##w) \
1295 IWMMXT_OP_ENV(name##l)
1297 #define IWMMXT_OP_ENV1(name) \
1298 static inline void gen_op_iwmmxt_##name##_M0(void) \
1300 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1303 IWMMXT_OP(maddsq)
1304 IWMMXT_OP(madduq)
1305 IWMMXT_OP(sadb)
1306 IWMMXT_OP(sadw)
1307 IWMMXT_OP(mulslw)
1308 IWMMXT_OP(mulshw)
1309 IWMMXT_OP(mululw)
1310 IWMMXT_OP(muluhw)
1311 IWMMXT_OP(macsw)
1312 IWMMXT_OP(macuw)
1314 IWMMXT_OP_ENV_SIZE(unpackl)
1315 IWMMXT_OP_ENV_SIZE(unpackh)
1317 IWMMXT_OP_ENV1(unpacklub)
1318 IWMMXT_OP_ENV1(unpackluw)
1319 IWMMXT_OP_ENV1(unpacklul)
1320 IWMMXT_OP_ENV1(unpackhub)
1321 IWMMXT_OP_ENV1(unpackhuw)
1322 IWMMXT_OP_ENV1(unpackhul)
1323 IWMMXT_OP_ENV1(unpacklsb)
1324 IWMMXT_OP_ENV1(unpacklsw)
1325 IWMMXT_OP_ENV1(unpacklsl)
1326 IWMMXT_OP_ENV1(unpackhsb)
1327 IWMMXT_OP_ENV1(unpackhsw)
1328 IWMMXT_OP_ENV1(unpackhsl)
1330 IWMMXT_OP_ENV_SIZE(cmpeq)
1331 IWMMXT_OP_ENV_SIZE(cmpgtu)
1332 IWMMXT_OP_ENV_SIZE(cmpgts)
1334 IWMMXT_OP_ENV_SIZE(mins)
1335 IWMMXT_OP_ENV_SIZE(minu)
1336 IWMMXT_OP_ENV_SIZE(maxs)
1337 IWMMXT_OP_ENV_SIZE(maxu)
1339 IWMMXT_OP_ENV_SIZE(subn)
1340 IWMMXT_OP_ENV_SIZE(addn)
1341 IWMMXT_OP_ENV_SIZE(subu)
1342 IWMMXT_OP_ENV_SIZE(addu)
1343 IWMMXT_OP_ENV_SIZE(subs)
1344 IWMMXT_OP_ENV_SIZE(adds)
1346 IWMMXT_OP_ENV(avgb0)
1347 IWMMXT_OP_ENV(avgb1)
1348 IWMMXT_OP_ENV(avgw0)
1349 IWMMXT_OP_ENV(avgw1)
1351 IWMMXT_OP(msadb)
1353 IWMMXT_OP_ENV(packuw)
1354 IWMMXT_OP_ENV(packul)
1355 IWMMXT_OP_ENV(packuq)
1356 IWMMXT_OP_ENV(packsw)
1357 IWMMXT_OP_ENV(packsl)
1358 IWMMXT_OP_ENV(packsq)
1360 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1362 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1365 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1367 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1370 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1372 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1375 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1377 iwmmxt_load_reg(cpu_V1, rn);
1378 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1381 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1383 TCGv tmp = tcg_const_i32(shift);
1384 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1387 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1389 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1390 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1391 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1394 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1396 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1397 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1398 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1401 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1403 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1404 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1405 if (mask != ~0u)
1406 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1409 static void gen_op_iwmmxt_set_mup(void)
1411 TCGv tmp;
1412 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1413 tcg_gen_ori_i32(tmp, tmp, 2);
1414 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1417 static void gen_op_iwmmxt_set_cup(void)
1419 TCGv tmp;
1420 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1421 tcg_gen_ori_i32(tmp, tmp, 1);
1422 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1425 static void gen_op_iwmmxt_setpsr_nz(void)
1427 TCGv tmp = new_tmp();
1428 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1429 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1432 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1434 iwmmxt_load_reg(cpu_V1, rn);
1435 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1436 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1440 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1442 iwmmxt_load_reg(cpu_V0, rn);
1443 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1444 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1445 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1448 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1450 tcg_gen_extu_i32_i64(cpu_V0, cpu_T[0]);
1451 tcg_gen_extu_i32_i64(cpu_V1, cpu_T[0]);
1452 tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
1453 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
1454 iwmmxt_store_reg(cpu_V0, rn);
1457 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1459 int rd;
1460 uint32_t offset;
1462 rd = (insn >> 16) & 0xf;
1463 gen_movl_T1_reg(s, rd);
1465 offset = (insn & 0xff) << ((insn >> 7) & 2);
1466 if (insn & (1 << 24)) {
1467 /* Pre indexed */
1468 if (insn & (1 << 23))
1469 gen_op_addl_T1_im(offset);
1470 else
1471 gen_op_addl_T1_im(-offset);
1473 if (insn & (1 << 21))
1474 gen_movl_reg_T1(s, rd);
1475 } else if (insn & (1 << 21)) {
1476 /* Post indexed */
1477 if (insn & (1 << 23))
1478 gen_op_movl_T0_im(offset);
1479 else
1480 gen_op_movl_T0_im(- offset);
1481 gen_op_addl_T0_T1();
1482 gen_movl_reg_T0(s, rd);
1483 } else if (!(insn & (1 << 23)))
1484 return 1;
1485 return 0;
1488 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1490 int rd = (insn >> 0) & 0xf;
1492 if (insn & (1 << 8))
1493 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1494 return 1;
1495 else
1496 gen_op_iwmmxt_movl_T0_wCx(rd);
1497 else
1498 gen_iwmmxt_movl_T0_T1_wRn(rd);
1500 gen_op_movl_T1_im(mask);
1501 gen_op_andl_T0_T1();
1502 return 0;
1505 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1506 (ie. an undefined instruction). */
1507 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1509 int rd, wrd;
1510 int rdhi, rdlo, rd0, rd1, i;
1511 TCGv tmp;
1513 if ((insn & 0x0e000e00) == 0x0c000000) {
1514 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1515 wrd = insn & 0xf;
1516 rdlo = (insn >> 12) & 0xf;
1517 rdhi = (insn >> 16) & 0xf;
1518 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1519 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1520 gen_movl_reg_T0(s, rdlo);
1521 gen_movl_reg_T1(s, rdhi);
1522 } else { /* TMCRR */
1523 gen_movl_T0_reg(s, rdlo);
1524 gen_movl_T1_reg(s, rdhi);
1525 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1526 gen_op_iwmmxt_set_mup();
1528 return 0;
1531 wrd = (insn >> 12) & 0xf;
1532 if (gen_iwmmxt_address(s, insn))
1533 return 1;
1534 if (insn & ARM_CP_RW_BIT) {
1535 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1536 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1537 tcg_gen_mov_i32(cpu_T[0], tmp);
1538 dead_tmp(tmp);
1539 gen_op_iwmmxt_movl_wCx_T0(wrd);
1540 } else {
1541 i = 1;
1542 if (insn & (1 << 8)) {
1543 if (insn & (1 << 22)) { /* WLDRD */
1544 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1545 i = 0;
1546 } else { /* WLDRW wRd */
1547 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1549 } else {
1550 if (insn & (1 << 22)) { /* WLDRH */
1551 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1552 } else { /* WLDRB */
1553 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1556 if (i) {
1557 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1558 dead_tmp(tmp);
1560 gen_op_iwmmxt_movq_wRn_M0(wrd);
1562 } else {
1563 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1564 gen_op_iwmmxt_movl_T0_wCx(wrd);
1565 tmp = new_tmp();
1566 tcg_gen_mov_i32(tmp, cpu_T[0]);
1567 gen_st32(tmp, cpu_T[1], IS_USER(s));
1568 } else {
1569 gen_op_iwmmxt_movq_M0_wRn(wrd);
1570 tmp = new_tmp();
1571 if (insn & (1 << 8)) {
1572 if (insn & (1 << 22)) { /* WSTRD */
1573 dead_tmp(tmp);
1574 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1575 } else { /* WSTRW wRd */
1576 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1577 gen_st32(tmp, cpu_T[1], IS_USER(s));
1579 } else {
1580 if (insn & (1 << 22)) { /* WSTRH */
1581 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1582 gen_st16(tmp, cpu_T[1], IS_USER(s));
1583 } else { /* WSTRB */
1584 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1585 gen_st8(tmp, cpu_T[1], IS_USER(s));
1590 return 0;
1593 if ((insn & 0x0f000000) != 0x0e000000)
1594 return 1;
1596 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1597 case 0x000: /* WOR */
1598 wrd = (insn >> 12) & 0xf;
1599 rd0 = (insn >> 0) & 0xf;
1600 rd1 = (insn >> 16) & 0xf;
1601 gen_op_iwmmxt_movq_M0_wRn(rd0);
1602 gen_op_iwmmxt_orq_M0_wRn(rd1);
1603 gen_op_iwmmxt_setpsr_nz();
1604 gen_op_iwmmxt_movq_wRn_M0(wrd);
1605 gen_op_iwmmxt_set_mup();
1606 gen_op_iwmmxt_set_cup();
1607 break;
1608 case 0x011: /* TMCR */
1609 if (insn & 0xf)
1610 return 1;
1611 rd = (insn >> 12) & 0xf;
1612 wrd = (insn >> 16) & 0xf;
1613 switch (wrd) {
1614 case ARM_IWMMXT_wCID:
1615 case ARM_IWMMXT_wCASF:
1616 break;
1617 case ARM_IWMMXT_wCon:
1618 gen_op_iwmmxt_set_cup();
1619 /* Fall through. */
1620 case ARM_IWMMXT_wCSSF:
1621 gen_op_iwmmxt_movl_T0_wCx(wrd);
1622 gen_movl_T1_reg(s, rd);
1623 gen_op_bicl_T0_T1();
1624 gen_op_iwmmxt_movl_wCx_T0(wrd);
1625 break;
1626 case ARM_IWMMXT_wCGR0:
1627 case ARM_IWMMXT_wCGR1:
1628 case ARM_IWMMXT_wCGR2:
1629 case ARM_IWMMXT_wCGR3:
1630 gen_op_iwmmxt_set_cup();
1631 gen_movl_reg_T0(s, rd);
1632 gen_op_iwmmxt_movl_wCx_T0(wrd);
1633 break;
1634 default:
1635 return 1;
1637 break;
1638 case 0x100: /* WXOR */
1639 wrd = (insn >> 12) & 0xf;
1640 rd0 = (insn >> 0) & 0xf;
1641 rd1 = (insn >> 16) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0);
1643 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1644 gen_op_iwmmxt_setpsr_nz();
1645 gen_op_iwmmxt_movq_wRn_M0(wrd);
1646 gen_op_iwmmxt_set_mup();
1647 gen_op_iwmmxt_set_cup();
1648 break;
1649 case 0x111: /* TMRC */
1650 if (insn & 0xf)
1651 return 1;
1652 rd = (insn >> 12) & 0xf;
1653 wrd = (insn >> 16) & 0xf;
1654 gen_op_iwmmxt_movl_T0_wCx(wrd);
1655 gen_movl_reg_T0(s, rd);
1656 break;
1657 case 0x300: /* WANDN */
1658 wrd = (insn >> 12) & 0xf;
1659 rd0 = (insn >> 0) & 0xf;
1660 rd1 = (insn >> 16) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0);
1662 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1663 gen_op_iwmmxt_andq_M0_wRn(rd1);
1664 gen_op_iwmmxt_setpsr_nz();
1665 gen_op_iwmmxt_movq_wRn_M0(wrd);
1666 gen_op_iwmmxt_set_mup();
1667 gen_op_iwmmxt_set_cup();
1668 break;
1669 case 0x200: /* WAND */
1670 wrd = (insn >> 12) & 0xf;
1671 rd0 = (insn >> 0) & 0xf;
1672 rd1 = (insn >> 16) & 0xf;
1673 gen_op_iwmmxt_movq_M0_wRn(rd0);
1674 gen_op_iwmmxt_andq_M0_wRn(rd1);
1675 gen_op_iwmmxt_setpsr_nz();
1676 gen_op_iwmmxt_movq_wRn_M0(wrd);
1677 gen_op_iwmmxt_set_mup();
1678 gen_op_iwmmxt_set_cup();
1679 break;
1680 case 0x810: case 0xa10: /* WMADD */
1681 wrd = (insn >> 12) & 0xf;
1682 rd0 = (insn >> 0) & 0xf;
1683 rd1 = (insn >> 16) & 0xf;
1684 gen_op_iwmmxt_movq_M0_wRn(rd0);
1685 if (insn & (1 << 21))
1686 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1687 else
1688 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1689 gen_op_iwmmxt_movq_wRn_M0(wrd);
1690 gen_op_iwmmxt_set_mup();
1691 break;
1692 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1693 wrd = (insn >> 12) & 0xf;
1694 rd0 = (insn >> 16) & 0xf;
1695 rd1 = (insn >> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0);
1697 switch ((insn >> 22) & 3) {
1698 case 0:
1699 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1700 break;
1701 case 1:
1702 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1703 break;
1704 case 2:
1705 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1706 break;
1707 case 3:
1708 return 1;
1710 gen_op_iwmmxt_movq_wRn_M0(wrd);
1711 gen_op_iwmmxt_set_mup();
1712 gen_op_iwmmxt_set_cup();
1713 break;
1714 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1715 wrd = (insn >> 12) & 0xf;
1716 rd0 = (insn >> 16) & 0xf;
1717 rd1 = (insn >> 0) & 0xf;
1718 gen_op_iwmmxt_movq_M0_wRn(rd0);
1719 switch ((insn >> 22) & 3) {
1720 case 0:
1721 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1722 break;
1723 case 1:
1724 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1725 break;
1726 case 2:
1727 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1728 break;
1729 case 3:
1730 return 1;
1732 gen_op_iwmmxt_movq_wRn_M0(wrd);
1733 gen_op_iwmmxt_set_mup();
1734 gen_op_iwmmxt_set_cup();
1735 break;
1736 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1737 wrd = (insn >> 12) & 0xf;
1738 rd0 = (insn >> 16) & 0xf;
1739 rd1 = (insn >> 0) & 0xf;
1740 gen_op_iwmmxt_movq_M0_wRn(rd0);
1741 if (insn & (1 << 22))
1742 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1743 else
1744 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1745 if (!(insn & (1 << 20)))
1746 gen_op_iwmmxt_addl_M0_wRn(wrd);
1747 gen_op_iwmmxt_movq_wRn_M0(wrd);
1748 gen_op_iwmmxt_set_mup();
1749 break;
1750 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1751 wrd = (insn >> 12) & 0xf;
1752 rd0 = (insn >> 16) & 0xf;
1753 rd1 = (insn >> 0) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0);
1755 if (insn & (1 << 21)) {
1756 if (insn & (1 << 20))
1757 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1758 else
1759 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1760 } else {
1761 if (insn & (1 << 20))
1762 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1763 else
1764 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd);
1767 gen_op_iwmmxt_set_mup();
1768 break;
1769 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1770 wrd = (insn >> 12) & 0xf;
1771 rd0 = (insn >> 16) & 0xf;
1772 rd1 = (insn >> 0) & 0xf;
1773 gen_op_iwmmxt_movq_M0_wRn(rd0);
1774 if (insn & (1 << 21))
1775 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1776 else
1777 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1778 if (!(insn & (1 << 20))) {
1779 iwmmxt_load_reg(cpu_V1, wrd);
1780 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1782 gen_op_iwmmxt_movq_wRn_M0(wrd);
1783 gen_op_iwmmxt_set_mup();
1784 break;
1785 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1786 wrd = (insn >> 12) & 0xf;
1787 rd0 = (insn >> 16) & 0xf;
1788 rd1 = (insn >> 0) & 0xf;
1789 gen_op_iwmmxt_movq_M0_wRn(rd0);
1790 switch ((insn >> 22) & 3) {
1791 case 0:
1792 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1793 break;
1794 case 1:
1795 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1796 break;
1797 case 2:
1798 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1799 break;
1800 case 3:
1801 return 1;
1803 gen_op_iwmmxt_movq_wRn_M0(wrd);
1804 gen_op_iwmmxt_set_mup();
1805 gen_op_iwmmxt_set_cup();
1806 break;
1807 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1808 wrd = (insn >> 12) & 0xf;
1809 rd0 = (insn >> 16) & 0xf;
1810 rd1 = (insn >> 0) & 0xf;
1811 gen_op_iwmmxt_movq_M0_wRn(rd0);
1812 if (insn & (1 << 22)) {
1813 if (insn & (1 << 20))
1814 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1815 else
1816 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1817 } else {
1818 if (insn & (1 << 20))
1819 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1820 else
1821 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1823 gen_op_iwmmxt_movq_wRn_M0(wrd);
1824 gen_op_iwmmxt_set_mup();
1825 gen_op_iwmmxt_set_cup();
1826 break;
1827 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1828 wrd = (insn >> 12) & 0xf;
1829 rd0 = (insn >> 16) & 0xf;
1830 rd1 = (insn >> 0) & 0xf;
1831 gen_op_iwmmxt_movq_M0_wRn(rd0);
1832 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1833 gen_op_movl_T1_im(7);
1834 gen_op_andl_T0_T1();
1835 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1836 gen_op_iwmmxt_movq_wRn_M0(wrd);
1837 gen_op_iwmmxt_set_mup();
1838 break;
1839 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1840 rd = (insn >> 12) & 0xf;
1841 wrd = (insn >> 16) & 0xf;
1842 gen_movl_T0_reg(s, rd);
1843 gen_op_iwmmxt_movq_M0_wRn(wrd);
1844 switch ((insn >> 6) & 3) {
1845 case 0:
1846 gen_op_movl_T1_im(0xff);
1847 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1848 break;
1849 case 1:
1850 gen_op_movl_T1_im(0xffff);
1851 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1852 break;
1853 case 2:
1854 gen_op_movl_T1_im(0xffffffff);
1855 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1856 break;
1857 case 3:
1858 return 1;
1860 gen_op_iwmmxt_movq_wRn_M0(wrd);
1861 gen_op_iwmmxt_set_mup();
1862 break;
1863 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1864 rd = (insn >> 12) & 0xf;
1865 wrd = (insn >> 16) & 0xf;
1866 if (rd == 15)
1867 return 1;
1868 gen_op_iwmmxt_movq_M0_wRn(wrd);
1869 switch ((insn >> 22) & 3) {
1870 case 0:
1871 if (insn & 8)
1872 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1873 else {
1874 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1876 break;
1877 case 1:
1878 if (insn & 8)
1879 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1880 else {
1881 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1883 break;
1884 case 2:
1885 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1886 break;
1887 case 3:
1888 return 1;
1890 gen_movl_reg_T0(s, rd);
1891 break;
1892 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1893 if ((insn & 0x000ff008) != 0x0003f000)
1894 return 1;
1895 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1896 switch ((insn >> 22) & 3) {
1897 case 0:
1898 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1899 break;
1900 case 1:
1901 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1902 break;
1903 case 2:
1904 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1905 break;
1906 case 3:
1907 return 1;
1909 gen_op_shll_T1_im(28);
1910 gen_set_nzcv(cpu_T[1]);
1911 break;
1912 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1913 rd = (insn >> 12) & 0xf;
1914 wrd = (insn >> 16) & 0xf;
1915 gen_movl_T0_reg(s, rd);
1916 switch ((insn >> 6) & 3) {
1917 case 0:
1918 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1919 break;
1920 case 1:
1921 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1922 break;
1923 case 2:
1924 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1925 break;
1926 case 3:
1927 return 1;
1929 gen_op_iwmmxt_movq_wRn_M0(wrd);
1930 gen_op_iwmmxt_set_mup();
1931 break;
1932 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1933 if ((insn & 0x000ff00f) != 0x0003f000)
1934 return 1;
1935 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1936 switch ((insn >> 22) & 3) {
1937 case 0:
1938 for (i = 0; i < 7; i ++) {
1939 gen_op_shll_T1_im(4);
1940 gen_op_andl_T0_T1();
1942 break;
1943 case 1:
1944 for (i = 0; i < 3; i ++) {
1945 gen_op_shll_T1_im(8);
1946 gen_op_andl_T0_T1();
1948 break;
1949 case 2:
1950 gen_op_shll_T1_im(16);
1951 gen_op_andl_T0_T1();
1952 break;
1953 case 3:
1954 return 1;
1956 gen_set_nzcv(cpu_T[0]);
1957 break;
1958 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1959 wrd = (insn >> 12) & 0xf;
1960 rd0 = (insn >> 16) & 0xf;
1961 gen_op_iwmmxt_movq_M0_wRn(rd0);
1962 switch ((insn >> 22) & 3) {
1963 case 0:
1964 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1965 break;
1966 case 1:
1967 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1968 break;
1969 case 2:
1970 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1971 break;
1972 case 3:
1973 return 1;
1975 gen_op_iwmmxt_movq_wRn_M0(wrd);
1976 gen_op_iwmmxt_set_mup();
1977 break;
1978 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1979 if ((insn & 0x000ff00f) != 0x0003f000)
1980 return 1;
1981 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1982 switch ((insn >> 22) & 3) {
1983 case 0:
1984 for (i = 0; i < 7; i ++) {
1985 gen_op_shll_T1_im(4);
1986 gen_op_orl_T0_T1();
1988 break;
1989 case 1:
1990 for (i = 0; i < 3; i ++) {
1991 gen_op_shll_T1_im(8);
1992 gen_op_orl_T0_T1();
1994 break;
1995 case 2:
1996 gen_op_shll_T1_im(16);
1997 gen_op_orl_T0_T1();
1998 break;
1999 case 3:
2000 return 1;
2002 gen_set_nzcv(cpu_T[0]);
2003 break;
2004 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2005 rd = (insn >> 12) & 0xf;
2006 rd0 = (insn >> 16) & 0xf;
2007 if ((insn & 0xf) != 0)
2008 return 1;
2009 gen_op_iwmmxt_movq_M0_wRn(rd0);
2010 switch ((insn >> 22) & 3) {
2011 case 0:
2012 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2013 break;
2014 case 1:
2015 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2016 break;
2017 case 2:
2018 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2019 break;
2020 case 3:
2021 return 1;
2023 gen_movl_reg_T0(s, rd);
2024 break;
2025 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2026 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2027 wrd = (insn >> 12) & 0xf;
2028 rd0 = (insn >> 16) & 0xf;
2029 rd1 = (insn >> 0) & 0xf;
2030 gen_op_iwmmxt_movq_M0_wRn(rd0);
2031 switch ((insn >> 22) & 3) {
2032 case 0:
2033 if (insn & (1 << 21))
2034 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2035 else
2036 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2037 break;
2038 case 1:
2039 if (insn & (1 << 21))
2040 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2041 else
2042 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2043 break;
2044 case 2:
2045 if (insn & (1 << 21))
2046 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2047 else
2048 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2049 break;
2050 case 3:
2051 return 1;
2053 gen_op_iwmmxt_movq_wRn_M0(wrd);
2054 gen_op_iwmmxt_set_mup();
2055 gen_op_iwmmxt_set_cup();
2056 break;
2057 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2058 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2059 wrd = (insn >> 12) & 0xf;
2060 rd0 = (insn >> 16) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0);
2062 switch ((insn >> 22) & 3) {
2063 case 0:
2064 if (insn & (1 << 21))
2065 gen_op_iwmmxt_unpacklsb_M0();
2066 else
2067 gen_op_iwmmxt_unpacklub_M0();
2068 break;
2069 case 1:
2070 if (insn & (1 << 21))
2071 gen_op_iwmmxt_unpacklsw_M0();
2072 else
2073 gen_op_iwmmxt_unpackluw_M0();
2074 break;
2075 case 2:
2076 if (insn & (1 << 21))
2077 gen_op_iwmmxt_unpacklsl_M0();
2078 else
2079 gen_op_iwmmxt_unpacklul_M0();
2080 break;
2081 case 3:
2082 return 1;
2084 gen_op_iwmmxt_movq_wRn_M0(wrd);
2085 gen_op_iwmmxt_set_mup();
2086 gen_op_iwmmxt_set_cup();
2087 break;
2088 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2089 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2090 wrd = (insn >> 12) & 0xf;
2091 rd0 = (insn >> 16) & 0xf;
2092 gen_op_iwmmxt_movq_M0_wRn(rd0);
2093 switch ((insn >> 22) & 3) {
2094 case 0:
2095 if (insn & (1 << 21))
2096 gen_op_iwmmxt_unpackhsb_M0();
2097 else
2098 gen_op_iwmmxt_unpackhub_M0();
2099 break;
2100 case 1:
2101 if (insn & (1 << 21))
2102 gen_op_iwmmxt_unpackhsw_M0();
2103 else
2104 gen_op_iwmmxt_unpackhuw_M0();
2105 break;
2106 case 2:
2107 if (insn & (1 << 21))
2108 gen_op_iwmmxt_unpackhsl_M0();
2109 else
2110 gen_op_iwmmxt_unpackhul_M0();
2111 break;
2112 case 3:
2113 return 1;
2115 gen_op_iwmmxt_movq_wRn_M0(wrd);
2116 gen_op_iwmmxt_set_mup();
2117 gen_op_iwmmxt_set_cup();
2118 break;
2119 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2120 case 0x214: case 0x614: case 0xa14: case 0xe14:
2121 wrd = (insn >> 12) & 0xf;
2122 rd0 = (insn >> 16) & 0xf;
2123 gen_op_iwmmxt_movq_M0_wRn(rd0);
2124 if (gen_iwmmxt_shift(insn, 0xff))
2125 return 1;
2126 switch ((insn >> 22) & 3) {
2127 case 0:
2128 return 1;
2129 case 1:
2130 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2131 break;
2132 case 2:
2133 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2134 break;
2135 case 3:
2136 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2137 break;
2139 gen_op_iwmmxt_movq_wRn_M0(wrd);
2140 gen_op_iwmmxt_set_mup();
2141 gen_op_iwmmxt_set_cup();
2142 break;
2143 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2144 case 0x014: case 0x414: case 0x814: case 0xc14:
2145 wrd = (insn >> 12) & 0xf;
2146 rd0 = (insn >> 16) & 0xf;
2147 gen_op_iwmmxt_movq_M0_wRn(rd0);
2148 if (gen_iwmmxt_shift(insn, 0xff))
2149 return 1;
2150 switch ((insn >> 22) & 3) {
2151 case 0:
2152 return 1;
2153 case 1:
2154 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2155 break;
2156 case 2:
2157 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2158 break;
2159 case 3:
2160 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2161 break;
2163 gen_op_iwmmxt_movq_wRn_M0(wrd);
2164 gen_op_iwmmxt_set_mup();
2165 gen_op_iwmmxt_set_cup();
2166 break;
2167 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2168 case 0x114: case 0x514: case 0x914: case 0xd14:
2169 wrd = (insn >> 12) & 0xf;
2170 rd0 = (insn >> 16) & 0xf;
2171 gen_op_iwmmxt_movq_M0_wRn(rd0);
2172 if (gen_iwmmxt_shift(insn, 0xff))
2173 return 1;
2174 switch ((insn >> 22) & 3) {
2175 case 0:
2176 return 1;
2177 case 1:
2178 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2179 break;
2180 case 2:
2181 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2182 break;
2183 case 3:
2184 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2185 break;
2187 gen_op_iwmmxt_movq_wRn_M0(wrd);
2188 gen_op_iwmmxt_set_mup();
2189 gen_op_iwmmxt_set_cup();
2190 break;
2191 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2192 case 0x314: case 0x714: case 0xb14: case 0xf14:
2193 wrd = (insn >> 12) & 0xf;
2194 rd0 = (insn >> 16) & 0xf;
2195 gen_op_iwmmxt_movq_M0_wRn(rd0);
2196 switch ((insn >> 22) & 3) {
2197 case 0:
2198 return 1;
2199 case 1:
2200 if (gen_iwmmxt_shift(insn, 0xf))
2201 return 1;
2202 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2203 break;
2204 case 2:
2205 if (gen_iwmmxt_shift(insn, 0x1f))
2206 return 1;
2207 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2208 break;
2209 case 3:
2210 if (gen_iwmmxt_shift(insn, 0x3f))
2211 return 1;
2212 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2213 break;
2215 gen_op_iwmmxt_movq_wRn_M0(wrd);
2216 gen_op_iwmmxt_set_mup();
2217 gen_op_iwmmxt_set_cup();
2218 break;
2219 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2220 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2221 wrd = (insn >> 12) & 0xf;
2222 rd0 = (insn >> 16) & 0xf;
2223 rd1 = (insn >> 0) & 0xf;
2224 gen_op_iwmmxt_movq_M0_wRn(rd0);
2225 switch ((insn >> 22) & 3) {
2226 case 0:
2227 if (insn & (1 << 21))
2228 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2229 else
2230 gen_op_iwmmxt_minub_M0_wRn(rd1);
2231 break;
2232 case 1:
2233 if (insn & (1 << 21))
2234 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2235 else
2236 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2237 break;
2238 case 2:
2239 if (insn & (1 << 21))
2240 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2241 else
2242 gen_op_iwmmxt_minul_M0_wRn(rd1);
2243 break;
2244 case 3:
2245 return 1;
2247 gen_op_iwmmxt_movq_wRn_M0(wrd);
2248 gen_op_iwmmxt_set_mup();
2249 break;
2250 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2251 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2252 wrd = (insn >> 12) & 0xf;
2253 rd0 = (insn >> 16) & 0xf;
2254 rd1 = (insn >> 0) & 0xf;
2255 gen_op_iwmmxt_movq_M0_wRn(rd0);
2256 switch ((insn >> 22) & 3) {
2257 case 0:
2258 if (insn & (1 << 21))
2259 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2260 else
2261 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2262 break;
2263 case 1:
2264 if (insn & (1 << 21))
2265 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2266 else
2267 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2268 break;
2269 case 2:
2270 if (insn & (1 << 21))
2271 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2272 else
2273 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2274 break;
2275 case 3:
2276 return 1;
2278 gen_op_iwmmxt_movq_wRn_M0(wrd);
2279 gen_op_iwmmxt_set_mup();
2280 break;
2281 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2282 case 0x402: case 0x502: case 0x602: case 0x702:
2283 wrd = (insn >> 12) & 0xf;
2284 rd0 = (insn >> 16) & 0xf;
2285 rd1 = (insn >> 0) & 0xf;
2286 gen_op_iwmmxt_movq_M0_wRn(rd0);
2287 gen_op_movl_T0_im((insn >> 20) & 3);
2288 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2289 gen_op_iwmmxt_movq_wRn_M0(wrd);
2290 gen_op_iwmmxt_set_mup();
2291 break;
2292 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2293 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2294 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2295 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2296 wrd = (insn >> 12) & 0xf;
2297 rd0 = (insn >> 16) & 0xf;
2298 rd1 = (insn >> 0) & 0xf;
2299 gen_op_iwmmxt_movq_M0_wRn(rd0);
2300 switch ((insn >> 20) & 0xf) {
2301 case 0x0:
2302 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2303 break;
2304 case 0x1:
2305 gen_op_iwmmxt_subub_M0_wRn(rd1);
2306 break;
2307 case 0x3:
2308 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2309 break;
2310 case 0x4:
2311 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2312 break;
2313 case 0x5:
2314 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2315 break;
2316 case 0x7:
2317 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2318 break;
2319 case 0x8:
2320 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2321 break;
2322 case 0x9:
2323 gen_op_iwmmxt_subul_M0_wRn(rd1);
2324 break;
2325 case 0xb:
2326 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2327 break;
2328 default:
2329 return 1;
2331 gen_op_iwmmxt_movq_wRn_M0(wrd);
2332 gen_op_iwmmxt_set_mup();
2333 gen_op_iwmmxt_set_cup();
2334 break;
2335 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2336 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2337 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2338 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2339 wrd = (insn >> 12) & 0xf;
2340 rd0 = (insn >> 16) & 0xf;
2341 gen_op_iwmmxt_movq_M0_wRn(rd0);
2342 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2343 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2344 gen_op_iwmmxt_movq_wRn_M0(wrd);
2345 gen_op_iwmmxt_set_mup();
2346 gen_op_iwmmxt_set_cup();
2347 break;
2348 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2349 case 0x418: case 0x518: case 0x618: case 0x718:
2350 case 0x818: case 0x918: case 0xa18: case 0xb18:
2351 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2352 wrd = (insn >> 12) & 0xf;
2353 rd0 = (insn >> 16) & 0xf;
2354 rd1 = (insn >> 0) & 0xf;
2355 gen_op_iwmmxt_movq_M0_wRn(rd0);
2356 switch ((insn >> 20) & 0xf) {
2357 case 0x0:
2358 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2359 break;
2360 case 0x1:
2361 gen_op_iwmmxt_addub_M0_wRn(rd1);
2362 break;
2363 case 0x3:
2364 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2365 break;
2366 case 0x4:
2367 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2368 break;
2369 case 0x5:
2370 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2371 break;
2372 case 0x7:
2373 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2374 break;
2375 case 0x8:
2376 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2377 break;
2378 case 0x9:
2379 gen_op_iwmmxt_addul_M0_wRn(rd1);
2380 break;
2381 case 0xb:
2382 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2383 break;
2384 default:
2385 return 1;
2387 gen_op_iwmmxt_movq_wRn_M0(wrd);
2388 gen_op_iwmmxt_set_mup();
2389 gen_op_iwmmxt_set_cup();
2390 break;
2391 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2392 case 0x408: case 0x508: case 0x608: case 0x708:
2393 case 0x808: case 0x908: case 0xa08: case 0xb08:
2394 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2395 wrd = (insn >> 12) & 0xf;
2396 rd0 = (insn >> 16) & 0xf;
2397 rd1 = (insn >> 0) & 0xf;
2398 gen_op_iwmmxt_movq_M0_wRn(rd0);
2399 if (!(insn & (1 << 20)))
2400 return 1;
2401 switch ((insn >> 22) & 3) {
2402 case 0:
2403 return 1;
2404 case 1:
2405 if (insn & (1 << 21))
2406 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2407 else
2408 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2409 break;
2410 case 2:
2411 if (insn & (1 << 21))
2412 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2413 else
2414 gen_op_iwmmxt_packul_M0_wRn(rd1);
2415 break;
2416 case 3:
2417 if (insn & (1 << 21))
2418 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2419 else
2420 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2421 break;
2423 gen_op_iwmmxt_movq_wRn_M0(wrd);
2424 gen_op_iwmmxt_set_mup();
2425 gen_op_iwmmxt_set_cup();
2426 break;
2427 case 0x201: case 0x203: case 0x205: case 0x207:
2428 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2429 case 0x211: case 0x213: case 0x215: case 0x217:
2430 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2431 wrd = (insn >> 5) & 0xf;
2432 rd0 = (insn >> 12) & 0xf;
2433 rd1 = (insn >> 0) & 0xf;
2434 if (rd0 == 0xf || rd1 == 0xf)
2435 return 1;
2436 gen_op_iwmmxt_movq_M0_wRn(wrd);
2437 switch ((insn >> 16) & 0xf) {
2438 case 0x0: /* TMIA */
2439 gen_movl_T0_reg(s, rd0);
2440 gen_movl_T1_reg(s, rd1);
2441 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2442 break;
2443 case 0x8: /* TMIAPH */
2444 gen_movl_T0_reg(s, rd0);
2445 gen_movl_T1_reg(s, rd1);
2446 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2447 break;
2448 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2449 gen_movl_T1_reg(s, rd0);
2450 if (insn & (1 << 16))
2451 gen_op_shrl_T1_im(16);
2452 gen_op_movl_T0_T1();
2453 gen_movl_T1_reg(s, rd1);
2454 if (insn & (1 << 17))
2455 gen_op_shrl_T1_im(16);
2456 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2457 break;
2458 default:
2459 return 1;
2461 gen_op_iwmmxt_movq_wRn_M0(wrd);
2462 gen_op_iwmmxt_set_mup();
2463 break;
2464 default:
2465 return 1;
2468 return 0;
2471 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2472 (ie. an undefined instruction). */
2473 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2475 int acc, rd0, rd1, rdhi, rdlo;
2477 if ((insn & 0x0ff00f10) == 0x0e200010) {
2478 /* Multiply with Internal Accumulate Format */
2479 rd0 = (insn >> 12) & 0xf;
2480 rd1 = insn & 0xf;
2481 acc = (insn >> 5) & 7;
2483 if (acc != 0)
2484 return 1;
2486 switch ((insn >> 16) & 0xf) {
2487 case 0x0: /* MIA */
2488 gen_movl_T0_reg(s, rd0);
2489 gen_movl_T1_reg(s, rd1);
2490 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2491 break;
2492 case 0x8: /* MIAPH */
2493 gen_movl_T0_reg(s, rd0);
2494 gen_movl_T1_reg(s, rd1);
2495 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2496 break;
2497 case 0xc: /* MIABB */
2498 case 0xd: /* MIABT */
2499 case 0xe: /* MIATB */
2500 case 0xf: /* MIATT */
2501 gen_movl_T1_reg(s, rd0);
2502 if (insn & (1 << 16))
2503 gen_op_shrl_T1_im(16);
2504 gen_op_movl_T0_T1();
2505 gen_movl_T1_reg(s, rd1);
2506 if (insn & (1 << 17))
2507 gen_op_shrl_T1_im(16);
2508 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2509 break;
2510 default:
2511 return 1;
2514 gen_op_iwmmxt_movq_wRn_M0(acc);
2515 return 0;
2518 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2519 /* Internal Accumulator Access Format */
2520 rdhi = (insn >> 16) & 0xf;
2521 rdlo = (insn >> 12) & 0xf;
2522 acc = insn & 7;
2524 if (acc != 0)
2525 return 1;
2527 if (insn & ARM_CP_RW_BIT) { /* MRA */
2528 gen_iwmmxt_movl_T0_T1_wRn(acc);
2529 gen_movl_reg_T0(s, rdlo);
2530 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2531 gen_op_andl_T0_T1();
2532 gen_movl_reg_T0(s, rdhi);
2533 } else { /* MAR */
2534 gen_movl_T0_reg(s, rdlo);
2535 gen_movl_T1_reg(s, rdhi);
2536 gen_iwmmxt_movl_wRn_T0_T1(acc);
2538 return 0;
2541 return 1;
2544 /* Disassemble system coprocessor instruction. Return nonzero if
2545 instruction is not defined. */
2546 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2548 TCGv tmp;
2549 uint32_t rd = (insn >> 12) & 0xf;
2550 uint32_t cp = (insn >> 8) & 0xf;
2551 if (IS_USER(s)) {
2552 return 1;
2555 if (insn & ARM_CP_RW_BIT) {
2556 if (!env->cp[cp].cp_read)
2557 return 1;
2558 gen_set_pc_im(s->pc);
2559 tmp = new_tmp();
2560 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2561 store_reg(s, rd, tmp);
2562 } else {
2563 if (!env->cp[cp].cp_write)
2564 return 1;
2565 gen_set_pc_im(s->pc);
2566 tmp = load_reg(s, rd);
2567 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2568 dead_tmp(tmp);
2570 return 0;
2573 static int cp15_user_ok(uint32_t insn)
2575 int cpn = (insn >> 16) & 0xf;
2576 int cpm = insn & 0xf;
2577 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2579 if (cpn == 13 && cpm == 0) {
2580 /* TLS register. */
2581 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2582 return 1;
2584 if (cpn == 7) {
2585 /* ISB, DSB, DMB. */
2586 if ((cpm == 5 && op == 4)
2587 || (cpm == 10 && (op == 4 || op == 5)))
2588 return 1;
2590 return 0;
2593 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2594 instruction is not defined. */
2595 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2597 uint32_t rd;
2598 TCGv tmp;
2600 /* M profile cores use memory mapped registers instead of cp15. */
2601 if (arm_feature(env, ARM_FEATURE_M))
2602 return 1;
2604 if ((insn & (1 << 25)) == 0) {
2605 if (insn & (1 << 20)) {
2606 /* mrrc */
2607 return 1;
2609 /* mcrr. Used for block cache operations, so implement as no-op. */
2610 return 0;
2612 if ((insn & (1 << 4)) == 0) {
2613 /* cdp */
2614 return 1;
2616 if (IS_USER(s) && !cp15_user_ok(insn)) {
2617 return 1;
2619 if ((insn & 0x0fff0fff) == 0x0e070f90
2620 || (insn & 0x0fff0fff) == 0x0e070f58) {
2621 /* Wait for interrupt. */
2622 gen_set_pc_im(s->pc);
2623 s->is_jmp = DISAS_WFI;
2624 return 0;
2626 rd = (insn >> 12) & 0xf;
2627 if (insn & ARM_CP_RW_BIT) {
2628 tmp = new_tmp();
2629 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2630 /* If the destination register is r15 then sets condition codes. */
2631 if (rd != 15)
2632 store_reg(s, rd, tmp);
2633 else
2634 dead_tmp(tmp);
2635 } else {
2636 tmp = load_reg(s, rd);
2637 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2638 dead_tmp(tmp);
2639 /* Normally we would always end the TB here, but Linux
2640 * arch/arm/mach-pxa/sleep.S expects two instructions following
2641 * an MMU enable to execute from cache. Imitate this behaviour. */
2642 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2643 (insn & 0x0fff0fff) != 0x0e010f10)
2644 gen_lookup_tb(s);
2646 return 0;
2649 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2650 #define VFP_SREG(insn, bigbit, smallbit) \
2651 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2652 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2653 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2654 reg = (((insn) >> (bigbit)) & 0x0f) \
2655 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2656 } else { \
2657 if (insn & (1 << (smallbit))) \
2658 return 1; \
2659 reg = ((insn) >> (bigbit)) & 0x0f; \
2660 }} while (0)
2662 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2663 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2664 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2665 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2666 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2667 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2669 /* Move between integer and VFP cores. */
2670 static TCGv gen_vfp_mrs(void)
2672 TCGv tmp = new_tmp();
2673 tcg_gen_mov_i32(tmp, cpu_F0s);
2674 return tmp;
2677 static void gen_vfp_msr(TCGv tmp)
2679 tcg_gen_mov_i32(cpu_F0s, tmp);
2680 dead_tmp(tmp);
2683 static inline int
2684 vfp_enabled(CPUState * env)
2686 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2689 static void gen_neon_dup_u8(TCGv var, int shift)
2691 TCGv tmp = new_tmp();
2692 if (shift)
2693 tcg_gen_shri_i32(var, var, shift);
2694 tcg_gen_ext8u_i32(var, var);
2695 tcg_gen_shli_i32(tmp, var, 8);
2696 tcg_gen_or_i32(var, var, tmp);
2697 tcg_gen_shli_i32(tmp, var, 16);
2698 tcg_gen_or_i32(var, var, tmp);
2699 dead_tmp(tmp);
2702 static void gen_neon_dup_low16(TCGv var)
2704 TCGv tmp = new_tmp();
2705 tcg_gen_ext16u_i32(var, var);
2706 tcg_gen_shli_i32(tmp, var, 16);
2707 tcg_gen_or_i32(var, var, tmp);
2708 dead_tmp(tmp);
2711 static void gen_neon_dup_high16(TCGv var)
2713 TCGv tmp = new_tmp();
2714 tcg_gen_andi_i32(var, var, 0xffff0000);
2715 tcg_gen_shri_i32(tmp, var, 16);
2716 tcg_gen_or_i32(var, var, tmp);
2717 dead_tmp(tmp);
2720 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2721 (ie. an undefined instruction). */
2722 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2724 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2725 int dp, veclen;
2726 TCGv tmp;
2727 TCGv tmp2;
2729 if (!arm_feature(env, ARM_FEATURE_VFP))
2730 return 1;
2732 if (!vfp_enabled(env)) {
2733 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2734 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2735 return 1;
2736 rn = (insn >> 16) & 0xf;
2737 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2738 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2739 return 1;
2741 dp = ((insn & 0xf00) == 0xb00);
2742 switch ((insn >> 24) & 0xf) {
2743 case 0xe:
2744 if (insn & (1 << 4)) {
2745 /* single register transfer */
2746 rd = (insn >> 12) & 0xf;
2747 if (dp) {
2748 int size;
2749 int pass;
2751 VFP_DREG_N(rn, insn);
2752 if (insn & 0xf)
2753 return 1;
2754 if (insn & 0x00c00060
2755 && !arm_feature(env, ARM_FEATURE_NEON))
2756 return 1;
2758 pass = (insn >> 21) & 1;
2759 if (insn & (1 << 22)) {
2760 size = 0;
2761 offset = ((insn >> 5) & 3) * 8;
2762 } else if (insn & (1 << 5)) {
2763 size = 1;
2764 offset = (insn & (1 << 6)) ? 16 : 0;
2765 } else {
2766 size = 2;
2767 offset = 0;
2769 if (insn & ARM_CP_RW_BIT) {
2770 /* vfp->arm */
2771 tmp = neon_load_reg(rn, pass);
2772 switch (size) {
2773 case 0:
2774 if (offset)
2775 tcg_gen_shri_i32(tmp, tmp, offset);
2776 if (insn & (1 << 23))
2777 gen_uxtb(tmp);
2778 else
2779 gen_sxtb(tmp);
2780 break;
2781 case 1:
2782 if (insn & (1 << 23)) {
2783 if (offset) {
2784 tcg_gen_shri_i32(tmp, tmp, 16);
2785 } else {
2786 gen_uxth(tmp);
2788 } else {
2789 if (offset) {
2790 tcg_gen_sari_i32(tmp, tmp, 16);
2791 } else {
2792 gen_sxth(tmp);
2795 break;
2796 case 2:
2797 break;
2799 store_reg(s, rd, tmp);
2800 } else {
2801 /* arm->vfp */
2802 tmp = load_reg(s, rd);
2803 if (insn & (1 << 23)) {
2804 /* VDUP */
2805 if (size == 0) {
2806 gen_neon_dup_u8(tmp, 0);
2807 } else if (size == 1) {
2808 gen_neon_dup_low16(tmp);
2810 tmp2 = new_tmp();
2811 tcg_gen_mov_i32(tmp2, tmp);
2812 neon_store_reg(rn, 0, tmp2);
2813 neon_store_reg(rn, 0, 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 /* Source and destination the same. */
3029 gen_mov_F0_vreg(dp, rd);
3030 break;
3031 default:
3032 /* One source operand. */
3033 gen_mov_F0_vreg(dp, rm);
3034 break;
3036 } else {
3037 /* Two source operands. */
3038 gen_mov_F0_vreg(dp, rn);
3039 gen_mov_F1_vreg(dp, rm);
3042 for (;;) {
3043 /* Perform the calculation. */
3044 switch (op) {
3045 case 0: /* mac: fd + (fn * fm) */
3046 gen_vfp_mul(dp);
3047 gen_mov_F1_vreg(dp, rd);
3048 gen_vfp_add(dp);
3049 break;
3050 case 1: /* nmac: fd - (fn * fm) */
3051 gen_vfp_mul(dp);
3052 gen_vfp_neg(dp);
3053 gen_mov_F1_vreg(dp, rd);
3054 gen_vfp_add(dp);
3055 break;
3056 case 2: /* msc: -fd + (fn * fm) */
3057 gen_vfp_mul(dp);
3058 gen_mov_F1_vreg(dp, rd);
3059 gen_vfp_sub(dp);
3060 break;
3061 case 3: /* nmsc: -fd - (fn * fm) */
3062 gen_vfp_mul(dp);
3063 gen_mov_F1_vreg(dp, rd);
3064 gen_vfp_add(dp);
3065 gen_vfp_neg(dp);
3066 break;
3067 case 4: /* mul: fn * fm */
3068 gen_vfp_mul(dp);
3069 break;
3070 case 5: /* nmul: -(fn * fm) */
3071 gen_vfp_mul(dp);
3072 gen_vfp_neg(dp);
3073 break;
3074 case 6: /* add: fn + fm */
3075 gen_vfp_add(dp);
3076 break;
3077 case 7: /* sub: fn - fm */
3078 gen_vfp_sub(dp);
3079 break;
3080 case 8: /* div: fn / fm */
3081 gen_vfp_div(dp);
3082 break;
3083 case 14: /* fconst */
3084 if (!arm_feature(env, ARM_FEATURE_VFP3))
3085 return 1;
3087 n = (insn << 12) & 0x80000000;
3088 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3089 if (dp) {
3090 if (i & 0x40)
3091 i |= 0x3f80;
3092 else
3093 i |= 0x4000;
3094 n |= i << 16;
3095 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3096 } else {
3097 if (i & 0x40)
3098 i |= 0x780;
3099 else
3100 i |= 0x800;
3101 n |= i << 19;
3102 tcg_gen_movi_i32(cpu_F0s, n);
3104 break;
3105 case 15: /* extension space */
3106 switch (rn) {
3107 case 0: /* cpy */
3108 /* no-op */
3109 break;
3110 case 1: /* abs */
3111 gen_vfp_abs(dp);
3112 break;
3113 case 2: /* neg */
3114 gen_vfp_neg(dp);
3115 break;
3116 case 3: /* sqrt */
3117 gen_vfp_sqrt(dp);
3118 break;
3119 case 8: /* cmp */
3120 gen_vfp_cmp(dp);
3121 break;
3122 case 9: /* cmpe */
3123 gen_vfp_cmpe(dp);
3124 break;
3125 case 10: /* cmpz */
3126 gen_vfp_cmp(dp);
3127 break;
3128 case 11: /* cmpez */
3129 gen_vfp_F1_ld0(dp);
3130 gen_vfp_cmpe(dp);
3131 break;
3132 case 15: /* single<->double conversion */
3133 if (dp)
3134 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3135 else
3136 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3137 break;
3138 case 16: /* fuito */
3139 gen_vfp_uito(dp);
3140 break;
3141 case 17: /* fsito */
3142 gen_vfp_sito(dp);
3143 break;
3144 case 20: /* fshto */
3145 if (!arm_feature(env, ARM_FEATURE_VFP3))
3146 return 1;
3147 gen_vfp_shto(dp, rm);
3148 break;
3149 case 21: /* fslto */
3150 if (!arm_feature(env, ARM_FEATURE_VFP3))
3151 return 1;
3152 gen_vfp_slto(dp, rm);
3153 break;
3154 case 22: /* fuhto */
3155 if (!arm_feature(env, ARM_FEATURE_VFP3))
3156 return 1;
3157 gen_vfp_uhto(dp, rm);
3158 break;
3159 case 23: /* fulto */
3160 if (!arm_feature(env, ARM_FEATURE_VFP3))
3161 return 1;
3162 gen_vfp_ulto(dp, rm);
3163 break;
3164 case 24: /* ftoui */
3165 gen_vfp_toui(dp);
3166 break;
3167 case 25: /* ftouiz */
3168 gen_vfp_touiz(dp);
3169 break;
3170 case 26: /* ftosi */
3171 gen_vfp_tosi(dp);
3172 break;
3173 case 27: /* ftosiz */
3174 gen_vfp_tosiz(dp);
3175 break;
3176 case 28: /* ftosh */
3177 if (!arm_feature(env, ARM_FEATURE_VFP3))
3178 return 1;
3179 gen_vfp_tosh(dp, rm);
3180 break;
3181 case 29: /* ftosl */
3182 if (!arm_feature(env, ARM_FEATURE_VFP3))
3183 return 1;
3184 gen_vfp_tosl(dp, rm);
3185 break;
3186 case 30: /* ftouh */
3187 if (!arm_feature(env, ARM_FEATURE_VFP3))
3188 return 1;
3189 gen_vfp_touh(dp, rm);
3190 break;
3191 case 31: /* ftoul */
3192 if (!arm_feature(env, ARM_FEATURE_VFP3))
3193 return 1;
3194 gen_vfp_toul(dp, rm);
3195 break;
3196 default: /* undefined */
3197 printf ("rn:%d\n", rn);
3198 return 1;
3200 break;
3201 default: /* undefined */
3202 printf ("op:%d\n", op);
3203 return 1;
3206 /* Write back the result. */
3207 if (op == 15 && (rn >= 8 && rn <= 11))
3208 ; /* Comparison, do nothing. */
3209 else if (op == 15 && rn > 17)
3210 /* Integer result. */
3211 gen_mov_vreg_F0(0, rd);
3212 else if (op == 15 && rn == 15)
3213 /* conversion */
3214 gen_mov_vreg_F0(!dp, rd);
3215 else
3216 gen_mov_vreg_F0(dp, rd);
3218 /* break out of the loop if we have finished */
3219 if (veclen == 0)
3220 break;
3222 if (op == 15 && delta_m == 0) {
3223 /* single source one-many */
3224 while (veclen--) {
3225 rd = ((rd + delta_d) & (bank_mask - 1))
3226 | (rd & bank_mask);
3227 gen_mov_vreg_F0(dp, rd);
3229 break;
3231 /* Setup the next operands. */
3232 veclen--;
3233 rd = ((rd + delta_d) & (bank_mask - 1))
3234 | (rd & bank_mask);
3236 if (op == 15) {
3237 /* One source operand. */
3238 rm = ((rm + delta_m) & (bank_mask - 1))
3239 | (rm & bank_mask);
3240 gen_mov_F0_vreg(dp, rm);
3241 } else {
3242 /* Two source operands. */
3243 rn = ((rn + delta_d) & (bank_mask - 1))
3244 | (rn & bank_mask);
3245 gen_mov_F0_vreg(dp, rn);
3246 if (delta_m) {
3247 rm = ((rm + delta_m) & (bank_mask - 1))
3248 | (rm & bank_mask);
3249 gen_mov_F1_vreg(dp, rm);
3254 break;
3255 case 0xc:
3256 case 0xd:
3257 if (dp && (insn & 0x03e00000) == 0x00400000) {
3258 /* two-register transfer */
3259 rn = (insn >> 16) & 0xf;
3260 rd = (insn >> 12) & 0xf;
3261 if (dp) {
3262 VFP_DREG_M(rm, insn);
3263 } else {
3264 rm = VFP_SREG_M(insn);
3267 if (insn & ARM_CP_RW_BIT) {
3268 /* vfp->arm */
3269 if (dp) {
3270 gen_mov_F0_vreg(0, rm * 2);
3271 tmp = gen_vfp_mrs();
3272 store_reg(s, rd, tmp);
3273 gen_mov_F0_vreg(0, rm * 2 + 1);
3274 tmp = gen_vfp_mrs();
3275 store_reg(s, rn, tmp);
3276 } else {
3277 gen_mov_F0_vreg(0, rm);
3278 tmp = gen_vfp_mrs();
3279 store_reg(s, rn, tmp);
3280 gen_mov_F0_vreg(0, rm + 1);
3281 tmp = gen_vfp_mrs();
3282 store_reg(s, rd, tmp);
3284 } else {
3285 /* arm->vfp */
3286 if (dp) {
3287 tmp = load_reg(s, rd);
3288 gen_vfp_msr(tmp);
3289 gen_mov_vreg_F0(0, rm * 2);
3290 tmp = load_reg(s, rn);
3291 gen_vfp_msr(tmp);
3292 gen_mov_vreg_F0(0, rm * 2 + 1);
3293 } else {
3294 tmp = load_reg(s, rn);
3295 gen_vfp_msr(tmp);
3296 gen_mov_vreg_F0(0, rm);
3297 tmp = load_reg(s, rd);
3298 gen_vfp_msr(tmp);
3299 gen_mov_vreg_F0(0, rm + 1);
3302 } else {
3303 /* Load/store */
3304 rn = (insn >> 16) & 0xf;
3305 if (dp)
3306 VFP_DREG_D(rd, insn);
3307 else
3308 rd = VFP_SREG_D(insn);
3309 if (s->thumb && rn == 15) {
3310 gen_op_movl_T1_im(s->pc & ~2);
3311 } else {
3312 gen_movl_T1_reg(s, rn);
3314 if ((insn & 0x01200000) == 0x01000000) {
3315 /* Single load/store */
3316 offset = (insn & 0xff) << 2;
3317 if ((insn & (1 << 23)) == 0)
3318 offset = -offset;
3319 gen_op_addl_T1_im(offset);
3320 if (insn & (1 << 20)) {
3321 gen_vfp_ld(s, dp);
3322 gen_mov_vreg_F0(dp, rd);
3323 } else {
3324 gen_mov_F0_vreg(dp, rd);
3325 gen_vfp_st(s, dp);
3327 } else {
3328 /* load/store multiple */
3329 if (dp)
3330 n = (insn >> 1) & 0x7f;
3331 else
3332 n = insn & 0xff;
3334 if (insn & (1 << 24)) /* pre-decrement */
3335 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3337 if (dp)
3338 offset = 8;
3339 else
3340 offset = 4;
3341 for (i = 0; i < n; i++) {
3342 if (insn & ARM_CP_RW_BIT) {
3343 /* load */
3344 gen_vfp_ld(s, dp);
3345 gen_mov_vreg_F0(dp, rd + i);
3346 } else {
3347 /* store */
3348 gen_mov_F0_vreg(dp, rd + i);
3349 gen_vfp_st(s, dp);
3351 gen_op_addl_T1_im(offset);
3353 if (insn & (1 << 21)) {
3354 /* writeback */
3355 if (insn & (1 << 24))
3356 offset = -offset * n;
3357 else if (dp && (insn & 1))
3358 offset = 4;
3359 else
3360 offset = 0;
3362 if (offset != 0)
3363 gen_op_addl_T1_im(offset);
3364 gen_movl_reg_T1(s, rn);
3368 break;
3369 default:
3370 /* Should never happen. */
3371 return 1;
3373 return 0;
3376 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3378 TranslationBlock *tb;
3380 tb = s->tb;
3381 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3382 tcg_gen_goto_tb(n);
3383 gen_set_pc_im(dest);
3384 tcg_gen_exit_tb((long)tb + n);
3385 } else {
3386 gen_set_pc_im(dest);
3387 tcg_gen_exit_tb(0);
3391 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3393 if (unlikely(s->singlestep_enabled)) {
3394 /* An indirect jump so that we still trigger the debug exception. */
3395 if (s->thumb)
3396 dest |= 1;
3397 gen_bx_im(s, dest);
3398 } else {
3399 gen_goto_tb(s, 0, dest);
3400 s->is_jmp = DISAS_TB_JUMP;
3404 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3406 if (x)
3407 tcg_gen_sari_i32(t0, t0, 16);
3408 else
3409 gen_sxth(t0);
3410 if (y)
3411 tcg_gen_sari_i32(t1, t1, 16);
3412 else
3413 gen_sxth(t1);
3414 tcg_gen_mul_i32(t0, t0, t1);
3417 /* Return the mask of PSR bits set by a MSR instruction. */
3418 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3419 uint32_t mask;
3421 mask = 0;
3422 if (flags & (1 << 0))
3423 mask |= 0xff;
3424 if (flags & (1 << 1))
3425 mask |= 0xff00;
3426 if (flags & (1 << 2))
3427 mask |= 0xff0000;
3428 if (flags & (1 << 3))
3429 mask |= 0xff000000;
3431 /* Mask out undefined bits. */
3432 mask &= ~CPSR_RESERVED;
3433 if (!arm_feature(env, ARM_FEATURE_V6))
3434 mask &= ~(CPSR_E | CPSR_GE);
3435 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3436 mask &= ~CPSR_IT;
3437 /* Mask out execution state bits. */
3438 if (!spsr)
3439 mask &= ~CPSR_EXEC;
3440 /* Mask out privileged bits. */
3441 if (IS_USER(s))
3442 mask &= CPSR_USER;
3443 return mask;
3446 /* Returns nonzero if access to the PSR is not permitted. */
3447 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3449 TCGv tmp;
3450 if (spsr) {
3451 /* ??? This is also undefined in system mode. */
3452 if (IS_USER(s))
3453 return 1;
3455 tmp = load_cpu_field(spsr);
3456 tcg_gen_andi_i32(tmp, tmp, ~mask);
3457 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3458 tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3459 store_cpu_field(tmp, spsr);
3460 } else {
3461 gen_set_cpsr(cpu_T[0], mask);
3463 gen_lookup_tb(s);
3464 return 0;
3467 /* Generate an old-style exception return. */
3468 static void gen_exception_return(DisasContext *s)
3470 TCGv tmp;
3471 gen_movl_reg_T0(s, 15);
3472 tmp = load_cpu_field(spsr);
3473 gen_set_cpsr(tmp, 0xffffffff);
3474 dead_tmp(tmp);
3475 s->is_jmp = DISAS_UPDATE;
3478 /* Generate a v6 exception return. Marks both values as dead. */
3479 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3481 gen_set_cpsr(cpsr, 0xffffffff);
3482 dead_tmp(cpsr);
3483 store_reg(s, 15, pc);
3484 s->is_jmp = DISAS_UPDATE;
3487 static inline void
3488 gen_set_condexec (DisasContext *s)
3490 if (s->condexec_mask) {
3491 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3492 TCGv tmp = new_tmp();
3493 tcg_gen_movi_i32(tmp, val);
3494 store_cpu_field(tmp, condexec_bits);
3498 static void gen_nop_hint(DisasContext *s, int val)
3500 switch (val) {
3501 case 3: /* wfi */
3502 gen_set_pc_im(s->pc);
3503 s->is_jmp = DISAS_WFI;
3504 break;
3505 case 2: /* wfe */
3506 case 4: /* sev */
3507 /* TODO: Implement SEV and WFE. May help SMP performance. */
3508 default: /* nop */
3509 break;
3513 /* These macros help make the code more readable when migrating from the
3514 old dyngen helpers. They should probably be removed when
3515 T0/T1 are removed. */
3516 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3517 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3519 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3521 static inline int gen_neon_add(int size)
3523 switch (size) {
3524 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3525 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3526 case 2: gen_op_addl_T0_T1(); break;
3527 default: return 1;
3529 return 0;
3532 static inline void gen_neon_rsb(int size)
3534 switch (size) {
3535 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3536 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3537 case 2: gen_op_rsbl_T0_T1(); break;
3538 default: return;
3542 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3543 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3544 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3545 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3546 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3548 /* FIXME: This is wrong. They set the wrong overflow bit. */
3549 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3550 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3551 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3552 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3554 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3555 switch ((size << 1) | u) { \
3556 case 0: \
3557 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3558 break; \
3559 case 1: \
3560 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3561 break; \
3562 case 2: \
3563 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3564 break; \
3565 case 3: \
3566 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3567 break; \
3568 case 4: \
3569 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3570 break; \
3571 case 5: \
3572 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3573 break; \
3574 default: return 1; \
3575 }} while (0)
3577 #define GEN_NEON_INTEGER_OP(name) do { \
3578 switch ((size << 1) | u) { \
3579 case 0: \
3580 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3581 break; \
3582 case 1: \
3583 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3584 break; \
3585 case 2: \
3586 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3587 break; \
3588 case 3: \
3589 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3590 break; \
3591 case 4: \
3592 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3593 break; \
3594 case 5: \
3595 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3596 break; \
3597 default: return 1; \
3598 }} while (0)
3600 static inline void
3601 gen_neon_movl_scratch_T0(int scratch)
3603 uint32_t offset;
3605 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3606 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3609 static inline void
3610 gen_neon_movl_scratch_T1(int scratch)
3612 uint32_t offset;
3614 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3615 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3618 static inline void
3619 gen_neon_movl_T0_scratch(int scratch)
3621 uint32_t offset;
3623 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3624 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3627 static inline void
3628 gen_neon_movl_T1_scratch(int scratch)
3630 uint32_t offset;
3632 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3633 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3636 static inline void gen_neon_get_scalar(int size, int reg)
3638 if (size == 1) {
3639 NEON_GET_REG(T0, reg >> 1, reg & 1);
3640 } else {
3641 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3642 if (reg & 1)
3643 gen_neon_dup_low16(cpu_T[0]);
3644 else
3645 gen_neon_dup_high16(cpu_T[0]);
3649 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3651 int n;
3653 for (n = 0; n < q + 1; n += 2) {
3654 NEON_GET_REG(T0, reg, n);
3655 NEON_GET_REG(T0, reg, n + n);
3656 switch (size) {
3657 case 0: gen_helper_neon_unzip_u8(); break;
3658 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3659 case 2: /* no-op */; break;
3660 default: abort();
3662 gen_neon_movl_scratch_T0(tmp + n);
3663 gen_neon_movl_scratch_T1(tmp + n + 1);
3667 static struct {
3668 int nregs;
3669 int interleave;
3670 int spacing;
3671 } neon_ls_element_type[11] = {
3672 {4, 4, 1},
3673 {4, 4, 2},
3674 {4, 1, 1},
3675 {4, 2, 1},
3676 {3, 3, 1},
3677 {3, 3, 2},
3678 {3, 1, 1},
3679 {1, 1, 1},
3680 {2, 2, 1},
3681 {2, 2, 2},
3682 {2, 1, 1}
3685 /* Translate a NEON load/store element instruction. Return nonzero if the
3686 instruction is invalid. */
3687 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3689 int rd, rn, rm;
3690 int op;
3691 int nregs;
3692 int interleave;
3693 int stride;
3694 int size;
3695 int reg;
3696 int pass;
3697 int load;
3698 int shift;
3699 int n;
3700 TCGv tmp;
3701 TCGv tmp2;
3703 if (!vfp_enabled(env))
3704 return 1;
3705 VFP_DREG_D(rd, insn);
3706 rn = (insn >> 16) & 0xf;
3707 rm = insn & 0xf;
3708 load = (insn & (1 << 21)) != 0;
3709 if ((insn & (1 << 23)) == 0) {
3710 /* Load store all elements. */
3711 op = (insn >> 8) & 0xf;
3712 size = (insn >> 6) & 3;
3713 if (op > 10 || size == 3)
3714 return 1;
3715 nregs = neon_ls_element_type[op].nregs;
3716 interleave = neon_ls_element_type[op].interleave;
3717 gen_movl_T1_reg(s, rn);
3718 stride = (1 << size) * interleave;
3719 for (reg = 0; reg < nregs; reg++) {
3720 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3721 gen_movl_T1_reg(s, rn);
3722 gen_op_addl_T1_im((1 << size) * reg);
3723 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3724 gen_movl_T1_reg(s, rn);
3725 gen_op_addl_T1_im(1 << size);
3727 for (pass = 0; pass < 2; pass++) {
3728 if (size == 2) {
3729 if (load) {
3730 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3731 neon_store_reg(rd, pass, tmp);
3732 } else {
3733 tmp = neon_load_reg(rd, pass);
3734 gen_st32(tmp, cpu_T[1], IS_USER(s));
3736 gen_op_addl_T1_im(stride);
3737 } else if (size == 1) {
3738 if (load) {
3739 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3740 gen_op_addl_T1_im(stride);
3741 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3742 gen_op_addl_T1_im(stride);
3743 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3744 dead_tmp(tmp2);
3745 neon_store_reg(rd, pass, tmp);
3746 } else {
3747 tmp = neon_load_reg(rd, pass);
3748 tmp2 = new_tmp();
3749 tcg_gen_shri_i32(tmp2, tmp, 16);
3750 gen_st16(tmp, cpu_T[1], IS_USER(s));
3751 gen_op_addl_T1_im(stride);
3752 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3753 gen_op_addl_T1_im(stride);
3755 } else /* size == 0 */ {
3756 if (load) {
3757 TCGV_UNUSED(tmp2);
3758 for (n = 0; n < 4; n++) {
3759 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3760 gen_op_addl_T1_im(stride);
3761 if (n == 0) {
3762 tmp2 = tmp;
3763 } else {
3764 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3765 dead_tmp(tmp);
3768 neon_store_reg(rd, pass, tmp2);
3769 } else {
3770 tmp2 = neon_load_reg(rd, pass);
3771 for (n = 0; n < 4; n++) {
3772 tmp = new_tmp();
3773 if (n == 0) {
3774 tcg_gen_mov_i32(tmp, tmp2);
3775 } else {
3776 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3778 gen_st8(tmp, cpu_T[1], IS_USER(s));
3779 gen_op_addl_T1_im(stride);
3781 dead_tmp(tmp2);
3785 rd += neon_ls_element_type[op].spacing;
3787 stride = nregs * 8;
3788 } else {
3789 size = (insn >> 10) & 3;
3790 if (size == 3) {
3791 /* Load single element to all lanes. */
3792 if (!load)
3793 return 1;
3794 size = (insn >> 6) & 3;
3795 nregs = ((insn >> 8) & 3) + 1;
3796 stride = (insn & (1 << 5)) ? 2 : 1;
3797 gen_movl_T1_reg(s, rn);
3798 for (reg = 0; reg < nregs; reg++) {
3799 switch (size) {
3800 case 0:
3801 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3802 gen_neon_dup_u8(tmp, 0);
3803 break;
3804 case 1:
3805 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3806 gen_neon_dup_low16(tmp);
3807 break;
3808 case 2:
3809 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3810 break;
3811 case 3:
3812 return 1;
3813 default: /* Avoid compiler warnings. */
3814 abort();
3816 gen_op_addl_T1_im(1 << size);
3817 tmp2 = new_tmp();
3818 tcg_gen_mov_i32(tmp2, tmp);
3819 neon_store_reg(rd, 0, tmp2);
3820 neon_store_reg(rd, 0, tmp);
3821 rd += stride;
3823 stride = (1 << size) * nregs;
3824 } else {
3825 /* Single element. */
3826 pass = (insn >> 7) & 1;
3827 switch (size) {
3828 case 0:
3829 shift = ((insn >> 5) & 3) * 8;
3830 stride = 1;
3831 break;
3832 case 1:
3833 shift = ((insn >> 6) & 1) * 16;
3834 stride = (insn & (1 << 5)) ? 2 : 1;
3835 break;
3836 case 2:
3837 shift = 0;
3838 stride = (insn & (1 << 6)) ? 2 : 1;
3839 break;
3840 default:
3841 abort();
3843 nregs = ((insn >> 8) & 3) + 1;
3844 gen_movl_T1_reg(s, rn);
3845 for (reg = 0; reg < nregs; reg++) {
3846 if (load) {
3847 switch (size) {
3848 case 0:
3849 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3850 break;
3851 case 1:
3852 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3853 break;
3854 case 2:
3855 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3856 break;
3857 default: /* Avoid compiler warnings. */
3858 abort();
3860 if (size != 2) {
3861 tmp2 = neon_load_reg(rd, pass);
3862 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3863 dead_tmp(tmp2);
3865 neon_store_reg(rd, pass, tmp);
3866 } else { /* Store */
3867 tmp = neon_load_reg(rd, pass);
3868 if (shift)
3869 tcg_gen_shri_i32(tmp, tmp, shift);
3870 switch (size) {
3871 case 0:
3872 gen_st8(tmp, cpu_T[1], IS_USER(s));
3873 break;
3874 case 1:
3875 gen_st16(tmp, cpu_T[1], IS_USER(s));
3876 break;
3877 case 2:
3878 gen_st32(tmp, cpu_T[1], IS_USER(s));
3879 break;
3882 rd += stride;
3883 gen_op_addl_T1_im(1 << size);
3885 stride = nregs * (1 << size);
3888 if (rm != 15) {
3889 TCGv base;
3891 base = load_reg(s, rn);
3892 if (rm == 13) {
3893 tcg_gen_addi_i32(base, base, stride);
3894 } else {
3895 TCGv index;
3896 index = load_reg(s, rm);
3897 tcg_gen_add_i32(base, base, index);
3898 dead_tmp(index);
3900 store_reg(s, rn, base);
3902 return 0;
3905 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3906 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3908 tcg_gen_and_i32(t, t, c);
3909 tcg_gen_bic_i32(f, f, c);
3910 tcg_gen_or_i32(dest, t, f);
3913 static inline void gen_neon_narrow(int size, TCGv dest, TCGv src)
3915 switch (size) {
3916 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3917 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3918 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3919 default: abort();
3923 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv src)
3925 switch (size) {
3926 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3927 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3928 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3929 default: abort();
3933 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv src)
3935 switch (size) {
3936 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3937 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3938 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3939 default: abort();
3943 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3944 int q, int u)
3946 if (q) {
3947 if (u) {
3948 switch (size) {
3949 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3950 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3951 default: abort();
3953 } else {
3954 switch (size) {
3955 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3956 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3957 default: abort();
3960 } else {
3961 if (u) {
3962 switch (size) {
3963 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3964 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3965 default: abort();
3967 } else {
3968 switch (size) {
3969 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3970 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3971 default: abort();
3977 static inline void gen_neon_widen(TCGv dest, TCGv src, int size, int u)
3979 if (u) {
3980 switch (size) {
3981 case 0: gen_helper_neon_widen_u8(dest, src); break;
3982 case 1: gen_helper_neon_widen_u16(dest, src); break;
3983 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3984 default: abort();
3986 } else {
3987 switch (size) {
3988 case 0: gen_helper_neon_widen_s8(dest, src); break;
3989 case 1: gen_helper_neon_widen_s16(dest, src); break;
3990 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3991 default: abort();
3994 dead_tmp(src);
3997 static inline void gen_neon_addl(int size)
3999 switch (size) {
4000 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4001 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4002 case 2: tcg_gen_add_i64(CPU_V001); break;
4003 default: abort();
4007 static inline void gen_neon_subl(int size)
4009 switch (size) {
4010 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4011 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4012 case 2: tcg_gen_sub_i64(CPU_V001); break;
4013 default: abort();
4017 static inline void gen_neon_negl(TCGv var, int size)
4019 switch (size) {
4020 case 0: gen_helper_neon_negl_u16(var, var); break;
4021 case 1: gen_helper_neon_negl_u32(var, var); break;
4022 case 2: gen_helper_neon_negl_u64(var, var); break;
4023 default: abort();
4027 static inline void gen_neon_addl_saturate(TCGv op0, TCGv op1, int size)
4029 switch (size) {
4030 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4031 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4032 default: abort();
4036 static inline void gen_neon_mull(TCGv dest, TCGv a, TCGv b, int size, int u)
4038 TCGv tmp;
4040 switch ((size << 1) | u) {
4041 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4042 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4043 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4044 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4045 case 4:
4046 tmp = gen_muls_i64_i32(a, b);
4047 tcg_gen_mov_i64(dest, tmp);
4048 break;
4049 case 5:
4050 tmp = gen_mulu_i64_i32(a, b);
4051 tcg_gen_mov_i64(dest, tmp);
4052 break;
4053 default: abort();
4055 if (size < 2) {
4056 dead_tmp(b);
4057 dead_tmp(a);
4061 /* Translate a NEON data processing instruction. Return nonzero if the
4062 instruction is invalid.
4063 We process data in a mixture of 32-bit and 64-bit chunks.
4064 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4066 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4068 int op;
4069 int q;
4070 int rd, rn, rm;
4071 int size;
4072 int shift;
4073 int pass;
4074 int count;
4075 int pairwise;
4076 int u;
4077 int n;
4078 uint32_t imm;
4079 TCGv tmp;
4080 TCGv tmp2;
4081 TCGv tmp3;
4083 if (!vfp_enabled(env))
4084 return 1;
4085 q = (insn & (1 << 6)) != 0;
4086 u = (insn >> 24) & 1;
4087 VFP_DREG_D(rd, insn);
4088 VFP_DREG_N(rn, insn);
4089 VFP_DREG_M(rm, insn);
4090 size = (insn >> 20) & 3;
4091 if ((insn & (1 << 23)) == 0) {
4092 /* Three register same length. */
4093 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4094 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4095 || op == 10 || op == 11 || op == 16)) {
4096 /* 64-bit element instructions. */
4097 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4098 neon_load_reg64(cpu_V0, rn + pass);
4099 neon_load_reg64(cpu_V1, rm + pass);
4100 switch (op) {
4101 case 1: /* VQADD */
4102 if (u) {
4103 gen_helper_neon_add_saturate_u64(CPU_V001);
4104 } else {
4105 gen_helper_neon_add_saturate_s64(CPU_V001);
4107 break;
4108 case 5: /* VQSUB */
4109 if (u) {
4110 gen_helper_neon_sub_saturate_u64(CPU_V001);
4111 } else {
4112 gen_helper_neon_sub_saturate_s64(CPU_V001);
4114 break;
4115 case 8: /* VSHL */
4116 if (u) {
4117 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4118 } else {
4119 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4121 break;
4122 case 9: /* VQSHL */
4123 if (u) {
4124 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4125 cpu_V0, cpu_V0);
4126 } else {
4127 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4128 cpu_V1, cpu_V0);
4130 break;
4131 case 10: /* VRSHL */
4132 if (u) {
4133 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4134 } else {
4135 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4137 break;
4138 case 11: /* VQRSHL */
4139 if (u) {
4140 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4141 cpu_V1, cpu_V0);
4142 } else {
4143 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4144 cpu_V1, cpu_V0);
4146 break;
4147 case 16:
4148 if (u) {
4149 tcg_gen_sub_i64(CPU_V001);
4150 } else {
4151 tcg_gen_add_i64(CPU_V001);
4153 break;
4154 default:
4155 abort();
4157 neon_store_reg64(cpu_V0, rd + pass);
4159 return 0;
4161 switch (op) {
4162 case 8: /* VSHL */
4163 case 9: /* VQSHL */
4164 case 10: /* VRSHL */
4165 case 11: /* VQRSHL */
4167 int rtmp;
4168 /* Shift instruction operands are reversed. */
4169 rtmp = rn;
4170 rn = rm;
4171 rm = rtmp;
4172 pairwise = 0;
4174 break;
4175 case 20: /* VPMAX */
4176 case 21: /* VPMIN */
4177 case 23: /* VPADD */
4178 pairwise = 1;
4179 break;
4180 case 26: /* VPADD (float) */
4181 pairwise = (u && size < 2);
4182 break;
4183 case 30: /* VPMIN/VPMAX (float) */
4184 pairwise = u;
4185 break;
4186 default:
4187 pairwise = 0;
4188 break;
4190 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4192 if (pairwise) {
4193 /* Pairwise. */
4194 if (q)
4195 n = (pass & 1) * 2;
4196 else
4197 n = 0;
4198 if (pass < q + 1) {
4199 NEON_GET_REG(T0, rn, n);
4200 NEON_GET_REG(T1, rn, n + 1);
4201 } else {
4202 NEON_GET_REG(T0, rm, n);
4203 NEON_GET_REG(T1, rm, n + 1);
4205 } else {
4206 /* Elementwise. */
4207 NEON_GET_REG(T0, rn, pass);
4208 NEON_GET_REG(T1, rm, pass);
4210 switch (op) {
4211 case 0: /* VHADD */
4212 GEN_NEON_INTEGER_OP(hadd);
4213 break;
4214 case 1: /* VQADD */
4215 GEN_NEON_INTEGER_OP_ENV(qadd);
4216 break;
4217 case 2: /* VRHADD */
4218 GEN_NEON_INTEGER_OP(rhadd);
4219 break;
4220 case 3: /* Logic ops. */
4221 switch ((u << 2) | size) {
4222 case 0: /* VAND */
4223 gen_op_andl_T0_T1();
4224 break;
4225 case 1: /* BIC */
4226 gen_op_bicl_T0_T1();
4227 break;
4228 case 2: /* VORR */
4229 gen_op_orl_T0_T1();
4230 break;
4231 case 3: /* VORN */
4232 gen_op_notl_T1();
4233 gen_op_orl_T0_T1();
4234 break;
4235 case 4: /* VEOR */
4236 gen_op_xorl_T0_T1();
4237 break;
4238 case 5: /* VBSL */
4239 tmp = neon_load_reg(rd, pass);
4240 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4241 dead_tmp(tmp);
4242 break;
4243 case 6: /* VBIT */
4244 tmp = neon_load_reg(rd, pass);
4245 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4246 dead_tmp(tmp);
4247 break;
4248 case 7: /* VBIF */
4249 tmp = neon_load_reg(rd, pass);
4250 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4251 dead_tmp(tmp);
4252 break;
4254 break;
4255 case 4: /* VHSUB */
4256 GEN_NEON_INTEGER_OP(hsub);
4257 break;
4258 case 5: /* VQSUB */
4259 GEN_NEON_INTEGER_OP_ENV(qsub);
4260 break;
4261 case 6: /* VCGT */
4262 GEN_NEON_INTEGER_OP(cgt);
4263 break;
4264 case 7: /* VCGE */
4265 GEN_NEON_INTEGER_OP(cge);
4266 break;
4267 case 8: /* VSHL */
4268 GEN_NEON_INTEGER_OP(shl);
4269 break;
4270 case 9: /* VQSHL */
4271 GEN_NEON_INTEGER_OP_ENV(qshl);
4272 break;
4273 case 10: /* VRSHL */
4274 GEN_NEON_INTEGER_OP(rshl);
4275 break;
4276 case 11: /* VQRSHL */
4277 GEN_NEON_INTEGER_OP_ENV(qrshl);
4278 break;
4279 case 12: /* VMAX */
4280 GEN_NEON_INTEGER_OP(max);
4281 break;
4282 case 13: /* VMIN */
4283 GEN_NEON_INTEGER_OP(min);
4284 break;
4285 case 14: /* VABD */
4286 GEN_NEON_INTEGER_OP(abd);
4287 break;
4288 case 15: /* VABA */
4289 GEN_NEON_INTEGER_OP(abd);
4290 NEON_GET_REG(T1, rd, pass);
4291 gen_neon_add(size);
4292 break;
4293 case 16:
4294 if (!u) { /* VADD */
4295 if (gen_neon_add(size))
4296 return 1;
4297 } else { /* VSUB */
4298 switch (size) {
4299 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4300 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4301 case 2: gen_op_subl_T0_T1(); break;
4302 default: return 1;
4305 break;
4306 case 17:
4307 if (!u) { /* VTST */
4308 switch (size) {
4309 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4310 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4311 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4312 default: return 1;
4314 } else { /* VCEQ */
4315 switch (size) {
4316 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4317 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4318 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4319 default: return 1;
4322 break;
4323 case 18: /* Multiply. */
4324 switch (size) {
4325 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4326 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4327 case 2: gen_op_mul_T0_T1(); break;
4328 default: return 1;
4330 NEON_GET_REG(T1, rd, pass);
4331 if (u) { /* VMLS */
4332 gen_neon_rsb(size);
4333 } else { /* VMLA */
4334 gen_neon_add(size);
4336 break;
4337 case 19: /* VMUL */
4338 if (u) { /* polynomial */
4339 gen_helper_neon_mul_p8(CPU_T001);
4340 } else { /* Integer */
4341 switch (size) {
4342 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4343 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4344 case 2: gen_op_mul_T0_T1(); break;
4345 default: return 1;
4348 break;
4349 case 20: /* VPMAX */
4350 GEN_NEON_INTEGER_OP(pmax);
4351 break;
4352 case 21: /* VPMIN */
4353 GEN_NEON_INTEGER_OP(pmin);
4354 break;
4355 case 22: /* Hultiply high. */
4356 if (!u) { /* VQDMULH */
4357 switch (size) {
4358 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4359 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4360 default: return 1;
4362 } else { /* VQRDHMUL */
4363 switch (size) {
4364 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4365 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4366 default: return 1;
4369 break;
4370 case 23: /* VPADD */
4371 if (u)
4372 return 1;
4373 switch (size) {
4374 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4375 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4376 case 2: gen_op_addl_T0_T1(); break;
4377 default: return 1;
4379 break;
4380 case 26: /* Floating point arithnetic. */
4381 switch ((u << 2) | size) {
4382 case 0: /* VADD */
4383 gen_helper_neon_add_f32(CPU_T001);
4384 break;
4385 case 2: /* VSUB */
4386 gen_helper_neon_sub_f32(CPU_T001);
4387 break;
4388 case 4: /* VPADD */
4389 gen_helper_neon_add_f32(CPU_T001);
4390 break;
4391 case 6: /* VABD */
4392 gen_helper_neon_abd_f32(CPU_T001);
4393 break;
4394 default:
4395 return 1;
4397 break;
4398 case 27: /* Float multiply. */
4399 gen_helper_neon_mul_f32(CPU_T001);
4400 if (!u) {
4401 NEON_GET_REG(T1, rd, pass);
4402 if (size == 0) {
4403 gen_helper_neon_add_f32(CPU_T001);
4404 } else {
4405 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4408 break;
4409 case 28: /* Float compare. */
4410 if (!u) {
4411 gen_helper_neon_ceq_f32(CPU_T001);
4412 } else {
4413 if (size == 0)
4414 gen_helper_neon_cge_f32(CPU_T001);
4415 else
4416 gen_helper_neon_cgt_f32(CPU_T001);
4418 break;
4419 case 29: /* Float compare absolute. */
4420 if (!u)
4421 return 1;
4422 if (size == 0)
4423 gen_helper_neon_acge_f32(CPU_T001);
4424 else
4425 gen_helper_neon_acgt_f32(CPU_T001);
4426 break;
4427 case 30: /* Float min/max. */
4428 if (size == 0)
4429 gen_helper_neon_max_f32(CPU_T001);
4430 else
4431 gen_helper_neon_min_f32(CPU_T001);
4432 break;
4433 case 31:
4434 if (size == 0)
4435 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4436 else
4437 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4438 break;
4439 default:
4440 abort();
4442 /* Save the result. For elementwise operations we can put it
4443 straight into the destination register. For pairwise operations
4444 we have to be careful to avoid clobbering the source operands. */
4445 if (pairwise && rd == rm) {
4446 gen_neon_movl_scratch_T0(pass);
4447 } else {
4448 NEON_SET_REG(T0, rd, pass);
4451 } /* for pass */
4452 if (pairwise && rd == rm) {
4453 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4454 gen_neon_movl_T0_scratch(pass);
4455 NEON_SET_REG(T0, rd, pass);
4458 /* End of 3 register same size operations. */
4459 } else if (insn & (1 << 4)) {
4460 if ((insn & 0x00380080) != 0) {
4461 /* Two registers and shift. */
4462 op = (insn >> 8) & 0xf;
4463 if (insn & (1 << 7)) {
4464 /* 64-bit shift. */
4465 size = 3;
4466 } else {
4467 size = 2;
4468 while ((insn & (1 << (size + 19))) == 0)
4469 size--;
4471 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4472 /* To avoid excessive dumplication of ops we implement shift
4473 by immediate using the variable shift operations. */
4474 if (op < 8) {
4475 /* Shift by immediate:
4476 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4477 /* Right shifts are encoded as N - shift, where N is the
4478 element size in bits. */
4479 if (op <= 4)
4480 shift = shift - (1 << (size + 3));
4481 if (size == 3) {
4482 count = q + 1;
4483 } else {
4484 count = q ? 4: 2;
4486 switch (size) {
4487 case 0:
4488 imm = (uint8_t) shift;
4489 imm |= imm << 8;
4490 imm |= imm << 16;
4491 break;
4492 case 1:
4493 imm = (uint16_t) shift;
4494 imm |= imm << 16;
4495 break;
4496 case 2:
4497 case 3:
4498 imm = shift;
4499 break;
4500 default:
4501 abort();
4504 for (pass = 0; pass < count; pass++) {
4505 if (size == 3) {
4506 neon_load_reg64(cpu_V0, rm + pass);
4507 tcg_gen_movi_i64(cpu_V1, imm);
4508 switch (op) {
4509 case 0: /* VSHR */
4510 case 1: /* VSRA */
4511 if (u)
4512 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4513 else
4514 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4515 break;
4516 case 2: /* VRSHR */
4517 case 3: /* VRSRA */
4518 if (u)
4519 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4520 else
4521 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4522 break;
4523 case 4: /* VSRI */
4524 if (!u)
4525 return 1;
4526 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4527 break;
4528 case 5: /* VSHL, VSLI */
4529 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4530 break;
4531 case 6: /* VQSHL */
4532 if (u)
4533 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4534 else
4535 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4536 break;
4537 case 7: /* VQSHLU */
4538 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4539 break;
4541 if (op == 1 || op == 3) {
4542 /* Accumulate. */
4543 neon_load_reg64(cpu_V0, rd + pass);
4544 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4545 } else if (op == 4 || (op == 5 && u)) {
4546 /* Insert */
4547 cpu_abort(env, "VS[LR]I.64 not implemented");
4549 neon_store_reg64(cpu_V0, rd + pass);
4550 } else { /* size < 3 */
4551 /* Operands in T0 and T1. */
4552 gen_op_movl_T1_im(imm);
4553 NEON_GET_REG(T0, rm, pass);
4554 switch (op) {
4555 case 0: /* VSHR */
4556 case 1: /* VSRA */
4557 GEN_NEON_INTEGER_OP(shl);
4558 break;
4559 case 2: /* VRSHR */
4560 case 3: /* VRSRA */
4561 GEN_NEON_INTEGER_OP(rshl);
4562 break;
4563 case 4: /* VSRI */
4564 if (!u)
4565 return 1;
4566 GEN_NEON_INTEGER_OP(shl);
4567 break;
4568 case 5: /* VSHL, VSLI */
4569 switch (size) {
4570 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4571 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4572 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4573 default: return 1;
4575 break;
4576 case 6: /* VQSHL */
4577 GEN_NEON_INTEGER_OP_ENV(qshl);
4578 break;
4579 case 7: /* VQSHLU */
4580 switch (size) {
4581 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4582 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4583 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4584 default: return 1;
4586 break;
4589 if (op == 1 || op == 3) {
4590 /* Accumulate. */
4591 NEON_GET_REG(T1, rd, pass);
4592 gen_neon_add(size);
4593 } else if (op == 4 || (op == 5 && u)) {
4594 /* Insert */
4595 switch (size) {
4596 case 0:
4597 if (op == 4)
4598 imm = 0xff >> -shift;
4599 else
4600 imm = (uint8_t)(0xff << shift);
4601 imm |= imm << 8;
4602 imm |= imm << 16;
4603 break;
4604 case 1:
4605 if (op == 4)
4606 imm = 0xffff >> -shift;
4607 else
4608 imm = (uint16_t)(0xffff << shift);
4609 imm |= imm << 16;
4610 break;
4611 case 2:
4612 if (op == 4)
4613 imm = 0xffffffffu >> -shift;
4614 else
4615 imm = 0xffffffffu << shift;
4616 break;
4617 default:
4618 abort();
4620 tmp = neon_load_reg(rd, pass);
4621 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4622 tcg_gen_andi_i32(tmp, tmp, ~imm);
4623 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4625 NEON_SET_REG(T0, rd, pass);
4627 } /* for pass */
4628 } else if (op < 10) {
4629 /* Shift by immediate and narrow:
4630 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4631 shift = shift - (1 << (size + 3));
4632 size++;
4633 switch (size) {
4634 case 1:
4635 imm = (uint16_t)shift;
4636 imm |= imm << 16;
4637 tmp2 = tcg_const_i32(imm);
4638 break;
4639 case 2:
4640 imm = (uint32_t)shift;
4641 tmp2 = tcg_const_i32(imm);
4642 case 3:
4643 tmp2 = tcg_const_i64(shift);
4644 break;
4645 default:
4646 abort();
4649 for (pass = 0; pass < 2; pass++) {
4650 if (size == 3) {
4651 neon_load_reg64(cpu_V0, rm + pass);
4652 if (q) {
4653 if (u)
4654 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp2);
4655 else
4656 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp2);
4657 } else {
4658 if (u)
4659 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp2);
4660 else
4661 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp2);
4663 } else {
4664 tmp = neon_load_reg(rm + pass, 0);
4665 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4666 tcg_gen_extu_i32_i64(cpu_V0, tmp);
4667 dead_tmp(tmp);
4668 tmp = neon_load_reg(rm + pass, 1);
4669 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4670 tcg_gen_extu_i32_i64(cpu_V1, tmp);
4671 dead_tmp(tmp);
4672 tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
4673 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4675 tmp = new_tmp();
4676 if (op == 8 && !u) {
4677 gen_neon_narrow(size - 1, tmp, cpu_V0);
4678 } else {
4679 if (op == 8)
4680 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4681 else
4682 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4684 if (pass == 0) {
4685 tmp2 = tmp;
4686 } else {
4687 neon_store_reg(rd, 0, tmp2);
4688 neon_store_reg(rd, 1, tmp);
4690 } /* for pass */
4691 } else if (op == 10) {
4692 /* VSHLL */
4693 if (q || size == 3)
4694 return 1;
4695 tmp = neon_load_reg(rm, 0);
4696 tmp2 = neon_load_reg(rm, 1);
4697 for (pass = 0; pass < 2; pass++) {
4698 if (pass == 1)
4699 tmp = tmp2;
4701 gen_neon_widen(cpu_V0, tmp, size, u);
4703 if (shift != 0) {
4704 /* The shift is less than the width of the source
4705 type, so we can just shift the whole register. */
4706 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4707 if (size < 2 || !u) {
4708 uint64_t imm64;
4709 if (size == 0) {
4710 imm = (0xffu >> (8 - shift));
4711 imm |= imm << 16;
4712 } else {
4713 imm = 0xffff >> (16 - shift);
4715 imm64 = imm | (((uint64_t)imm) << 32);
4716 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4719 neon_store_reg64(cpu_V0, rd + pass);
4721 } else if (op == 15 || op == 16) {
4722 /* VCVT fixed-point. */
4723 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4724 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4725 if (op & 1) {
4726 if (u)
4727 gen_vfp_ulto(0, shift);
4728 else
4729 gen_vfp_slto(0, shift);
4730 } else {
4731 if (u)
4732 gen_vfp_toul(0, shift);
4733 else
4734 gen_vfp_tosl(0, shift);
4736 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4738 } else {
4739 return 1;
4741 } else { /* (insn & 0x00380080) == 0 */
4742 int invert;
4744 op = (insn >> 8) & 0xf;
4745 /* One register and immediate. */
4746 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4747 invert = (insn & (1 << 5)) != 0;
4748 switch (op) {
4749 case 0: case 1:
4750 /* no-op */
4751 break;
4752 case 2: case 3:
4753 imm <<= 8;
4754 break;
4755 case 4: case 5:
4756 imm <<= 16;
4757 break;
4758 case 6: case 7:
4759 imm <<= 24;
4760 break;
4761 case 8: case 9:
4762 imm |= imm << 16;
4763 break;
4764 case 10: case 11:
4765 imm = (imm << 8) | (imm << 24);
4766 break;
4767 case 12:
4768 imm = (imm < 8) | 0xff;
4769 break;
4770 case 13:
4771 imm = (imm << 16) | 0xffff;
4772 break;
4773 case 14:
4774 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4775 if (invert)
4776 imm = ~imm;
4777 break;
4778 case 15:
4779 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4780 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4781 break;
4783 if (invert)
4784 imm = ~imm;
4786 if (op != 14 || !invert)
4787 gen_op_movl_T1_im(imm);
4789 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4790 if (op & 1 && op < 12) {
4791 tmp = neon_load_reg(rd, pass);
4792 if (invert) {
4793 /* The immediate value has already been inverted, so
4794 BIC becomes AND. */
4795 tcg_gen_andi_i32(tmp, tmp, imm);
4796 } else {
4797 tcg_gen_ori_i32(tmp, tmp, imm);
4799 } else {
4800 /* VMOV, VMVN. */
4801 tmp = new_tmp();
4802 if (op == 14 && invert) {
4803 uint32_t val;
4804 val = 0;
4805 for (n = 0; n < 4; n++) {
4806 if (imm & (1 << (n + (pass & 1) * 4)))
4807 val |= 0xff << (n * 8);
4809 tcg_gen_movi_i32(tmp, val);
4810 } else {
4811 tcg_gen_movi_i32(tmp, imm);
4814 neon_store_reg(rd, pass, tmp);
4817 } else { /* (insn & 0x00800010 == 0x00800010) */
4818 if (size != 3) {
4819 op = (insn >> 8) & 0xf;
4820 if ((insn & (1 << 6)) == 0) {
4821 /* Three registers of different lengths. */
4822 int src1_wide;
4823 int src2_wide;
4824 int prewiden;
4825 /* prewiden, src1_wide, src2_wide */
4826 static const int neon_3reg_wide[16][3] = {
4827 {1, 0, 0}, /* VADDL */
4828 {1, 1, 0}, /* VADDW */
4829 {1, 0, 0}, /* VSUBL */
4830 {1, 1, 0}, /* VSUBW */
4831 {0, 1, 1}, /* VADDHN */
4832 {0, 0, 0}, /* VABAL */
4833 {0, 1, 1}, /* VSUBHN */
4834 {0, 0, 0}, /* VABDL */
4835 {0, 0, 0}, /* VMLAL */
4836 {0, 0, 0}, /* VQDMLAL */
4837 {0, 0, 0}, /* VMLSL */
4838 {0, 0, 0}, /* VQDMLSL */
4839 {0, 0, 0}, /* Integer VMULL */
4840 {0, 0, 0}, /* VQDMULL */
4841 {0, 0, 0} /* Polynomial VMULL */
4844 prewiden = neon_3reg_wide[op][0];
4845 src1_wide = neon_3reg_wide[op][1];
4846 src2_wide = neon_3reg_wide[op][2];
4848 if (size == 0 && (op == 9 || op == 11 || op == 13))
4849 return 1;
4851 /* Avoid overlapping operands. Wide source operands are
4852 always aligned so will never overlap with wide
4853 destinations in problematic ways. */
4854 if (rd == rm && !src2_wide) {
4855 NEON_GET_REG(T0, rm, 1);
4856 gen_neon_movl_scratch_T0(2);
4857 } else if (rd == rn && !src1_wide) {
4858 NEON_GET_REG(T0, rn, 1);
4859 gen_neon_movl_scratch_T0(2);
4861 TCGV_UNUSED(tmp3);
4862 for (pass = 0; pass < 2; pass++) {
4863 if (src1_wide) {
4864 neon_load_reg64(cpu_V0, rn + pass);
4865 TCGV_UNUSED(tmp);
4866 } else {
4867 if (pass == 1 && rd == rn) {
4868 gen_neon_movl_T0_scratch(2);
4869 tmp = new_tmp();
4870 tcg_gen_mov_i32(tmp, cpu_T[0]);
4871 } else {
4872 tmp = neon_load_reg(rn, pass);
4874 if (prewiden) {
4875 gen_neon_widen(cpu_V0, tmp, size, u);
4878 if (src2_wide) {
4879 neon_load_reg64(cpu_V1, rm + pass);
4880 TCGV_UNUSED(tmp2);
4881 } else {
4882 if (pass == 1 && rd == rm) {
4883 gen_neon_movl_T0_scratch(2);
4884 tmp2 = new_tmp();
4885 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4886 } else {
4887 tmp2 = neon_load_reg(rm, pass);
4889 if (prewiden) {
4890 gen_neon_widen(cpu_V1, tmp2, size, u);
4893 switch (op) {
4894 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4895 gen_neon_addl(size);
4896 break;
4897 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4898 gen_neon_subl(size);
4899 break;
4900 case 5: case 7: /* VABAL, VABDL */
4901 switch ((size << 1) | u) {
4902 case 0:
4903 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4904 break;
4905 case 1:
4906 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4907 break;
4908 case 2:
4909 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4910 break;
4911 case 3:
4912 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4913 break;
4914 case 4:
4915 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4916 break;
4917 case 5:
4918 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4919 break;
4920 default: abort();
4922 dead_tmp(tmp2);
4923 dead_tmp(tmp);
4924 break;
4925 case 8: case 9: case 10: case 11: case 12: case 13:
4926 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4927 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4928 break;
4929 case 14: /* Polynomial VMULL */
4930 cpu_abort(env, "Polynomial VMULL not implemented");
4932 default: /* 15 is RESERVED. */
4933 return 1;
4935 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4936 /* Accumulate. */
4937 if (op == 10 || op == 11) {
4938 gen_neon_negl(cpu_V0, size);
4941 if (op != 13) {
4942 neon_load_reg64(cpu_V1, rd + pass);
4945 switch (op) {
4946 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4947 gen_neon_addl(size);
4948 break;
4949 case 9: case 11: /* VQDMLAL, VQDMLSL */
4950 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4951 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4952 break;
4953 /* Fall through. */
4954 case 13: /* VQDMULL */
4955 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4956 break;
4957 default:
4958 abort();
4960 neon_store_reg64(cpu_V0, rd + pass);
4961 } else if (op == 4 || op == 6) {
4962 /* Narrowing operation. */
4963 tmp = new_tmp();
4964 if (u) {
4965 switch (size) {
4966 case 0:
4967 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4968 break;
4969 case 1:
4970 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4971 break;
4972 case 2:
4973 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4974 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4975 break;
4976 default: abort();
4978 } else {
4979 switch (size) {
4980 case 0:
4981 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4982 break;
4983 case 1:
4984 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4985 break;
4986 case 2:
4987 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4988 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4989 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4990 break;
4991 default: abort();
4994 if (pass == 0) {
4995 tmp3 = tmp;
4996 } else {
4997 neon_store_reg(rd, 0, tmp3);
4998 neon_store_reg(rd, 1, tmp);
5000 } else {
5001 /* Write back the result. */
5002 neon_store_reg64(cpu_V0, rd + pass);
5005 } else {
5006 /* Two registers and a scalar. */
5007 switch (op) {
5008 case 0: /* Integer VMLA scalar */
5009 case 1: /* Float VMLA scalar */
5010 case 4: /* Integer VMLS scalar */
5011 case 5: /* Floating point VMLS scalar */
5012 case 8: /* Integer VMUL scalar */
5013 case 9: /* Floating point VMUL scalar */
5014 case 12: /* VQDMULH scalar */
5015 case 13: /* VQRDMULH scalar */
5016 gen_neon_get_scalar(size, rm);
5017 gen_neon_movl_scratch_T0(0);
5018 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5019 if (pass != 0)
5020 gen_neon_movl_T0_scratch(0);
5021 NEON_GET_REG(T1, rn, pass);
5022 if (op == 12) {
5023 if (size == 1) {
5024 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5025 } else {
5026 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5028 } else if (op == 13) {
5029 if (size == 1) {
5030 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5031 } else {
5032 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5034 } else if (op & 1) {
5035 gen_helper_neon_mul_f32(CPU_T001);
5036 } else {
5037 switch (size) {
5038 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5039 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5040 case 2: gen_op_mul_T0_T1(); break;
5041 default: return 1;
5044 if (op < 8) {
5045 /* Accumulate. */
5046 NEON_GET_REG(T1, rd, pass);
5047 switch (op) {
5048 case 0:
5049 gen_neon_add(size);
5050 break;
5051 case 1:
5052 gen_helper_neon_add_f32(CPU_T001);
5053 break;
5054 case 4:
5055 gen_neon_rsb(size);
5056 break;
5057 case 5:
5058 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5059 break;
5060 default:
5061 abort();
5064 NEON_SET_REG(T0, rd, pass);
5066 break;
5067 case 2: /* VMLAL sclar */
5068 case 3: /* VQDMLAL scalar */
5069 case 6: /* VMLSL scalar */
5070 case 7: /* VQDMLSL scalar */
5071 case 10: /* VMULL scalar */
5072 case 11: /* VQDMULL scalar */
5073 if (size == 0 && (op == 3 || op == 7 || op == 11))
5074 return 1;
5076 gen_neon_get_scalar(size, rm);
5077 NEON_GET_REG(T1, rn, 1);
5079 for (pass = 0; pass < 2; pass++) {
5080 if (pass == 0) {
5081 tmp = neon_load_reg(rn, 0);
5082 } else {
5083 tmp = new_tmp();
5084 tcg_gen_mov_i32(tmp, cpu_T[1]);
5086 tmp2 = new_tmp();
5087 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5088 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5089 if (op == 6 || op == 7) {
5090 gen_neon_negl(cpu_V0, size);
5092 if (op != 11) {
5093 neon_load_reg64(cpu_V1, rd + pass);
5095 switch (op) {
5096 case 2: case 6:
5097 gen_neon_addl(size);
5098 break;
5099 case 3: case 7:
5100 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5101 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5102 break;
5103 case 10:
5104 /* no-op */
5105 break;
5106 case 11:
5107 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5108 break;
5109 default:
5110 abort();
5112 neon_store_reg64(cpu_V0, rd + pass);
5114 break;
5115 default: /* 14 and 15 are RESERVED */
5116 return 1;
5119 } else { /* size == 3 */
5120 if (!u) {
5121 /* Extract. */
5122 imm = (insn >> 8) & 0xf;
5123 count = q + 1;
5125 if (imm > 7 && !q)
5126 return 1;
5128 if (imm == 0) {
5129 neon_load_reg64(cpu_V0, rn);
5130 if (q) {
5131 neon_load_reg64(cpu_V1, rn + 1);
5133 } else if (imm == 8) {
5134 neon_load_reg64(cpu_V0, rn + 1);
5135 if (q) {
5136 neon_load_reg64(cpu_V1, rm);
5138 } else if (q) {
5139 tmp = tcg_temp_new(TCG_TYPE_I64);
5140 if (imm < 8) {
5141 neon_load_reg64(cpu_V0, rn);
5142 neon_load_reg64(tmp, rn + 1);
5143 } else {
5144 neon_load_reg64(cpu_V0, rn + 1);
5145 neon_load_reg64(tmp, rm);
5147 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5148 tcg_gen_shli_i64(cpu_V1, tmp, 64 - ((imm & 7) * 8));
5149 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5150 if (imm < 8) {
5151 neon_load_reg64(cpu_V1, rm);
5152 } else {
5153 neon_load_reg64(cpu_V1, rm + 1);
5154 imm -= 8;
5156 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5157 tcg_gen_shri_i64(tmp, tmp, imm * 8);
5158 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp);
5159 } else {
5160 neon_load_reg64(cpu_V0, rn);
5161 tcg_gen_shri_i32(cpu_V0, cpu_V0, imm * 8);
5162 neon_load_reg64(cpu_V1, rm);
5163 tcg_gen_shli_i32(cpu_V1, cpu_V1, 64 - (imm * 8));
5164 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5166 neon_store_reg64(cpu_V0, rd);
5167 if (q) {
5168 neon_store_reg64(cpu_V1, rd + 1);
5170 } else if ((insn & (1 << 11)) == 0) {
5171 /* Two register misc. */
5172 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5173 size = (insn >> 18) & 3;
5174 switch (op) {
5175 case 0: /* VREV64 */
5176 if (size == 3)
5177 return 1;
5178 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5179 NEON_GET_REG(T0, rm, pass * 2);
5180 NEON_GET_REG(T1, rm, pass * 2 + 1);
5181 switch (size) {
5182 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5183 case 1: gen_swap_half(cpu_T[0]); break;
5184 case 2: /* no-op */ break;
5185 default: abort();
5187 NEON_SET_REG(T0, rd, pass * 2 + 1);
5188 if (size == 2) {
5189 NEON_SET_REG(T1, rd, pass * 2);
5190 } else {
5191 gen_op_movl_T0_T1();
5192 switch (size) {
5193 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5194 case 1: gen_swap_half(cpu_T[0]); break;
5195 default: abort();
5197 NEON_SET_REG(T0, rd, pass * 2);
5200 break;
5201 case 4: case 5: /* VPADDL */
5202 case 12: case 13: /* VPADAL */
5203 if (size == 3)
5204 return 1;
5205 for (pass = 0; pass < q + 1; pass++) {
5206 tmp = neon_load_reg(rm, pass * 2);
5207 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5208 tmp = neon_load_reg(rm, pass * 2 + 1);
5209 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5210 switch (size) {
5211 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5212 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5213 case 2: tcg_gen_add_i64(CPU_V001); break;
5214 default: abort();
5216 if (op >= 12) {
5217 /* Accumulate. */
5218 neon_load_reg64(cpu_V1, rd + pass);
5219 gen_neon_addl(size);
5221 neon_store_reg64(cpu_V0, rd + pass);
5223 break;
5224 case 33: /* VTRN */
5225 if (size == 2) {
5226 for (n = 0; n < (q ? 4 : 2); n += 2) {
5227 NEON_GET_REG(T0, rm, n);
5228 NEON_GET_REG(T1, rd, n + 1);
5229 NEON_SET_REG(T1, rm, n);
5230 NEON_SET_REG(T0, rd, n + 1);
5232 } else {
5233 goto elementwise;
5235 break;
5236 case 34: /* VUZP */
5237 /* Reg Before After
5238 Rd A3 A2 A1 A0 B2 B0 A2 A0
5239 Rm B3 B2 B1 B0 B3 B1 A3 A1
5241 if (size == 3)
5242 return 1;
5243 gen_neon_unzip(rd, q, 0, size);
5244 gen_neon_unzip(rm, q, 4, size);
5245 if (q) {
5246 static int unzip_order_q[8] =
5247 {0, 2, 4, 6, 1, 3, 5, 7};
5248 for (n = 0; n < 8; n++) {
5249 int reg = (n < 4) ? rd : rm;
5250 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5251 NEON_SET_REG(T0, reg, n % 4);
5253 } else {
5254 static int unzip_order[4] =
5255 {0, 4, 1, 5};
5256 for (n = 0; n < 4; n++) {
5257 int reg = (n < 2) ? rd : rm;
5258 gen_neon_movl_T0_scratch(unzip_order[n]);
5259 NEON_SET_REG(T0, reg, n % 2);
5262 break;
5263 case 35: /* VZIP */
5264 /* Reg Before After
5265 Rd A3 A2 A1 A0 B1 A1 B0 A0
5266 Rm B3 B2 B1 B0 B3 A3 B2 A2
5268 if (size == 3)
5269 return 1;
5270 count = (q ? 4 : 2);
5271 for (n = 0; n < count; n++) {
5272 NEON_GET_REG(T0, rd, n);
5273 NEON_GET_REG(T1, rd, n);
5274 switch (size) {
5275 case 0: gen_helper_neon_zip_u8(); break;
5276 case 1: gen_helper_neon_zip_u16(); break;
5277 case 2: /* no-op */; break;
5278 default: abort();
5280 gen_neon_movl_scratch_T0(n * 2);
5281 gen_neon_movl_scratch_T1(n * 2 + 1);
5283 for (n = 0; n < count * 2; n++) {
5284 int reg = (n < count) ? rd : rm;
5285 gen_neon_movl_T0_scratch(n);
5286 NEON_SET_REG(T0, reg, n % count);
5288 break;
5289 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5290 if (size == 3)
5291 return 1;
5292 TCGV_UNUSED(tmp2);
5293 for (pass = 0; pass < 2; pass++) {
5294 neon_load_reg64(cpu_V0, rm + pass);
5295 tmp = new_tmp();
5296 if (op == 36 && q == 0) {
5297 gen_neon_narrow(size, tmp, cpu_V0);
5298 } else if (q) {
5299 gen_neon_narrow_satu(size, tmp, cpu_V0);
5300 } else {
5301 gen_neon_narrow_sats(size, tmp, cpu_V0);
5303 if (pass == 0) {
5304 tmp2 = tmp;
5305 } else {
5306 neon_store_reg(rd, 0, tmp2);
5307 neon_store_reg(rd, 1, tmp);
5310 break;
5311 case 38: /* VSHLL */
5312 if (q || size == 3)
5313 return 1;
5314 tmp = neon_load_reg(rm, 0);
5315 tmp2 = neon_load_reg(rm, 1);
5316 for (pass = 0; pass < 2; pass++) {
5317 if (pass == 1)
5318 tmp = tmp2;
5319 gen_neon_widen(cpu_V0, tmp, size, 1);
5320 neon_store_reg64(cpu_V0, rd + pass);
5322 break;
5323 default:
5324 elementwise:
5325 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5326 if (op == 30 || op == 31 || op >= 58) {
5327 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5328 neon_reg_offset(rm, pass));
5329 } else {
5330 NEON_GET_REG(T0, rm, pass);
5332 switch (op) {
5333 case 1: /* VREV32 */
5334 switch (size) {
5335 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5336 case 1: gen_swap_half(cpu_T[0]); break;
5337 default: return 1;
5339 break;
5340 case 2: /* VREV16 */
5341 if (size != 0)
5342 return 1;
5343 gen_rev16(cpu_T[0]);
5344 break;
5345 case 8: /* CLS */
5346 switch (size) {
5347 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5348 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5349 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5350 default: return 1;
5352 break;
5353 case 9: /* CLZ */
5354 switch (size) {
5355 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5356 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5357 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5358 default: return 1;
5360 break;
5361 case 10: /* CNT */
5362 if (size != 0)
5363 return 1;
5364 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5365 break;
5366 case 11: /* VNOT */
5367 if (size != 0)
5368 return 1;
5369 gen_op_notl_T0();
5370 break;
5371 case 14: /* VQABS */
5372 switch (size) {
5373 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5374 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5375 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5376 default: return 1;
5378 break;
5379 case 15: /* VQNEG */
5380 switch (size) {
5381 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5382 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5383 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5384 default: return 1;
5386 break;
5387 case 16: case 19: /* VCGT #0, VCLE #0 */
5388 gen_op_movl_T1_im(0);
5389 switch(size) {
5390 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5391 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5392 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5393 default: return 1;
5395 if (op == 19)
5396 gen_op_notl_T0();
5397 break;
5398 case 17: case 20: /* VCGE #0, VCLT #0 */
5399 gen_op_movl_T1_im(0);
5400 switch(size) {
5401 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5402 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5403 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5404 default: return 1;
5406 if (op == 20)
5407 gen_op_notl_T0();
5408 break;
5409 case 18: /* VCEQ #0 */
5410 gen_op_movl_T1_im(0);
5411 switch(size) {
5412 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5413 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5414 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5415 default: return 1;
5417 break;
5418 case 22: /* VABS */
5419 switch(size) {
5420 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5421 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5422 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5423 default: return 1;
5425 break;
5426 case 23: /* VNEG */
5427 gen_op_movl_T1_im(0);
5428 if (size == 3)
5429 return 1;
5430 gen_neon_rsb(size);
5431 break;
5432 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5433 gen_op_movl_T1_im(0);
5434 gen_helper_neon_cgt_f32(CPU_T001);
5435 if (op == 27)
5436 gen_op_notl_T0();
5437 break;
5438 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5439 gen_op_movl_T1_im(0);
5440 gen_helper_neon_cge_f32(CPU_T001);
5441 if (op == 28)
5442 gen_op_notl_T0();
5443 break;
5444 case 26: /* Float VCEQ #0 */
5445 gen_op_movl_T1_im(0);
5446 gen_helper_neon_ceq_f32(CPU_T001);
5447 break;
5448 case 30: /* Float VABS */
5449 gen_vfp_abs(0);
5450 break;
5451 case 31: /* Float VNEG */
5452 gen_vfp_neg(0);
5453 break;
5454 case 32: /* VSWP */
5455 NEON_GET_REG(T1, rd, pass);
5456 NEON_SET_REG(T1, rm, pass);
5457 break;
5458 case 33: /* VTRN */
5459 NEON_GET_REG(T1, rd, pass);
5460 switch (size) {
5461 case 0: gen_helper_neon_trn_u8(); break;
5462 case 1: gen_helper_neon_trn_u16(); break;
5463 case 2: abort();
5464 default: return 1;
5466 NEON_SET_REG(T1, rm, pass);
5467 break;
5468 case 56: /* Integer VRECPE */
5469 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5470 break;
5471 case 57: /* Integer VRSQRTE */
5472 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5473 break;
5474 case 58: /* Float VRECPE */
5475 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5476 break;
5477 case 59: /* Float VRSQRTE */
5478 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5479 break;
5480 case 60: /* VCVT.F32.S32 */
5481 gen_vfp_tosiz(0);
5482 break;
5483 case 61: /* VCVT.F32.U32 */
5484 gen_vfp_touiz(0);
5485 break;
5486 case 62: /* VCVT.S32.F32 */
5487 gen_vfp_sito(0);
5488 break;
5489 case 63: /* VCVT.U32.F32 */
5490 gen_vfp_uito(0);
5491 break;
5492 default:
5493 /* Reserved: 21, 29, 39-56 */
5494 return 1;
5496 if (op == 30 || op == 31 || op >= 58) {
5497 tcg_gen_st_f32(cpu_F0s, cpu_env,
5498 neon_reg_offset(rd, pass));
5499 } else {
5500 NEON_SET_REG(T0, rd, pass);
5503 break;
5505 } else if ((insn & (1 << 10)) == 0) {
5506 /* VTBL, VTBX. */
5507 n = (insn >> 5) & 0x18;
5508 if (insn & (1 << 6)) {
5509 tmp = neon_load_reg(rd, 0);
5510 } else {
5511 tmp = new_tmp();
5512 tcg_gen_movi_i32(tmp, 0);
5514 tmp2 = neon_load_reg(rm, 0);
5515 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5516 tcg_const_i32(n));
5517 if (insn & (1 << 6)) {
5518 tmp = neon_load_reg(rd, 1);
5519 } else {
5520 tmp = new_tmp();
5521 tcg_gen_movi_i32(tmp, 0);
5523 tmp3 = neon_load_reg(rm, 1);
5524 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5525 tcg_const_i32(n));
5526 neon_store_reg(rd, 0, tmp2);
5527 neon_store_reg(rd, 1, tmp2);
5528 } else if ((insn & 0x380) == 0) {
5529 /* VDUP */
5530 if (insn & (1 << 19)) {
5531 NEON_SET_REG(T0, rm, 1);
5532 } else {
5533 NEON_SET_REG(T0, rm, 0);
5535 if (insn & (1 << 16)) {
5536 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5537 } else if (insn & (1 << 17)) {
5538 if ((insn >> 18) & 1)
5539 gen_neon_dup_high16(cpu_T[0]);
5540 else
5541 gen_neon_dup_low16(cpu_T[0]);
5543 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5544 NEON_SET_REG(T0, rd, pass);
5546 } else {
5547 return 1;
5551 return 0;
5554 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5556 int cpnum;
5558 cpnum = (insn >> 8) & 0xf;
5559 if (arm_feature(env, ARM_FEATURE_XSCALE)
5560 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5561 return 1;
5563 switch (cpnum) {
5564 case 0:
5565 case 1:
5566 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5567 return disas_iwmmxt_insn(env, s, insn);
5568 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5569 return disas_dsp_insn(env, s, insn);
5571 return 1;
5572 case 10:
5573 case 11:
5574 return disas_vfp_insn (env, s, insn);
5575 case 15:
5576 return disas_cp15_insn (env, s, insn);
5577 default:
5578 /* Unknown coprocessor. See if the board has hooked it. */
5579 return disas_cp_insn (env, s, insn);
5584 /* Store a 64-bit value to a register pair. Clobbers val. */
5585 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv val)
5587 TCGv tmp;
5588 tmp = new_tmp();
5589 tcg_gen_trunc_i64_i32(tmp, val);
5590 store_reg(s, rlow, tmp);
5591 tmp = new_tmp();
5592 tcg_gen_shri_i64(val, val, 32);
5593 tcg_gen_trunc_i64_i32(tmp, val);
5594 store_reg(s, rhigh, tmp);
5597 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5598 static void gen_addq_lo(DisasContext *s, TCGv val, int rlow)
5600 TCGv tmp;
5601 TCGv tmp2;
5603 /* Load 64-bit value rd:rn. */
5604 tmp = tcg_temp_new(TCG_TYPE_I64);
5605 tmp2 = load_reg(s, rlow);
5606 tcg_gen_extu_i32_i64(tmp, tmp2);
5607 dead_tmp(tmp2);
5608 tcg_gen_add_i64(val, val, tmp);
5611 /* load and add a 64-bit value from a register pair. */
5612 static void gen_addq(DisasContext *s, TCGv val, int rlow, int rhigh)
5614 TCGv tmp;
5615 TCGv tmp2;
5617 /* Load 64-bit value rd:rn. */
5618 tmp = tcg_temp_new(TCG_TYPE_I64);
5619 tmp2 = load_reg(s, rhigh);
5620 tcg_gen_extu_i32_i64(tmp, tmp2);
5621 dead_tmp(tmp2);
5622 tcg_gen_shli_i64(tmp, tmp, 32);
5623 tcg_gen_add_i64(val, val, tmp);
5625 tmp2 = load_reg(s, rlow);
5626 tcg_gen_extu_i32_i64(tmp, tmp2);
5627 dead_tmp(tmp2);
5628 tcg_gen_add_i64(val, val, tmp);
5631 /* Set N and Z flags from a 64-bit value. */
5632 static void gen_logicq_cc(TCGv val)
5634 TCGv tmp = new_tmp();
5635 gen_helper_logicq_cc(tmp, val);
5636 gen_logic_CC(tmp);
5637 dead_tmp(tmp);
5640 static void disas_arm_insn(CPUState * env, DisasContext *s)
5642 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5643 TCGv tmp;
5644 TCGv tmp2;
5645 TCGv tmp3;
5646 TCGv addr;
5648 insn = ldl_code(s->pc);
5649 s->pc += 4;
5651 /* M variants do not implement ARM mode. */
5652 if (IS_M(env))
5653 goto illegal_op;
5654 cond = insn >> 28;
5655 if (cond == 0xf){
5656 /* Unconditional instructions. */
5657 if (((insn >> 25) & 7) == 1) {
5658 /* NEON Data processing. */
5659 if (!arm_feature(env, ARM_FEATURE_NEON))
5660 goto illegal_op;
5662 if (disas_neon_data_insn(env, s, insn))
5663 goto illegal_op;
5664 return;
5666 if ((insn & 0x0f100000) == 0x04000000) {
5667 /* NEON load/store. */
5668 if (!arm_feature(env, ARM_FEATURE_NEON))
5669 goto illegal_op;
5671 if (disas_neon_ls_insn(env, s, insn))
5672 goto illegal_op;
5673 return;
5675 if ((insn & 0x0d70f000) == 0x0550f000)
5676 return; /* PLD */
5677 else if ((insn & 0x0ffffdff) == 0x01010000) {
5678 ARCH(6);
5679 /* setend */
5680 if (insn & (1 << 9)) {
5681 /* BE8 mode not implemented. */
5682 goto illegal_op;
5684 return;
5685 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5686 switch ((insn >> 4) & 0xf) {
5687 case 1: /* clrex */
5688 ARCH(6K);
5689 gen_helper_clrex(cpu_env);
5690 return;
5691 case 4: /* dsb */
5692 case 5: /* dmb */
5693 case 6: /* isb */
5694 ARCH(7);
5695 /* We don't emulate caches so these are a no-op. */
5696 return;
5697 default:
5698 goto illegal_op;
5700 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5701 /* srs */
5702 uint32_t offset;
5703 if (IS_USER(s))
5704 goto illegal_op;
5705 ARCH(6);
5706 op1 = (insn & 0x1f);
5707 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5708 addr = load_reg(s, 13);
5709 } else {
5710 addr = new_tmp();
5711 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5713 i = (insn >> 23) & 3;
5714 switch (i) {
5715 case 0: offset = -4; break; /* DA */
5716 case 1: offset = -8; break; /* DB */
5717 case 2: offset = 0; break; /* IA */
5718 case 3: offset = 4; break; /* IB */
5719 default: abort();
5721 if (offset)
5722 tcg_gen_addi_i32(addr, addr, offset);
5723 tmp = load_reg(s, 14);
5724 gen_st32(tmp, addr, 0);
5725 tmp = new_tmp();
5726 gen_helper_cpsr_read(tmp);
5727 tcg_gen_addi_i32(addr, addr, 4);
5728 gen_st32(tmp, addr, 0);
5729 if (insn & (1 << 21)) {
5730 /* Base writeback. */
5731 switch (i) {
5732 case 0: offset = -8; break;
5733 case 1: offset = -4; break;
5734 case 2: offset = 4; break;
5735 case 3: offset = 0; break;
5736 default: abort();
5738 if (offset)
5739 tcg_gen_addi_i32(addr, tmp, offset);
5740 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5741 gen_movl_reg_T1(s, 13);
5742 } else {
5743 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5745 } else {
5746 dead_tmp(addr);
5748 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5749 /* rfe */
5750 uint32_t offset;
5751 if (IS_USER(s))
5752 goto illegal_op;
5753 ARCH(6);
5754 rn = (insn >> 16) & 0xf;
5755 addr = load_reg(s, rn);
5756 i = (insn >> 23) & 3;
5757 switch (i) {
5758 case 0: offset = -4; break; /* DA */
5759 case 1: offset = -8; break; /* DB */
5760 case 2: offset = 0; break; /* IA */
5761 case 3: offset = 4; break; /* IB */
5762 default: abort();
5764 if (offset)
5765 tcg_gen_addi_i32(addr, addr, offset);
5766 /* Load PC into tmp and CPSR into tmp2. */
5767 tmp = gen_ld32(addr, 0);
5768 tcg_gen_addi_i32(addr, addr, 4);
5769 tmp2 = gen_ld32(addr, 0);
5770 if (insn & (1 << 21)) {
5771 /* Base writeback. */
5772 switch (i) {
5773 case 0: offset = -8; break;
5774 case 1: offset = -4; break;
5775 case 2: offset = 4; break;
5776 case 3: offset = 0; break;
5777 default: abort();
5779 if (offset)
5780 tcg_gen_addi_i32(addr, addr, offset);
5781 store_reg(s, rn, addr);
5782 } else {
5783 dead_tmp(addr);
5785 gen_rfe(s, tmp, tmp2);
5786 } else if ((insn & 0x0e000000) == 0x0a000000) {
5787 /* branch link and change to thumb (blx <offset>) */
5788 int32_t offset;
5790 val = (uint32_t)s->pc;
5791 tmp = new_tmp();
5792 tcg_gen_movi_i32(tmp, val);
5793 store_reg(s, 14, tmp);
5794 /* Sign-extend the 24-bit offset */
5795 offset = (((int32_t)insn) << 8) >> 8;
5796 /* offset * 4 + bit24 * 2 + (thumb bit) */
5797 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5798 /* pipeline offset */
5799 val += 4;
5800 gen_bx_im(s, val);
5801 return;
5802 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5803 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5804 /* iWMMXt register transfer. */
5805 if (env->cp15.c15_cpar & (1 << 1))
5806 if (!disas_iwmmxt_insn(env, s, insn))
5807 return;
5809 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5810 /* Coprocessor double register transfer. */
5811 } else if ((insn & 0x0f000010) == 0x0e000010) {
5812 /* Additional coprocessor register transfer. */
5813 } else if ((insn & 0x0ff10020) == 0x01000000) {
5814 uint32_t mask;
5815 uint32_t val;
5816 /* cps (privileged) */
5817 if (IS_USER(s))
5818 return;
5819 mask = val = 0;
5820 if (insn & (1 << 19)) {
5821 if (insn & (1 << 8))
5822 mask |= CPSR_A;
5823 if (insn & (1 << 7))
5824 mask |= CPSR_I;
5825 if (insn & (1 << 6))
5826 mask |= CPSR_F;
5827 if (insn & (1 << 18))
5828 val |= mask;
5830 if (insn & (1 << 17)) {
5831 mask |= CPSR_M;
5832 val |= (insn & 0x1f);
5834 if (mask) {
5835 gen_op_movl_T0_im(val);
5836 gen_set_psr_T0(s, mask, 0);
5838 return;
5840 goto illegal_op;
5842 if (cond != 0xe) {
5843 /* if not always execute, we generate a conditional jump to
5844 next instruction */
5845 s->condlabel = gen_new_label();
5846 gen_test_cc(cond ^ 1, s->condlabel);
5847 s->condjmp = 1;
5849 if ((insn & 0x0f900000) == 0x03000000) {
5850 if ((insn & (1 << 21)) == 0) {
5851 ARCH(6T2);
5852 rd = (insn >> 12) & 0xf;
5853 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5854 if ((insn & (1 << 22)) == 0) {
5855 /* MOVW */
5856 tmp = new_tmp();
5857 tcg_gen_movi_i32(tmp, val);
5858 } else {
5859 /* MOVT */
5860 tmp = load_reg(s, rd);
5861 tcg_gen_ext16u_i32(tmp, tmp);
5862 tcg_gen_ori_i32(tmp, tmp, val << 16);
5864 store_reg(s, rd, tmp);
5865 } else {
5866 if (((insn >> 12) & 0xf) != 0xf)
5867 goto illegal_op;
5868 if (((insn >> 16) & 0xf) == 0) {
5869 gen_nop_hint(s, insn & 0xff);
5870 } else {
5871 /* CPSR = immediate */
5872 val = insn & 0xff;
5873 shift = ((insn >> 8) & 0xf) * 2;
5874 if (shift)
5875 val = (val >> shift) | (val << (32 - shift));
5876 gen_op_movl_T0_im(val);
5877 i = ((insn & (1 << 22)) != 0);
5878 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5879 goto illegal_op;
5882 } else if ((insn & 0x0f900000) == 0x01000000
5883 && (insn & 0x00000090) != 0x00000090) {
5884 /* miscellaneous instructions */
5885 op1 = (insn >> 21) & 3;
5886 sh = (insn >> 4) & 0xf;
5887 rm = insn & 0xf;
5888 switch (sh) {
5889 case 0x0: /* move program status register */
5890 if (op1 & 1) {
5891 /* PSR = reg */
5892 gen_movl_T0_reg(s, rm);
5893 i = ((op1 & 2) != 0);
5894 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5895 goto illegal_op;
5896 } else {
5897 /* reg = PSR */
5898 rd = (insn >> 12) & 0xf;
5899 if (op1 & 2) {
5900 if (IS_USER(s))
5901 goto illegal_op;
5902 tmp = load_cpu_field(spsr);
5903 } else {
5904 tmp = new_tmp();
5905 gen_helper_cpsr_read(tmp);
5907 store_reg(s, rd, tmp);
5909 break;
5910 case 0x1:
5911 if (op1 == 1) {
5912 /* branch/exchange thumb (bx). */
5913 tmp = load_reg(s, rm);
5914 gen_bx(s, tmp);
5915 } else if (op1 == 3) {
5916 /* clz */
5917 rd = (insn >> 12) & 0xf;
5918 tmp = load_reg(s, rm);
5919 gen_helper_clz(tmp, tmp);
5920 store_reg(s, rd, tmp);
5921 } else {
5922 goto illegal_op;
5924 break;
5925 case 0x2:
5926 if (op1 == 1) {
5927 ARCH(5J); /* bxj */
5928 /* Trivial implementation equivalent to bx. */
5929 tmp = load_reg(s, rm);
5930 gen_bx(s, tmp);
5931 } else {
5932 goto illegal_op;
5934 break;
5935 case 0x3:
5936 if (op1 != 1)
5937 goto illegal_op;
5939 /* branch link/exchange thumb (blx) */
5940 tmp = load_reg(s, rm);
5941 tmp2 = new_tmp();
5942 tcg_gen_movi_i32(tmp2, s->pc);
5943 store_reg(s, 14, tmp2);
5944 gen_bx(s, tmp);
5945 break;
5946 case 0x5: /* saturating add/subtract */
5947 rd = (insn >> 12) & 0xf;
5948 rn = (insn >> 16) & 0xf;
5949 tmp = load_reg(s, rn);
5950 tmp2 = load_reg(s, rn);
5951 if (op1 & 2)
5952 gen_helper_double_saturate(tmp2, tmp2);
5953 if (op1 & 1)
5954 gen_helper_sub_saturate(tmp, tmp, tmp2);
5955 else
5956 gen_helper_add_saturate(tmp, tmp, tmp2);
5957 dead_tmp(tmp2);
5958 store_reg(s, rd, tmp);
5959 break;
5960 case 7: /* bkpt */
5961 gen_set_condexec(s);
5962 gen_set_pc_im(s->pc - 4);
5963 gen_exception(EXCP_BKPT);
5964 s->is_jmp = DISAS_JUMP;
5965 break;
5966 case 0x8: /* signed multiply */
5967 case 0xa:
5968 case 0xc:
5969 case 0xe:
5970 rs = (insn >> 8) & 0xf;
5971 rn = (insn >> 12) & 0xf;
5972 rd = (insn >> 16) & 0xf;
5973 if (op1 == 1) {
5974 /* (32 * 16) >> 16 */
5975 tmp = load_reg(s, rm);
5976 tmp2 = load_reg(s, rs);
5977 if (sh & 4)
5978 tcg_gen_sari_i32(tmp2, tmp2, 16);
5979 else
5980 gen_sxth(tmp2);
5981 tmp2 = gen_muls_i64_i32(tmp, tmp2);
5982 tcg_gen_shri_i64(tmp2, tmp2, 16);
5983 tmp = new_tmp();
5984 tcg_gen_trunc_i64_i32(tmp, tmp2);
5985 if ((sh & 2) == 0) {
5986 tmp2 = load_reg(s, rn);
5987 gen_helper_add_setq(tmp, tmp, tmp2);
5988 dead_tmp(tmp2);
5990 store_reg(s, rd, tmp);
5991 } else {
5992 /* 16 * 16 */
5993 tmp = load_reg(s, rm);
5994 tmp2 = load_reg(s, rs);
5995 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
5996 dead_tmp(tmp2);
5997 if (op1 == 2) {
5998 tmp2 = tcg_temp_new(TCG_TYPE_I64);
5999 tcg_gen_ext_i32_i64(tmp2, tmp);
6000 dead_tmp(tmp);
6001 gen_addq(s, tmp2, rn, rd);
6002 gen_storeq_reg(s, rn, rd, tmp2);
6003 } else {
6004 if (op1 == 0) {
6005 tmp2 = load_reg(s, rn);
6006 gen_helper_add_setq(tmp, tmp, tmp2);
6007 dead_tmp(tmp2);
6009 store_reg(s, rd, tmp);
6012 break;
6013 default:
6014 goto illegal_op;
6016 } else if (((insn & 0x0e000000) == 0 &&
6017 (insn & 0x00000090) != 0x90) ||
6018 ((insn & 0x0e000000) == (1 << 25))) {
6019 int set_cc, logic_cc, shiftop;
6021 op1 = (insn >> 21) & 0xf;
6022 set_cc = (insn >> 20) & 1;
6023 logic_cc = table_logic_cc[op1] & set_cc;
6025 /* data processing instruction */
6026 if (insn & (1 << 25)) {
6027 /* immediate operand */
6028 val = insn & 0xff;
6029 shift = ((insn >> 8) & 0xf) * 2;
6030 if (shift)
6031 val = (val >> shift) | (val << (32 - shift));
6032 gen_op_movl_T1_im(val);
6033 if (logic_cc && shift)
6034 gen_set_CF_bit31(cpu_T[1]);
6035 } else {
6036 /* register */
6037 rm = (insn) & 0xf;
6038 gen_movl_T1_reg(s, rm);
6039 shiftop = (insn >> 5) & 3;
6040 if (!(insn & (1 << 4))) {
6041 shift = (insn >> 7) & 0x1f;
6042 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
6043 } else {
6044 rs = (insn >> 8) & 0xf;
6045 tmp = load_reg(s, rs);
6046 gen_arm_shift_reg(cpu_T[1], shiftop, tmp, logic_cc);
6049 if (op1 != 0x0f && op1 != 0x0d) {
6050 rn = (insn >> 16) & 0xf;
6051 gen_movl_T0_reg(s, rn);
6053 rd = (insn >> 12) & 0xf;
6054 switch(op1) {
6055 case 0x00:
6056 gen_op_andl_T0_T1();
6057 gen_movl_reg_T0(s, rd);
6058 if (logic_cc)
6059 gen_op_logic_T0_cc();
6060 break;
6061 case 0x01:
6062 gen_op_xorl_T0_T1();
6063 gen_movl_reg_T0(s, rd);
6064 if (logic_cc)
6065 gen_op_logic_T0_cc();
6066 break;
6067 case 0x02:
6068 if (set_cc && rd == 15) {
6069 /* SUBS r15, ... is used for exception return. */
6070 if (IS_USER(s))
6071 goto illegal_op;
6072 gen_op_subl_T0_T1_cc();
6073 gen_exception_return(s);
6074 } else {
6075 if (set_cc)
6076 gen_op_subl_T0_T1_cc();
6077 else
6078 gen_op_subl_T0_T1();
6079 gen_movl_reg_T0(s, rd);
6081 break;
6082 case 0x03:
6083 if (set_cc)
6084 gen_op_rsbl_T0_T1_cc();
6085 else
6086 gen_op_rsbl_T0_T1();
6087 gen_movl_reg_T0(s, rd);
6088 break;
6089 case 0x04:
6090 if (set_cc)
6091 gen_op_addl_T0_T1_cc();
6092 else
6093 gen_op_addl_T0_T1();
6094 gen_movl_reg_T0(s, rd);
6095 break;
6096 case 0x05:
6097 if (set_cc)
6098 gen_op_adcl_T0_T1_cc();
6099 else
6100 gen_adc_T0_T1();
6101 gen_movl_reg_T0(s, rd);
6102 break;
6103 case 0x06:
6104 if (set_cc)
6105 gen_op_sbcl_T0_T1_cc();
6106 else
6107 gen_sbc_T0_T1();
6108 gen_movl_reg_T0(s, rd);
6109 break;
6110 case 0x07:
6111 if (set_cc)
6112 gen_op_rscl_T0_T1_cc();
6113 else
6114 gen_rsc_T0_T1();
6115 gen_movl_reg_T0(s, rd);
6116 break;
6117 case 0x08:
6118 if (set_cc) {
6119 gen_op_andl_T0_T1();
6120 gen_op_logic_T0_cc();
6122 break;
6123 case 0x09:
6124 if (set_cc) {
6125 gen_op_xorl_T0_T1();
6126 gen_op_logic_T0_cc();
6128 break;
6129 case 0x0a:
6130 if (set_cc) {
6131 gen_op_subl_T0_T1_cc();
6133 break;
6134 case 0x0b:
6135 if (set_cc) {
6136 gen_op_addl_T0_T1_cc();
6138 break;
6139 case 0x0c:
6140 gen_op_orl_T0_T1();
6141 gen_movl_reg_T0(s, rd);
6142 if (logic_cc)
6143 gen_op_logic_T0_cc();
6144 break;
6145 case 0x0d:
6146 if (logic_cc && rd == 15) {
6147 /* MOVS r15, ... is used for exception return. */
6148 if (IS_USER(s))
6149 goto illegal_op;
6150 gen_op_movl_T0_T1();
6151 gen_exception_return(s);
6152 } else {
6153 gen_movl_reg_T1(s, rd);
6154 if (logic_cc)
6155 gen_op_logic_T1_cc();
6157 break;
6158 case 0x0e:
6159 gen_op_bicl_T0_T1();
6160 gen_movl_reg_T0(s, rd);
6161 if (logic_cc)
6162 gen_op_logic_T0_cc();
6163 break;
6164 default:
6165 case 0x0f:
6166 gen_op_notl_T1();
6167 gen_movl_reg_T1(s, rd);
6168 if (logic_cc)
6169 gen_op_logic_T1_cc();
6170 break;
6172 } else {
6173 /* other instructions */
6174 op1 = (insn >> 24) & 0xf;
6175 switch(op1) {
6176 case 0x0:
6177 case 0x1:
6178 /* multiplies, extra load/stores */
6179 sh = (insn >> 5) & 3;
6180 if (sh == 0) {
6181 if (op1 == 0x0) {
6182 rd = (insn >> 16) & 0xf;
6183 rn = (insn >> 12) & 0xf;
6184 rs = (insn >> 8) & 0xf;
6185 rm = (insn) & 0xf;
6186 op1 = (insn >> 20) & 0xf;
6187 switch (op1) {
6188 case 0: case 1: case 2: case 3: case 6:
6189 /* 32 bit mul */
6190 tmp = load_reg(s, rs);
6191 tmp2 = load_reg(s, rm);
6192 tcg_gen_mul_i32(tmp, tmp, tmp2);
6193 dead_tmp(tmp2);
6194 if (insn & (1 << 22)) {
6195 /* Subtract (mls) */
6196 ARCH(6T2);
6197 tmp2 = load_reg(s, rn);
6198 tcg_gen_sub_i32(tmp, tmp2, tmp);
6199 dead_tmp(tmp2);
6200 } else if (insn & (1 << 21)) {
6201 /* Add */
6202 tmp2 = load_reg(s, rn);
6203 tcg_gen_add_i32(tmp, tmp, tmp2);
6204 dead_tmp(tmp2);
6206 if (insn & (1 << 20))
6207 gen_logic_CC(tmp);
6208 store_reg(s, rd, tmp);
6209 break;
6210 default:
6211 /* 64 bit mul */
6212 tmp = load_reg(s, rs);
6213 tmp2 = load_reg(s, rm);
6214 if (insn & (1 << 22))
6215 tmp = gen_muls_i64_i32(tmp, tmp2);
6216 else
6217 tmp = gen_mulu_i64_i32(tmp, tmp2);
6218 if (insn & (1 << 21)) /* mult accumulate */
6219 gen_addq(s, tmp, rn, rd);
6220 if (!(insn & (1 << 23))) { /* double accumulate */
6221 ARCH(6);
6222 gen_addq_lo(s, tmp, rn);
6223 gen_addq_lo(s, tmp, rd);
6225 if (insn & (1 << 20))
6226 gen_logicq_cc(tmp);
6227 gen_storeq_reg(s, rn, rd, tmp);
6228 break;
6230 } else {
6231 rn = (insn >> 16) & 0xf;
6232 rd = (insn >> 12) & 0xf;
6233 if (insn & (1 << 23)) {
6234 /* load/store exclusive */
6235 gen_movl_T1_reg(s, rn);
6236 addr = cpu_T[1];
6237 if (insn & (1 << 20)) {
6238 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6239 tmp = gen_ld32(addr, IS_USER(s));
6240 store_reg(s, rd, tmp);
6241 } else {
6242 int label = gen_new_label();
6243 rm = insn & 0xf;
6244 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6245 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6246 0, label);
6247 tmp = load_reg(s,rm);
6248 gen_st32(tmp, cpu_T[1], IS_USER(s));
6249 gen_set_label(label);
6250 gen_movl_reg_T0(s, rd);
6252 } else {
6253 /* SWP instruction */
6254 rm = (insn) & 0xf;
6256 /* ??? This is not really atomic. However we know
6257 we never have multiple CPUs running in parallel,
6258 so it is good enough. */
6259 addr = load_reg(s, rn);
6260 tmp = load_reg(s, rm);
6261 if (insn & (1 << 22)) {
6262 tmp2 = gen_ld8u(addr, IS_USER(s));
6263 gen_st8(tmp, addr, IS_USER(s));
6264 } else {
6265 tmp2 = gen_ld32(addr, IS_USER(s));
6266 gen_st32(tmp, addr, IS_USER(s));
6268 dead_tmp(addr);
6269 store_reg(s, rd, tmp2);
6272 } else {
6273 int address_offset;
6274 int load;
6275 /* Misc load/store */
6276 rn = (insn >> 16) & 0xf;
6277 rd = (insn >> 12) & 0xf;
6278 addr = load_reg(s, rn);
6279 if (insn & (1 << 24))
6280 gen_add_datah_offset(s, insn, 0, addr);
6281 address_offset = 0;
6282 if (insn & (1 << 20)) {
6283 /* load */
6284 switch(sh) {
6285 case 1:
6286 tmp = gen_ld16u(addr, IS_USER(s));
6287 break;
6288 case 2:
6289 tmp = gen_ld8s(addr, IS_USER(s));
6290 break;
6291 default:
6292 case 3:
6293 tmp = gen_ld16s(addr, IS_USER(s));
6294 break;
6296 load = 1;
6297 } else if (sh & 2) {
6298 /* doubleword */
6299 if (sh & 1) {
6300 /* store */
6301 tmp = load_reg(s, rd);
6302 gen_st32(tmp, addr, IS_USER(s));
6303 tcg_gen_addi_i32(addr, addr, 4);
6304 tmp = load_reg(s, rd + 1);
6305 gen_st32(tmp, addr, IS_USER(s));
6306 load = 0;
6307 } else {
6308 /* load */
6309 tmp = gen_ld32(addr, IS_USER(s));
6310 store_reg(s, rd, tmp);
6311 tcg_gen_addi_i32(addr, addr, 4);
6312 tmp = gen_ld32(addr, IS_USER(s));
6313 rd++;
6314 load = 1;
6316 address_offset = -4;
6317 } else {
6318 /* store */
6319 tmp = load_reg(s, rd);
6320 gen_st16(tmp, addr, IS_USER(s));
6321 load = 0;
6323 /* Perform base writeback before the loaded value to
6324 ensure correct behavior with overlapping index registers.
6325 ldrd with base writeback is is undefined if the
6326 destination and index registers overlap. */
6327 if (!(insn & (1 << 24))) {
6328 gen_add_datah_offset(s, insn, address_offset, addr);
6329 store_reg(s, rn, addr);
6330 } else if (insn & (1 << 21)) {
6331 if (address_offset)
6332 tcg_gen_addi_i32(addr, addr, address_offset);
6333 store_reg(s, rn, addr);
6334 } else {
6335 dead_tmp(addr);
6337 if (load) {
6338 /* Complete the load. */
6339 store_reg(s, rd, tmp);
6342 break;
6343 case 0x4:
6344 case 0x5:
6345 goto do_ldst;
6346 case 0x6:
6347 case 0x7:
6348 if (insn & (1 << 4)) {
6349 ARCH(6);
6350 /* Armv6 Media instructions. */
6351 rm = insn & 0xf;
6352 rn = (insn >> 16) & 0xf;
6353 rd = (insn >> 12) & 0xf;
6354 rs = (insn >> 8) & 0xf;
6355 switch ((insn >> 23) & 3) {
6356 case 0: /* Parallel add/subtract. */
6357 op1 = (insn >> 20) & 7;
6358 tmp = load_reg(s, rn);
6359 tmp2 = load_reg(s, rm);
6360 sh = (insn >> 5) & 7;
6361 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6362 goto illegal_op;
6363 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6364 dead_tmp(tmp2);
6365 store_reg(s, rd, tmp);
6366 break;
6367 case 1:
6368 if ((insn & 0x00700020) == 0) {
6369 /* Halfword pack. */
6370 tmp = load_reg(s, rn);
6371 tmp2 = load_reg(s, rm);
6372 shift = (insn >> 7) & 0x1f;
6373 if (insn & (1 << 6)) {
6374 /* pkhtb */
6375 if (shift == 0)
6376 shift = 31;
6377 tcg_gen_sari_i32(tmp2, tmp2, shift);
6378 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6379 tcg_gen_ext16u_i32(tmp2, tmp2);
6380 } else {
6381 /* pkhbt */
6382 if (shift)
6383 tcg_gen_shli_i32(tmp2, tmp2, shift);
6384 tcg_gen_ext16u_i32(tmp, tmp);
6385 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6387 tcg_gen_or_i32(tmp, tmp, tmp2);
6388 dead_tmp(tmp2);
6389 store_reg(s, rd, tmp);
6390 } else if ((insn & 0x00200020) == 0x00200000) {
6391 /* [us]sat */
6392 tmp = load_reg(s, rm);
6393 shift = (insn >> 7) & 0x1f;
6394 if (insn & (1 << 6)) {
6395 if (shift == 0)
6396 shift = 31;
6397 tcg_gen_sari_i32(tmp, tmp, shift);
6398 } else {
6399 tcg_gen_shli_i32(tmp, tmp, shift);
6401 sh = (insn >> 16) & 0x1f;
6402 if (sh != 0) {
6403 if (insn & (1 << 22))
6404 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6405 else
6406 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6408 store_reg(s, rd, tmp);
6409 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6410 /* [us]sat16 */
6411 tmp = load_reg(s, rm);
6412 sh = (insn >> 16) & 0x1f;
6413 if (sh != 0) {
6414 if (insn & (1 << 22))
6415 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6416 else
6417 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6419 store_reg(s, rd, tmp);
6420 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6421 /* Select bytes. */
6422 tmp = load_reg(s, rn);
6423 tmp2 = load_reg(s, rm);
6424 tmp3 = new_tmp();
6425 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6426 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6427 dead_tmp(tmp3);
6428 dead_tmp(tmp2);
6429 store_reg(s, rd, tmp);
6430 } else if ((insn & 0x000003e0) == 0x00000060) {
6431 tmp = load_reg(s, rm);
6432 shift = (insn >> 10) & 3;
6433 /* ??? In many cases it's not neccessary to do a
6434 rotate, a shift is sufficient. */
6435 if (shift != 0)
6436 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6437 op1 = (insn >> 20) & 7;
6438 switch (op1) {
6439 case 0: gen_sxtb16(tmp); break;
6440 case 2: gen_sxtb(tmp); break;
6441 case 3: gen_sxth(tmp); break;
6442 case 4: gen_uxtb16(tmp); break;
6443 case 6: gen_uxtb(tmp); break;
6444 case 7: gen_uxth(tmp); break;
6445 default: goto illegal_op;
6447 if (rn != 15) {
6448 tmp2 = load_reg(s, rn);
6449 if ((op1 & 3) == 0) {
6450 gen_add16(tmp, tmp2);
6451 } else {
6452 tcg_gen_add_i32(tmp, tmp, tmp2);
6453 dead_tmp(tmp2);
6456 store_reg(s, rd, tmp);
6457 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6458 /* rev */
6459 tmp = load_reg(s, rm);
6460 if (insn & (1 << 22)) {
6461 if (insn & (1 << 7)) {
6462 gen_revsh(tmp);
6463 } else {
6464 ARCH(6T2);
6465 gen_helper_rbit(tmp, tmp);
6467 } else {
6468 if (insn & (1 << 7))
6469 gen_rev16(tmp);
6470 else
6471 tcg_gen_bswap_i32(tmp, tmp);
6473 store_reg(s, rd, tmp);
6474 } else {
6475 goto illegal_op;
6477 break;
6478 case 2: /* Multiplies (Type 3). */
6479 tmp = load_reg(s, rm);
6480 tmp2 = load_reg(s, rs);
6481 if (insn & (1 << 20)) {
6482 /* Signed multiply most significant [accumulate]. */
6483 tmp2 = gen_muls_i64_i32(tmp, tmp2);
6484 if (insn & (1 << 5))
6485 tcg_gen_addi_i64(tmp2, tmp2, 0x80000000u);
6486 tcg_gen_shri_i64(tmp2, tmp2, 32);
6487 tmp = new_tmp();
6488 tcg_gen_trunc_i64_i32(tmp, tmp2);
6489 if (rn != 15) {
6490 tmp2 = load_reg(s, rn);
6491 if (insn & (1 << 6)) {
6492 tcg_gen_sub_i32(tmp, tmp, tmp2);
6493 } else {
6494 tcg_gen_add_i32(tmp, tmp, tmp2);
6496 dead_tmp(tmp2);
6498 store_reg(s, rd, tmp);
6499 } else {
6500 if (insn & (1 << 5))
6501 gen_swap_half(tmp2);
6502 gen_smul_dual(tmp, tmp2);
6503 /* This addition cannot overflow. */
6504 if (insn & (1 << 6)) {
6505 tcg_gen_sub_i32(tmp, tmp, tmp2);
6506 } else {
6507 tcg_gen_add_i32(tmp, tmp, tmp2);
6509 dead_tmp(tmp2);
6510 if (insn & (1 << 22)) {
6511 /* smlald, smlsld */
6512 tmp2 = tcg_temp_new(TCG_TYPE_I64);
6513 tcg_gen_ext_i32_i64(tmp2, tmp);
6514 dead_tmp(tmp);
6515 gen_addq(s, tmp2, rd, rn);
6516 gen_storeq_reg(s, rd, rn, tmp2);
6517 } else {
6518 /* smuad, smusd, smlad, smlsd */
6519 if (rd != 15)
6521 tmp2 = load_reg(s, rd);
6522 gen_helper_add_setq(tmp, tmp, tmp2);
6523 dead_tmp(tmp2);
6525 store_reg(s, rn, tmp);
6528 break;
6529 case 3:
6530 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6531 switch (op1) {
6532 case 0: /* Unsigned sum of absolute differences. */
6533 ARCH(6);
6534 tmp = load_reg(s, rm);
6535 tmp2 = load_reg(s, rs);
6536 gen_helper_usad8(tmp, tmp, tmp2);
6537 dead_tmp(tmp2);
6538 if (rn != 15) {
6539 tmp2 = load_reg(s, rn);
6540 tcg_gen_add_i32(tmp, tmp, tmp2);
6541 dead_tmp(tmp2);
6543 store_reg(s, rd, tmp);
6544 break;
6545 case 0x20: case 0x24: case 0x28: case 0x2c:
6546 /* Bitfield insert/clear. */
6547 ARCH(6T2);
6548 shift = (insn >> 7) & 0x1f;
6549 i = (insn >> 16) & 0x1f;
6550 i = i + 1 - shift;
6551 if (rm == 15) {
6552 tmp = new_tmp();
6553 tcg_gen_movi_i32(tmp, 0);
6554 } else {
6555 tmp = load_reg(s, rm);
6557 if (i != 32) {
6558 tmp2 = load_reg(s, rd);
6559 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6560 dead_tmp(tmp2);
6562 store_reg(s, rd, tmp);
6563 break;
6564 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6565 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6566 tmp = load_reg(s, rm);
6567 shift = (insn >> 7) & 0x1f;
6568 i = ((insn >> 16) & 0x1f) + 1;
6569 if (shift + i > 32)
6570 goto illegal_op;
6571 if (i < 32) {
6572 if (op1 & 0x20) {
6573 gen_ubfx(tmp, shift, (1u << i) - 1);
6574 } else {
6575 gen_sbfx(tmp, shift, i);
6578 store_reg(s, rd, tmp);
6579 break;
6580 default:
6581 goto illegal_op;
6583 break;
6585 break;
6587 do_ldst:
6588 /* Check for undefined extension instructions
6589 * per the ARM Bible IE:
6590 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6592 sh = (0xf << 20) | (0xf << 4);
6593 if (op1 == 0x7 && ((insn & sh) == sh))
6595 goto illegal_op;
6597 /* load/store byte/word */
6598 rn = (insn >> 16) & 0xf;
6599 rd = (insn >> 12) & 0xf;
6600 tmp2 = load_reg(s, rn);
6601 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6602 if (insn & (1 << 24))
6603 gen_add_data_offset(s, insn, tmp2);
6604 if (insn & (1 << 20)) {
6605 /* load */
6606 s->is_mem = 1;
6607 if (insn & (1 << 22)) {
6608 tmp = gen_ld8u(tmp2, i);
6609 } else {
6610 tmp = gen_ld32(tmp2, i);
6612 } else {
6613 /* store */
6614 tmp = load_reg(s, rd);
6615 if (insn & (1 << 22))
6616 gen_st8(tmp, tmp2, i);
6617 else
6618 gen_st32(tmp, tmp2, i);
6620 if (!(insn & (1 << 24))) {
6621 gen_add_data_offset(s, insn, tmp2);
6622 store_reg(s, rn, tmp2);
6623 } else if (insn & (1 << 21)) {
6624 store_reg(s, rn, tmp2);
6625 } else {
6626 dead_tmp(tmp2);
6628 if (insn & (1 << 20)) {
6629 /* Complete the load. */
6630 if (rd == 15)
6631 gen_bx(s, tmp);
6632 else
6633 store_reg(s, rd, tmp);
6635 break;
6636 case 0x08:
6637 case 0x09:
6639 int j, n, user, loaded_base;
6640 TCGv loaded_var;
6641 /* load/store multiple words */
6642 /* XXX: store correct base if write back */
6643 user = 0;
6644 if (insn & (1 << 22)) {
6645 if (IS_USER(s))
6646 goto illegal_op; /* only usable in supervisor mode */
6648 if ((insn & (1 << 15)) == 0)
6649 user = 1;
6651 rn = (insn >> 16) & 0xf;
6652 addr = load_reg(s, rn);
6654 /* compute total size */
6655 loaded_base = 0;
6656 TCGV_UNUSED(loaded_var);
6657 n = 0;
6658 for(i=0;i<16;i++) {
6659 if (insn & (1 << i))
6660 n++;
6662 /* XXX: test invalid n == 0 case ? */
6663 if (insn & (1 << 23)) {
6664 if (insn & (1 << 24)) {
6665 /* pre increment */
6666 tcg_gen_addi_i32(addr, addr, 4);
6667 } else {
6668 /* post increment */
6670 } else {
6671 if (insn & (1 << 24)) {
6672 /* pre decrement */
6673 tcg_gen_addi_i32(addr, addr, -(n * 4));
6674 } else {
6675 /* post decrement */
6676 if (n != 1)
6677 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6680 j = 0;
6681 for(i=0;i<16;i++) {
6682 if (insn & (1 << i)) {
6683 if (insn & (1 << 20)) {
6684 /* load */
6685 tmp = gen_ld32(addr, IS_USER(s));
6686 if (i == 15) {
6687 gen_bx(s, tmp);
6688 } else if (user) {
6689 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6690 dead_tmp(tmp);
6691 } else if (i == rn) {
6692 loaded_var = tmp;
6693 loaded_base = 1;
6694 } else {
6695 store_reg(s, i, tmp);
6697 } else {
6698 /* store */
6699 if (i == 15) {
6700 /* special case: r15 = PC + 8 */
6701 val = (long)s->pc + 4;
6702 tmp = new_tmp();
6703 tcg_gen_movi_i32(tmp, val);
6704 } else if (user) {
6705 tmp = new_tmp();
6706 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6707 } else {
6708 tmp = load_reg(s, i);
6710 gen_st32(tmp, addr, IS_USER(s));
6712 j++;
6713 /* no need to add after the last transfer */
6714 if (j != n)
6715 tcg_gen_addi_i32(addr, addr, 4);
6718 if (insn & (1 << 21)) {
6719 /* write back */
6720 if (insn & (1 << 23)) {
6721 if (insn & (1 << 24)) {
6722 /* pre increment */
6723 } else {
6724 /* post increment */
6725 tcg_gen_addi_i32(addr, addr, 4);
6727 } else {
6728 if (insn & (1 << 24)) {
6729 /* pre decrement */
6730 if (n != 1)
6731 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6732 } else {
6733 /* post decrement */
6734 tcg_gen_addi_i32(addr, addr, -(n * 4));
6737 store_reg(s, rn, addr);
6738 } else {
6739 dead_tmp(addr);
6741 if (loaded_base) {
6742 store_reg(s, rn, loaded_var);
6744 if ((insn & (1 << 22)) && !user) {
6745 /* Restore CPSR from SPSR. */
6746 tmp = load_cpu_field(spsr);
6747 gen_set_cpsr(tmp, 0xffffffff);
6748 dead_tmp(tmp);
6749 s->is_jmp = DISAS_UPDATE;
6752 break;
6753 case 0xa:
6754 case 0xb:
6756 int32_t offset;
6758 /* branch (and link) */
6759 val = (int32_t)s->pc;
6760 if (insn & (1 << 24)) {
6761 tmp = new_tmp();
6762 tcg_gen_movi_i32(tmp, val);
6763 store_reg(s, 14, tmp);
6765 offset = (((int32_t)insn << 8) >> 8);
6766 val += (offset << 2) + 4;
6767 gen_jmp(s, val);
6769 break;
6770 case 0xc:
6771 case 0xd:
6772 case 0xe:
6773 /* Coprocessor. */
6774 if (disas_coproc_insn(env, s, insn))
6775 goto illegal_op;
6776 break;
6777 case 0xf:
6778 /* swi */
6779 gen_set_pc_im(s->pc);
6780 s->is_jmp = DISAS_SWI;
6781 break;
6782 default:
6783 illegal_op:
6784 gen_set_condexec(s);
6785 gen_set_pc_im(s->pc - 4);
6786 gen_exception(EXCP_UDEF);
6787 s->is_jmp = DISAS_JUMP;
6788 break;
6793 /* Return true if this is a Thumb-2 logical op. */
6794 static int
6795 thumb2_logic_op(int op)
6797 return (op < 8);
6800 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6801 then set condition code flags based on the result of the operation.
6802 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6803 to the high bit of T1.
6804 Returns zero if the opcode is valid. */
6806 static int
6807 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6809 int logic_cc;
6811 logic_cc = 0;
6812 switch (op) {
6813 case 0: /* and */
6814 gen_op_andl_T0_T1();
6815 logic_cc = conds;
6816 break;
6817 case 1: /* bic */
6818 gen_op_bicl_T0_T1();
6819 logic_cc = conds;
6820 break;
6821 case 2: /* orr */
6822 gen_op_orl_T0_T1();
6823 logic_cc = conds;
6824 break;
6825 case 3: /* orn */
6826 gen_op_notl_T1();
6827 gen_op_orl_T0_T1();
6828 logic_cc = conds;
6829 break;
6830 case 4: /* eor */
6831 gen_op_xorl_T0_T1();
6832 logic_cc = conds;
6833 break;
6834 case 8: /* add */
6835 if (conds)
6836 gen_op_addl_T0_T1_cc();
6837 else
6838 gen_op_addl_T0_T1();
6839 break;
6840 case 10: /* adc */
6841 if (conds)
6842 gen_op_adcl_T0_T1_cc();
6843 else
6844 gen_adc_T0_T1();
6845 break;
6846 case 11: /* sbc */
6847 if (conds)
6848 gen_op_sbcl_T0_T1_cc();
6849 else
6850 gen_sbc_T0_T1();
6851 break;
6852 case 13: /* sub */
6853 if (conds)
6854 gen_op_subl_T0_T1_cc();
6855 else
6856 gen_op_subl_T0_T1();
6857 break;
6858 case 14: /* rsb */
6859 if (conds)
6860 gen_op_rsbl_T0_T1_cc();
6861 else
6862 gen_op_rsbl_T0_T1();
6863 break;
6864 default: /* 5, 6, 7, 9, 12, 15. */
6865 return 1;
6867 if (logic_cc) {
6868 gen_op_logic_T0_cc();
6869 if (shifter_out)
6870 gen_set_CF_bit31(cpu_T[1]);
6872 return 0;
6875 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6876 is not legal. */
6877 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6879 uint32_t insn, imm, shift, offset;
6880 uint32_t rd, rn, rm, rs;
6881 TCGv tmp;
6882 TCGv tmp2;
6883 TCGv tmp3;
6884 TCGv addr;
6885 int op;
6886 int shiftop;
6887 int conds;
6888 int logic_cc;
6890 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
6891 || arm_feature (env, ARM_FEATURE_M))) {
6892 /* Thumb-1 cores may need to treat bl and blx as a pair of
6893 16-bit instructions to get correct prefetch abort behavior. */
6894 insn = insn_hw1;
6895 if ((insn & (1 << 12)) == 0) {
6896 /* Second half of blx. */
6897 offset = ((insn & 0x7ff) << 1);
6898 tmp = load_reg(s, 14);
6899 tcg_gen_addi_i32(tmp, tmp, offset);
6900 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
6902 tmp2 = new_tmp();
6903 tcg_gen_movi_i32(tmp2, s->pc | 1);
6904 store_reg(s, 14, tmp2);
6905 gen_bx(s, tmp);
6906 return 0;
6908 if (insn & (1 << 11)) {
6909 /* Second half of bl. */
6910 offset = ((insn & 0x7ff) << 1) | 1;
6911 tmp = load_reg(s, 14);
6912 tcg_gen_addi_i32(tmp, tmp, offset);
6914 tmp2 = new_tmp();
6915 tcg_gen_movi_i32(tmp2, s->pc | 1);
6916 store_reg(s, 14, tmp2);
6917 gen_bx(s, tmp);
6918 return 0;
6920 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6921 /* Instruction spans a page boundary. Implement it as two
6922 16-bit instructions in case the second half causes an
6923 prefetch abort. */
6924 offset = ((int32_t)insn << 21) >> 9;
6925 gen_op_movl_T0_im(s->pc + 2 + offset);
6926 gen_movl_reg_T0(s, 14);
6927 return 0;
6929 /* Fall through to 32-bit decode. */
6932 insn = lduw_code(s->pc);
6933 s->pc += 2;
6934 insn |= (uint32_t)insn_hw1 << 16;
6936 if ((insn & 0xf800e800) != 0xf000e800) {
6937 ARCH(6T2);
6940 rn = (insn >> 16) & 0xf;
6941 rs = (insn >> 12) & 0xf;
6942 rd = (insn >> 8) & 0xf;
6943 rm = insn & 0xf;
6944 switch ((insn >> 25) & 0xf) {
6945 case 0: case 1: case 2: case 3:
6946 /* 16-bit instructions. Should never happen. */
6947 abort();
6948 case 4:
6949 if (insn & (1 << 22)) {
6950 /* Other load/store, table branch. */
6951 if (insn & 0x01200000) {
6952 /* Load/store doubleword. */
6953 if (rn == 15) {
6954 addr = new_tmp();
6955 tcg_gen_movi_i32(addr, s->pc & ~3);
6956 } else {
6957 addr = load_reg(s, rn);
6959 offset = (insn & 0xff) * 4;
6960 if ((insn & (1 << 23)) == 0)
6961 offset = -offset;
6962 if (insn & (1 << 24)) {
6963 tcg_gen_addi_i32(addr, addr, offset);
6964 offset = 0;
6966 if (insn & (1 << 20)) {
6967 /* ldrd */
6968 tmp = gen_ld32(addr, IS_USER(s));
6969 store_reg(s, rs, tmp);
6970 tcg_gen_addi_i32(addr, addr, 4);
6971 tmp = gen_ld32(addr, IS_USER(s));
6972 store_reg(s, rd, tmp);
6973 } else {
6974 /* strd */
6975 tmp = load_reg(s, rs);
6976 gen_st32(tmp, addr, IS_USER(s));
6977 tcg_gen_addi_i32(addr, addr, 4);
6978 tmp = load_reg(s, rd);
6979 gen_st32(tmp, addr, IS_USER(s));
6981 if (insn & (1 << 21)) {
6982 /* Base writeback. */
6983 if (rn == 15)
6984 goto illegal_op;
6985 tcg_gen_addi_i32(addr, addr, offset - 4);
6986 store_reg(s, rn, addr);
6987 } else {
6988 dead_tmp(addr);
6990 } else if ((insn & (1 << 23)) == 0) {
6991 /* Load/store exclusive word. */
6992 gen_movl_T1_reg(s, rn);
6993 addr = cpu_T[1];
6994 if (insn & (1 << 20)) {
6995 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6996 tmp = gen_ld32(addr, IS_USER(s));
6997 store_reg(s, rd, tmp);
6998 } else {
6999 int label = gen_new_label();
7000 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7001 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7002 0, label);
7003 tmp = load_reg(s, rs);
7004 gen_st32(tmp, cpu_T[1], IS_USER(s));
7005 gen_set_label(label);
7006 gen_movl_reg_T0(s, rd);
7008 } else if ((insn & (1 << 6)) == 0) {
7009 /* Table Branch. */
7010 if (rn == 15) {
7011 addr = new_tmp();
7012 tcg_gen_movi_i32(addr, s->pc);
7013 } else {
7014 addr = load_reg(s, rn);
7016 tmp = load_reg(s, rm);
7017 tcg_gen_add_i32(addr, addr, tmp);
7018 if (insn & (1 << 4)) {
7019 /* tbh */
7020 tcg_gen_add_i32(addr, addr, tmp);
7021 dead_tmp(tmp);
7022 tmp = gen_ld16u(addr, IS_USER(s));
7023 } else { /* tbb */
7024 dead_tmp(tmp);
7025 tmp = gen_ld8u(addr, IS_USER(s));
7027 dead_tmp(addr);
7028 tcg_gen_shli_i32(tmp, tmp, 1);
7029 tcg_gen_addi_i32(tmp, tmp, s->pc);
7030 store_reg(s, 15, tmp);
7031 } else {
7032 /* Load/store exclusive byte/halfword/doubleword. */
7033 /* ??? These are not really atomic. However we know
7034 we never have multiple CPUs running in parallel,
7035 so it is good enough. */
7036 op = (insn >> 4) & 0x3;
7037 /* Must use a global reg for the address because we have
7038 a conditional branch in the store instruction. */
7039 gen_movl_T1_reg(s, rn);
7040 addr = cpu_T[1];
7041 if (insn & (1 << 20)) {
7042 gen_helper_mark_exclusive(cpu_env, addr);
7043 switch (op) {
7044 case 0:
7045 tmp = gen_ld8u(addr, IS_USER(s));
7046 break;
7047 case 1:
7048 tmp = gen_ld16u(addr, IS_USER(s));
7049 break;
7050 case 3:
7051 tmp = gen_ld32(addr, IS_USER(s));
7052 tcg_gen_addi_i32(addr, addr, 4);
7053 tmp2 = gen_ld32(addr, IS_USER(s));
7054 store_reg(s, rd, tmp2);
7055 break;
7056 default:
7057 goto illegal_op;
7059 store_reg(s, rs, tmp);
7060 } else {
7061 int label = gen_new_label();
7062 /* Must use a global that is not killed by the branch. */
7063 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7064 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
7065 tmp = load_reg(s, rs);
7066 switch (op) {
7067 case 0:
7068 gen_st8(tmp, addr, IS_USER(s));
7069 break;
7070 case 1:
7071 gen_st16(tmp, addr, IS_USER(s));
7072 break;
7073 case 3:
7074 gen_st32(tmp, addr, IS_USER(s));
7075 tcg_gen_addi_i32(addr, addr, 4);
7076 tmp = load_reg(s, rd);
7077 gen_st32(tmp, addr, IS_USER(s));
7078 break;
7079 default:
7080 goto illegal_op;
7082 gen_set_label(label);
7083 gen_movl_reg_T0(s, rm);
7086 } else {
7087 /* Load/store multiple, RFE, SRS. */
7088 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7089 /* Not available in user mode. */
7090 if (IS_USER(s))
7091 goto illegal_op;
7092 if (insn & (1 << 20)) {
7093 /* rfe */
7094 addr = load_reg(s, rn);
7095 if ((insn & (1 << 24)) == 0)
7096 tcg_gen_addi_i32(addr, addr, -8);
7097 /* Load PC into tmp and CPSR into tmp2. */
7098 tmp = gen_ld32(addr, 0);
7099 tcg_gen_addi_i32(addr, addr, 4);
7100 tmp2 = gen_ld32(addr, 0);
7101 if (insn & (1 << 21)) {
7102 /* Base writeback. */
7103 if (insn & (1 << 24)) {
7104 tcg_gen_addi_i32(addr, addr, 4);
7105 } else {
7106 tcg_gen_addi_i32(addr, addr, -4);
7108 store_reg(s, rn, addr);
7109 } else {
7110 dead_tmp(addr);
7112 gen_rfe(s, tmp, tmp2);
7113 } else {
7114 /* srs */
7115 op = (insn & 0x1f);
7116 if (op == (env->uncached_cpsr & CPSR_M)) {
7117 addr = load_reg(s, 13);
7118 } else {
7119 addr = new_tmp();
7120 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7122 if ((insn & (1 << 24)) == 0) {
7123 tcg_gen_addi_i32(addr, addr, -8);
7125 tmp = load_reg(s, 14);
7126 gen_st32(tmp, addr, 0);
7127 tcg_gen_addi_i32(addr, addr, 4);
7128 tmp = new_tmp();
7129 gen_helper_cpsr_read(tmp);
7130 gen_st32(tmp, addr, 0);
7131 if (insn & (1 << 21)) {
7132 if ((insn & (1 << 24)) == 0) {
7133 tcg_gen_addi_i32(addr, addr, -4);
7134 } else {
7135 tcg_gen_addi_i32(addr, addr, 4);
7137 if (op == (env->uncached_cpsr & CPSR_M)) {
7138 store_reg(s, 13, addr);
7139 } else {
7140 gen_helper_set_r13_banked(cpu_env,
7141 tcg_const_i32(op), addr);
7143 } else {
7144 dead_tmp(addr);
7147 } else {
7148 int i;
7149 /* Load/store multiple. */
7150 addr = load_reg(s, rn);
7151 offset = 0;
7152 for (i = 0; i < 16; i++) {
7153 if (insn & (1 << i))
7154 offset += 4;
7156 if (insn & (1 << 24)) {
7157 tcg_gen_addi_i32(addr, addr, -offset);
7160 for (i = 0; i < 16; i++) {
7161 if ((insn & (1 << i)) == 0)
7162 continue;
7163 if (insn & (1 << 20)) {
7164 /* Load. */
7165 tmp = gen_ld32(addr, IS_USER(s));
7166 if (i == 15) {
7167 gen_bx(s, tmp);
7168 } else {
7169 store_reg(s, i, tmp);
7171 } else {
7172 /* Store. */
7173 tmp = load_reg(s, i);
7174 gen_st32(tmp, addr, IS_USER(s));
7176 tcg_gen_addi_i32(addr, addr, 4);
7178 if (insn & (1 << 21)) {
7179 /* Base register writeback. */
7180 if (insn & (1 << 24)) {
7181 tcg_gen_addi_i32(addr, addr, -offset);
7183 /* Fault if writeback register is in register list. */
7184 if (insn & (1 << rn))
7185 goto illegal_op;
7186 store_reg(s, rn, addr);
7187 } else {
7188 dead_tmp(addr);
7192 break;
7193 case 5: /* Data processing register constant shift. */
7194 if (rn == 15)
7195 gen_op_movl_T0_im(0);
7196 else
7197 gen_movl_T0_reg(s, rn);
7198 gen_movl_T1_reg(s, rm);
7199 op = (insn >> 21) & 0xf;
7200 shiftop = (insn >> 4) & 3;
7201 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7202 conds = (insn & (1 << 20)) != 0;
7203 logic_cc = (conds && thumb2_logic_op(op));
7204 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7205 if (gen_thumb2_data_op(s, op, conds, 0))
7206 goto illegal_op;
7207 if (rd != 15)
7208 gen_movl_reg_T0(s, rd);
7209 break;
7210 case 13: /* Misc data processing. */
7211 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7212 if (op < 4 && (insn & 0xf000) != 0xf000)
7213 goto illegal_op;
7214 switch (op) {
7215 case 0: /* Register controlled shift. */
7216 tmp = load_reg(s, rn);
7217 tmp2 = load_reg(s, rm);
7218 if ((insn & 0x70) != 0)
7219 goto illegal_op;
7220 op = (insn >> 21) & 3;
7221 logic_cc = (insn & (1 << 20)) != 0;
7222 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7223 if (logic_cc)
7224 gen_logic_CC(tmp);
7225 store_reg(s, rd, tmp);
7226 break;
7227 case 1: /* Sign/zero extend. */
7228 tmp = load_reg(s, rm);
7229 shift = (insn >> 4) & 3;
7230 /* ??? In many cases it's not neccessary to do a
7231 rotate, a shift is sufficient. */
7232 if (shift != 0)
7233 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7234 op = (insn >> 20) & 7;
7235 switch (op) {
7236 case 0: gen_sxth(tmp); break;
7237 case 1: gen_uxth(tmp); break;
7238 case 2: gen_sxtb16(tmp); break;
7239 case 3: gen_uxtb16(tmp); break;
7240 case 4: gen_sxtb(tmp); break;
7241 case 5: gen_uxtb(tmp); break;
7242 default: goto illegal_op;
7244 if (rn != 15) {
7245 tmp2 = load_reg(s, rn);
7246 if ((op >> 1) == 1) {
7247 gen_add16(tmp, tmp2);
7248 } else {
7249 tcg_gen_add_i32(tmp, tmp, tmp2);
7250 dead_tmp(tmp2);
7253 store_reg(s, rd, tmp);
7254 break;
7255 case 2: /* SIMD add/subtract. */
7256 op = (insn >> 20) & 7;
7257 shift = (insn >> 4) & 7;
7258 if ((op & 3) == 3 || (shift & 3) == 3)
7259 goto illegal_op;
7260 tmp = load_reg(s, rn);
7261 tmp2 = load_reg(s, rm);
7262 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7263 dead_tmp(tmp2);
7264 store_reg(s, rd, tmp);
7265 break;
7266 case 3: /* Other data processing. */
7267 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7268 if (op < 4) {
7269 /* Saturating add/subtract. */
7270 tmp = load_reg(s, rn);
7271 tmp2 = load_reg(s, rm);
7272 if (op & 2)
7273 gen_helper_double_saturate(tmp, tmp);
7274 if (op & 1)
7275 gen_helper_sub_saturate(tmp, tmp2, tmp);
7276 else
7277 gen_helper_add_saturate(tmp, tmp, tmp2);
7278 dead_tmp(tmp2);
7279 } else {
7280 tmp = load_reg(s, rn);
7281 switch (op) {
7282 case 0x0a: /* rbit */
7283 gen_helper_rbit(tmp, tmp);
7284 break;
7285 case 0x08: /* rev */
7286 tcg_gen_bswap_i32(tmp, tmp);
7287 break;
7288 case 0x09: /* rev16 */
7289 gen_rev16(tmp);
7290 break;
7291 case 0x0b: /* revsh */
7292 gen_revsh(tmp);
7293 break;
7294 case 0x10: /* sel */
7295 tmp2 = load_reg(s, rm);
7296 tmp3 = new_tmp();
7297 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7298 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7299 dead_tmp(tmp3);
7300 dead_tmp(tmp2);
7301 break;
7302 case 0x18: /* clz */
7303 gen_helper_clz(tmp, tmp);
7304 break;
7305 default:
7306 goto illegal_op;
7309 store_reg(s, rd, tmp);
7310 break;
7311 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7312 op = (insn >> 4) & 0xf;
7313 tmp = load_reg(s, rn);
7314 tmp2 = load_reg(s, rm);
7315 switch ((insn >> 20) & 7) {
7316 case 0: /* 32 x 32 -> 32 */
7317 tcg_gen_mul_i32(tmp, tmp, tmp2);
7318 dead_tmp(tmp2);
7319 if (rs != 15) {
7320 tmp2 = load_reg(s, rs);
7321 if (op)
7322 tcg_gen_sub_i32(tmp, tmp2, tmp);
7323 else
7324 tcg_gen_add_i32(tmp, tmp, tmp2);
7325 dead_tmp(tmp2);
7327 break;
7328 case 1: /* 16 x 16 -> 32 */
7329 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7330 dead_tmp(tmp2);
7331 if (rs != 15) {
7332 tmp2 = load_reg(s, rs);
7333 gen_helper_add_setq(tmp, tmp, tmp2);
7334 dead_tmp(tmp2);
7336 break;
7337 case 2: /* Dual multiply add. */
7338 case 4: /* Dual multiply subtract. */
7339 if (op)
7340 gen_swap_half(tmp2);
7341 gen_smul_dual(tmp, tmp2);
7342 /* This addition cannot overflow. */
7343 if (insn & (1 << 22)) {
7344 tcg_gen_sub_i32(tmp, tmp, tmp2);
7345 } else {
7346 tcg_gen_add_i32(tmp, tmp, tmp2);
7348 dead_tmp(tmp2);
7349 if (rs != 15)
7351 tmp2 = load_reg(s, rs);
7352 gen_helper_add_setq(tmp, tmp, tmp2);
7353 dead_tmp(tmp2);
7355 break;
7356 case 3: /* 32 * 16 -> 32msb */
7357 if (op)
7358 tcg_gen_sari_i32(tmp2, tmp2, 16);
7359 else
7360 gen_sxth(tmp2);
7361 tmp2 = gen_muls_i64_i32(tmp, tmp2);
7362 tcg_gen_shri_i64(tmp2, tmp2, 16);
7363 tmp = new_tmp();
7364 tcg_gen_trunc_i64_i32(tmp, tmp2);
7365 if (rs != 15)
7367 tmp2 = load_reg(s, rs);
7368 gen_helper_add_setq(tmp, tmp, tmp2);
7369 dead_tmp(tmp2);
7371 break;
7372 case 5: case 6: /* 32 * 32 -> 32msb */
7373 gen_imull(tmp, tmp2);
7374 if (insn & (1 << 5)) {
7375 gen_roundqd(tmp, tmp2);
7376 dead_tmp(tmp2);
7377 } else {
7378 dead_tmp(tmp);
7379 tmp = tmp2;
7381 if (rs != 15) {
7382 tmp2 = load_reg(s, rs);
7383 if (insn & (1 << 21)) {
7384 tcg_gen_add_i32(tmp, tmp, tmp2);
7385 } else {
7386 tcg_gen_sub_i32(tmp, tmp2, tmp);
7388 dead_tmp(tmp2);
7390 break;
7391 case 7: /* Unsigned sum of absolute differences. */
7392 gen_helper_usad8(tmp, tmp, tmp2);
7393 dead_tmp(tmp2);
7394 if (rs != 15) {
7395 tmp2 = load_reg(s, rs);
7396 tcg_gen_add_i32(tmp, tmp, tmp2);
7397 dead_tmp(tmp2);
7399 break;
7401 store_reg(s, rd, tmp);
7402 break;
7403 case 6: case 7: /* 64-bit multiply, Divide. */
7404 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7405 tmp = load_reg(s, rn);
7406 tmp2 = load_reg(s, rm);
7407 if ((op & 0x50) == 0x10) {
7408 /* sdiv, udiv */
7409 if (!arm_feature(env, ARM_FEATURE_DIV))
7410 goto illegal_op;
7411 if (op & 0x20)
7412 gen_helper_udiv(tmp, tmp, tmp2);
7413 else
7414 gen_helper_sdiv(tmp, tmp, tmp2);
7415 dead_tmp(tmp2);
7416 store_reg(s, rd, tmp);
7417 } else if ((op & 0xe) == 0xc) {
7418 /* Dual multiply accumulate long. */
7419 if (op & 1)
7420 gen_swap_half(tmp2);
7421 gen_smul_dual(tmp, tmp2);
7422 if (op & 0x10) {
7423 tcg_gen_sub_i32(tmp, tmp, tmp2);
7424 } else {
7425 tcg_gen_add_i32(tmp, tmp, tmp2);
7427 dead_tmp(tmp2);
7428 tmp2 = tcg_temp_new(TCG_TYPE_I64);
7429 gen_addq(s, tmp, rs, rd);
7430 gen_storeq_reg(s, rs, rd, tmp);
7431 } else {
7432 if (op & 0x20) {
7433 /* Unsigned 64-bit multiply */
7434 tmp = gen_mulu_i64_i32(tmp, tmp2);
7435 } else {
7436 if (op & 8) {
7437 /* smlalxy */
7438 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7439 dead_tmp(tmp2);
7440 tmp2 = tcg_temp_new(TCG_TYPE_I64);
7441 tcg_gen_ext_i32_i64(tmp2, tmp);
7442 dead_tmp(tmp);
7443 tmp = tmp2;
7444 } else {
7445 /* Signed 64-bit multiply */
7446 tmp = gen_muls_i64_i32(tmp, tmp2);
7449 if (op & 4) {
7450 /* umaal */
7451 gen_addq_lo(s, tmp, rs);
7452 gen_addq_lo(s, tmp, rd);
7453 } else if (op & 0x40) {
7454 /* 64-bit accumulate. */
7455 gen_addq(s, tmp, rs, rd);
7457 gen_storeq_reg(s, rs, rd, tmp);
7459 break;
7461 break;
7462 case 6: case 7: case 14: case 15:
7463 /* Coprocessor. */
7464 if (((insn >> 24) & 3) == 3) {
7465 /* Translate into the equivalent ARM encoding. */
7466 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7467 if (disas_neon_data_insn(env, s, insn))
7468 goto illegal_op;
7469 } else {
7470 if (insn & (1 << 28))
7471 goto illegal_op;
7472 if (disas_coproc_insn (env, s, insn))
7473 goto illegal_op;
7475 break;
7476 case 8: case 9: case 10: case 11:
7477 if (insn & (1 << 15)) {
7478 /* Branches, misc control. */
7479 if (insn & 0x5000) {
7480 /* Unconditional branch. */
7481 /* signextend(hw1[10:0]) -> offset[:12]. */
7482 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7483 /* hw1[10:0] -> offset[11:1]. */
7484 offset |= (insn & 0x7ff) << 1;
7485 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7486 offset[24:22] already have the same value because of the
7487 sign extension above. */
7488 offset ^= ((~insn) & (1 << 13)) << 10;
7489 offset ^= ((~insn) & (1 << 11)) << 11;
7491 if (insn & (1 << 14)) {
7492 /* Branch and link. */
7493 gen_op_movl_T1_im(s->pc | 1);
7494 gen_movl_reg_T1(s, 14);
7497 offset += s->pc;
7498 if (insn & (1 << 12)) {
7499 /* b/bl */
7500 gen_jmp(s, offset);
7501 } else {
7502 /* blx */
7503 offset &= ~(uint32_t)2;
7504 gen_bx_im(s, offset);
7506 } else if (((insn >> 23) & 7) == 7) {
7507 /* Misc control */
7508 if (insn & (1 << 13))
7509 goto illegal_op;
7511 if (insn & (1 << 26)) {
7512 /* Secure monitor call (v6Z) */
7513 goto illegal_op; /* not implemented. */
7514 } else {
7515 op = (insn >> 20) & 7;
7516 switch (op) {
7517 case 0: /* msr cpsr. */
7518 if (IS_M(env)) {
7519 tmp = load_reg(s, rn);
7520 addr = tcg_const_i32(insn & 0xff);
7521 gen_helper_v7m_msr(cpu_env, addr, tmp);
7522 gen_lookup_tb(s);
7523 break;
7525 /* fall through */
7526 case 1: /* msr spsr. */
7527 if (IS_M(env))
7528 goto illegal_op;
7529 gen_movl_T0_reg(s, rn);
7530 if (gen_set_psr_T0(s,
7531 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7532 op == 1))
7533 goto illegal_op;
7534 break;
7535 case 2: /* cps, nop-hint. */
7536 if (((insn >> 8) & 7) == 0) {
7537 gen_nop_hint(s, insn & 0xff);
7539 /* Implemented as NOP in user mode. */
7540 if (IS_USER(s))
7541 break;
7542 offset = 0;
7543 imm = 0;
7544 if (insn & (1 << 10)) {
7545 if (insn & (1 << 7))
7546 offset |= CPSR_A;
7547 if (insn & (1 << 6))
7548 offset |= CPSR_I;
7549 if (insn & (1 << 5))
7550 offset |= CPSR_F;
7551 if (insn & (1 << 9))
7552 imm = CPSR_A | CPSR_I | CPSR_F;
7554 if (insn & (1 << 8)) {
7555 offset |= 0x1f;
7556 imm |= (insn & 0x1f);
7558 if (offset) {
7559 gen_op_movl_T0_im(imm);
7560 gen_set_psr_T0(s, offset, 0);
7562 break;
7563 case 3: /* Special control operations. */
7564 op = (insn >> 4) & 0xf;
7565 switch (op) {
7566 case 2: /* clrex */
7567 gen_helper_clrex(cpu_env);
7568 break;
7569 case 4: /* dsb */
7570 case 5: /* dmb */
7571 case 6: /* isb */
7572 /* These execute as NOPs. */
7573 ARCH(7);
7574 break;
7575 default:
7576 goto illegal_op;
7578 break;
7579 case 4: /* bxj */
7580 /* Trivial implementation equivalent to bx. */
7581 tmp = load_reg(s, rn);
7582 gen_bx(s, tmp);
7583 break;
7584 case 5: /* Exception return. */
7585 /* Unpredictable in user mode. */
7586 goto illegal_op;
7587 case 6: /* mrs cpsr. */
7588 tmp = new_tmp();
7589 if (IS_M(env)) {
7590 addr = tcg_const_i32(insn & 0xff);
7591 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7592 } else {
7593 gen_helper_cpsr_read(tmp);
7595 store_reg(s, rd, tmp);
7596 break;
7597 case 7: /* mrs spsr. */
7598 /* Not accessible in user mode. */
7599 if (IS_USER(s) || IS_M(env))
7600 goto illegal_op;
7601 tmp = load_cpu_field(spsr);
7602 store_reg(s, rd, tmp);
7603 break;
7606 } else {
7607 /* Conditional branch. */
7608 op = (insn >> 22) & 0xf;
7609 /* Generate a conditional jump to next instruction. */
7610 s->condlabel = gen_new_label();
7611 gen_test_cc(op ^ 1, s->condlabel);
7612 s->condjmp = 1;
7614 /* offset[11:1] = insn[10:0] */
7615 offset = (insn & 0x7ff) << 1;
7616 /* offset[17:12] = insn[21:16]. */
7617 offset |= (insn & 0x003f0000) >> 4;
7618 /* offset[31:20] = insn[26]. */
7619 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7620 /* offset[18] = insn[13]. */
7621 offset |= (insn & (1 << 13)) << 5;
7622 /* offset[19] = insn[11]. */
7623 offset |= (insn & (1 << 11)) << 8;
7625 /* jump to the offset */
7626 gen_jmp(s, s->pc + offset);
7628 } else {
7629 /* Data processing immediate. */
7630 if (insn & (1 << 25)) {
7631 if (insn & (1 << 24)) {
7632 if (insn & (1 << 20))
7633 goto illegal_op;
7634 /* Bitfield/Saturate. */
7635 op = (insn >> 21) & 7;
7636 imm = insn & 0x1f;
7637 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7638 if (rn == 15) {
7639 tmp = new_tmp();
7640 tcg_gen_movi_i32(tmp, 0);
7641 } else {
7642 tmp = load_reg(s, rn);
7644 switch (op) {
7645 case 2: /* Signed bitfield extract. */
7646 imm++;
7647 if (shift + imm > 32)
7648 goto illegal_op;
7649 if (imm < 32)
7650 gen_sbfx(tmp, shift, imm);
7651 break;
7652 case 6: /* Unsigned bitfield extract. */
7653 imm++;
7654 if (shift + imm > 32)
7655 goto illegal_op;
7656 if (imm < 32)
7657 gen_ubfx(tmp, shift, (1u << imm) - 1);
7658 break;
7659 case 3: /* Bitfield insert/clear. */
7660 if (imm < shift)
7661 goto illegal_op;
7662 imm = imm + 1 - shift;
7663 if (imm != 32) {
7664 tmp2 = load_reg(s, rd);
7665 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7666 dead_tmp(tmp2);
7668 break;
7669 case 7:
7670 goto illegal_op;
7671 default: /* Saturate. */
7672 if (shift) {
7673 if (op & 1)
7674 tcg_gen_sari_i32(tmp, tmp, shift);
7675 else
7676 tcg_gen_shli_i32(tmp, tmp, shift);
7678 tmp2 = tcg_const_i32(imm);
7679 if (op & 4) {
7680 /* Unsigned. */
7681 if ((op & 1) && shift == 0)
7682 gen_helper_usat16(tmp, tmp, tmp2);
7683 else
7684 gen_helper_usat(tmp, tmp, tmp2);
7685 } else {
7686 /* Signed. */
7687 if ((op & 1) && shift == 0)
7688 gen_helper_ssat16(tmp, tmp, tmp2);
7689 else
7690 gen_helper_ssat(tmp, tmp, tmp2);
7692 break;
7694 store_reg(s, rd, tmp);
7695 } else {
7696 imm = ((insn & 0x04000000) >> 15)
7697 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7698 if (insn & (1 << 22)) {
7699 /* 16-bit immediate. */
7700 imm |= (insn >> 4) & 0xf000;
7701 if (insn & (1 << 23)) {
7702 /* movt */
7703 tmp = load_reg(s, rd);
7704 tcg_gen_ext16u_i32(tmp, tmp);
7705 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7706 } else {
7707 /* movw */
7708 tmp = new_tmp();
7709 tcg_gen_movi_i32(tmp, imm);
7711 } else {
7712 /* Add/sub 12-bit immediate. */
7713 if (rn == 15) {
7714 offset = s->pc & ~(uint32_t)3;
7715 if (insn & (1 << 23))
7716 offset -= imm;
7717 else
7718 offset += imm;
7719 tmp = new_tmp();
7720 tcg_gen_movi_i32(tmp, offset);
7721 } else {
7722 tmp = load_reg(s, rn);
7723 if (insn & (1 << 23))
7724 tcg_gen_subi_i32(tmp, tmp, imm);
7725 else
7726 tcg_gen_addi_i32(tmp, tmp, imm);
7729 store_reg(s, rd, tmp);
7731 } else {
7732 int shifter_out = 0;
7733 /* modified 12-bit immediate. */
7734 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7735 imm = (insn & 0xff);
7736 switch (shift) {
7737 case 0: /* XY */
7738 /* Nothing to do. */
7739 break;
7740 case 1: /* 00XY00XY */
7741 imm |= imm << 16;
7742 break;
7743 case 2: /* XY00XY00 */
7744 imm |= imm << 16;
7745 imm <<= 8;
7746 break;
7747 case 3: /* XYXYXYXY */
7748 imm |= imm << 16;
7749 imm |= imm << 8;
7750 break;
7751 default: /* Rotated constant. */
7752 shift = (shift << 1) | (imm >> 7);
7753 imm |= 0x80;
7754 imm = imm << (32 - shift);
7755 shifter_out = 1;
7756 break;
7758 gen_op_movl_T1_im(imm);
7759 rn = (insn >> 16) & 0xf;
7760 if (rn == 15)
7761 gen_op_movl_T0_im(0);
7762 else
7763 gen_movl_T0_reg(s, rn);
7764 op = (insn >> 21) & 0xf;
7765 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7766 shifter_out))
7767 goto illegal_op;
7768 rd = (insn >> 8) & 0xf;
7769 if (rd != 15) {
7770 gen_movl_reg_T0(s, rd);
7774 break;
7775 case 12: /* Load/store single data item. */
7777 int postinc = 0;
7778 int writeback = 0;
7779 int user;
7780 if ((insn & 0x01100000) == 0x01000000) {
7781 if (disas_neon_ls_insn(env, s, insn))
7782 goto illegal_op;
7783 break;
7785 user = IS_USER(s);
7786 if (rn == 15) {
7787 addr = new_tmp();
7788 /* PC relative. */
7789 /* s->pc has already been incremented by 4. */
7790 imm = s->pc & 0xfffffffc;
7791 if (insn & (1 << 23))
7792 imm += insn & 0xfff;
7793 else
7794 imm -= insn & 0xfff;
7795 tcg_gen_movi_i32(addr, imm);
7796 } else {
7797 addr = load_reg(s, rn);
7798 if (insn & (1 << 23)) {
7799 /* Positive offset. */
7800 imm = insn & 0xfff;
7801 tcg_gen_addi_i32(addr, addr, imm);
7802 } else {
7803 op = (insn >> 8) & 7;
7804 imm = insn & 0xff;
7805 switch (op) {
7806 case 0: case 8: /* Shifted Register. */
7807 shift = (insn >> 4) & 0xf;
7808 if (shift > 3)
7809 goto illegal_op;
7810 tmp = load_reg(s, rm);
7811 if (shift)
7812 tcg_gen_shli_i32(tmp, tmp, shift);
7813 tcg_gen_add_i32(addr, addr, tmp);
7814 dead_tmp(tmp);
7815 break;
7816 case 4: /* Negative offset. */
7817 tcg_gen_addi_i32(addr, addr, -imm);
7818 break;
7819 case 6: /* User privilege. */
7820 tcg_gen_addi_i32(addr, addr, imm);
7821 user = 1;
7822 break;
7823 case 1: /* Post-decrement. */
7824 imm = -imm;
7825 /* Fall through. */
7826 case 3: /* Post-increment. */
7827 postinc = 1;
7828 writeback = 1;
7829 break;
7830 case 5: /* Pre-decrement. */
7831 imm = -imm;
7832 /* Fall through. */
7833 case 7: /* Pre-increment. */
7834 tcg_gen_addi_i32(addr, addr, imm);
7835 writeback = 1;
7836 break;
7837 default:
7838 goto illegal_op;
7842 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7843 if (insn & (1 << 20)) {
7844 /* Load. */
7845 if (rs == 15 && op != 2) {
7846 if (op & 2)
7847 goto illegal_op;
7848 /* Memory hint. Implemented as NOP. */
7849 } else {
7850 switch (op) {
7851 case 0: tmp = gen_ld8u(addr, user); break;
7852 case 4: tmp = gen_ld8s(addr, user); break;
7853 case 1: tmp = gen_ld16u(addr, user); break;
7854 case 5: tmp = gen_ld16s(addr, user); break;
7855 case 2: tmp = gen_ld32(addr, user); break;
7856 default: goto illegal_op;
7858 if (rs == 15) {
7859 gen_bx(s, tmp);
7860 } else {
7861 store_reg(s, rs, tmp);
7864 } else {
7865 /* Store. */
7866 if (rs == 15)
7867 goto illegal_op;
7868 tmp = load_reg(s, rs);
7869 switch (op) {
7870 case 0: gen_st8(tmp, addr, user); break;
7871 case 1: gen_st16(tmp, addr, user); break;
7872 case 2: gen_st32(tmp, addr, user); break;
7873 default: goto illegal_op;
7876 if (postinc)
7877 tcg_gen_addi_i32(addr, addr, imm);
7878 if (writeback) {
7879 store_reg(s, rn, addr);
7880 } else {
7881 dead_tmp(addr);
7884 break;
7885 default:
7886 goto illegal_op;
7888 return 0;
7889 illegal_op:
7890 return 1;
7893 static void disas_thumb_insn(CPUState *env, DisasContext *s)
7895 uint32_t val, insn, op, rm, rn, rd, shift, cond;
7896 int32_t offset;
7897 int i;
7898 TCGv tmp;
7899 TCGv tmp2;
7900 TCGv addr;
7902 if (s->condexec_mask) {
7903 cond = s->condexec_cond;
7904 s->condlabel = gen_new_label();
7905 gen_test_cc(cond ^ 1, s->condlabel);
7906 s->condjmp = 1;
7909 insn = lduw_code(s->pc);
7910 s->pc += 2;
7912 switch (insn >> 12) {
7913 case 0: case 1:
7914 rd = insn & 7;
7915 op = (insn >> 11) & 3;
7916 if (op == 3) {
7917 /* add/subtract */
7918 rn = (insn >> 3) & 7;
7919 gen_movl_T0_reg(s, rn);
7920 if (insn & (1 << 10)) {
7921 /* immediate */
7922 gen_op_movl_T1_im((insn >> 6) & 7);
7923 } else {
7924 /* reg */
7925 rm = (insn >> 6) & 7;
7926 gen_movl_T1_reg(s, rm);
7928 if (insn & (1 << 9)) {
7929 if (s->condexec_mask)
7930 gen_op_subl_T0_T1();
7931 else
7932 gen_op_subl_T0_T1_cc();
7933 } else {
7934 if (s->condexec_mask)
7935 gen_op_addl_T0_T1();
7936 else
7937 gen_op_addl_T0_T1_cc();
7939 gen_movl_reg_T0(s, rd);
7940 } else {
7941 /* shift immediate */
7942 rm = (insn >> 3) & 7;
7943 shift = (insn >> 6) & 0x1f;
7944 tmp = load_reg(s, rm);
7945 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
7946 if (!s->condexec_mask)
7947 gen_logic_CC(tmp);
7948 store_reg(s, rd, tmp);
7950 break;
7951 case 2: case 3:
7952 /* arithmetic large immediate */
7953 op = (insn >> 11) & 3;
7954 rd = (insn >> 8) & 0x7;
7955 if (op == 0) {
7956 gen_op_movl_T0_im(insn & 0xff);
7957 } else {
7958 gen_movl_T0_reg(s, rd);
7959 gen_op_movl_T1_im(insn & 0xff);
7961 switch (op) {
7962 case 0: /* mov */
7963 if (!s->condexec_mask)
7964 gen_op_logic_T0_cc();
7965 break;
7966 case 1: /* cmp */
7967 gen_op_subl_T0_T1_cc();
7968 break;
7969 case 2: /* add */
7970 if (s->condexec_mask)
7971 gen_op_addl_T0_T1();
7972 else
7973 gen_op_addl_T0_T1_cc();
7974 break;
7975 case 3: /* sub */
7976 if (s->condexec_mask)
7977 gen_op_subl_T0_T1();
7978 else
7979 gen_op_subl_T0_T1_cc();
7980 break;
7982 if (op != 1)
7983 gen_movl_reg_T0(s, rd);
7984 break;
7985 case 4:
7986 if (insn & (1 << 11)) {
7987 rd = (insn >> 8) & 7;
7988 /* load pc-relative. Bit 1 of PC is ignored. */
7989 val = s->pc + 2 + ((insn & 0xff) * 4);
7990 val &= ~(uint32_t)2;
7991 addr = new_tmp();
7992 tcg_gen_movi_i32(addr, val);
7993 tmp = gen_ld32(addr, IS_USER(s));
7994 dead_tmp(addr);
7995 store_reg(s, rd, tmp);
7996 break;
7998 if (insn & (1 << 10)) {
7999 /* data processing extended or blx */
8000 rd = (insn & 7) | ((insn >> 4) & 8);
8001 rm = (insn >> 3) & 0xf;
8002 op = (insn >> 8) & 3;
8003 switch (op) {
8004 case 0: /* add */
8005 gen_movl_T0_reg(s, rd);
8006 gen_movl_T1_reg(s, rm);
8007 gen_op_addl_T0_T1();
8008 gen_movl_reg_T0(s, rd);
8009 break;
8010 case 1: /* cmp */
8011 gen_movl_T0_reg(s, rd);
8012 gen_movl_T1_reg(s, rm);
8013 gen_op_subl_T0_T1_cc();
8014 break;
8015 case 2: /* mov/cpy */
8016 gen_movl_T0_reg(s, rm);
8017 gen_movl_reg_T0(s, rd);
8018 break;
8019 case 3:/* branch [and link] exchange thumb register */
8020 tmp = load_reg(s, rm);
8021 if (insn & (1 << 7)) {
8022 val = (uint32_t)s->pc | 1;
8023 tmp2 = new_tmp();
8024 tcg_gen_movi_i32(tmp2, val);
8025 store_reg(s, 14, tmp2);
8027 gen_bx(s, tmp);
8028 break;
8030 break;
8033 /* data processing register */
8034 rd = insn & 7;
8035 rm = (insn >> 3) & 7;
8036 op = (insn >> 6) & 0xf;
8037 if (op == 2 || op == 3 || op == 4 || op == 7) {
8038 /* the shift/rotate ops want the operands backwards */
8039 val = rm;
8040 rm = rd;
8041 rd = val;
8042 val = 1;
8043 } else {
8044 val = 0;
8047 if (op == 9) /* neg */
8048 gen_op_movl_T0_im(0);
8049 else if (op != 0xf) /* mvn doesn't read its first operand */
8050 gen_movl_T0_reg(s, rd);
8052 gen_movl_T1_reg(s, rm);
8053 switch (op) {
8054 case 0x0: /* and */
8055 gen_op_andl_T0_T1();
8056 if (!s->condexec_mask)
8057 gen_op_logic_T0_cc();
8058 break;
8059 case 0x1: /* eor */
8060 gen_op_xorl_T0_T1();
8061 if (!s->condexec_mask)
8062 gen_op_logic_T0_cc();
8063 break;
8064 case 0x2: /* lsl */
8065 if (s->condexec_mask) {
8066 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8067 } else {
8068 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8069 gen_op_logic_T1_cc();
8071 break;
8072 case 0x3: /* lsr */
8073 if (s->condexec_mask) {
8074 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8075 } else {
8076 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8077 gen_op_logic_T1_cc();
8079 break;
8080 case 0x4: /* asr */
8081 if (s->condexec_mask) {
8082 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8083 } else {
8084 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8085 gen_op_logic_T1_cc();
8087 break;
8088 case 0x5: /* adc */
8089 if (s->condexec_mask)
8090 gen_adc_T0_T1();
8091 else
8092 gen_op_adcl_T0_T1_cc();
8093 break;
8094 case 0x6: /* sbc */
8095 if (s->condexec_mask)
8096 gen_sbc_T0_T1();
8097 else
8098 gen_op_sbcl_T0_T1_cc();
8099 break;
8100 case 0x7: /* ror */
8101 if (s->condexec_mask) {
8102 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8103 } else {
8104 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8105 gen_op_logic_T1_cc();
8107 break;
8108 case 0x8: /* tst */
8109 gen_op_andl_T0_T1();
8110 gen_op_logic_T0_cc();
8111 rd = 16;
8112 break;
8113 case 0x9: /* neg */
8114 if (s->condexec_mask)
8115 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
8116 else
8117 gen_op_subl_T0_T1_cc();
8118 break;
8119 case 0xa: /* cmp */
8120 gen_op_subl_T0_T1_cc();
8121 rd = 16;
8122 break;
8123 case 0xb: /* cmn */
8124 gen_op_addl_T0_T1_cc();
8125 rd = 16;
8126 break;
8127 case 0xc: /* orr */
8128 gen_op_orl_T0_T1();
8129 if (!s->condexec_mask)
8130 gen_op_logic_T0_cc();
8131 break;
8132 case 0xd: /* mul */
8133 gen_op_mull_T0_T1();
8134 if (!s->condexec_mask)
8135 gen_op_logic_T0_cc();
8136 break;
8137 case 0xe: /* bic */
8138 gen_op_bicl_T0_T1();
8139 if (!s->condexec_mask)
8140 gen_op_logic_T0_cc();
8141 break;
8142 case 0xf: /* mvn */
8143 gen_op_notl_T1();
8144 if (!s->condexec_mask)
8145 gen_op_logic_T1_cc();
8146 val = 1;
8147 rm = rd;
8148 break;
8150 if (rd != 16) {
8151 if (val)
8152 gen_movl_reg_T1(s, rm);
8153 else
8154 gen_movl_reg_T0(s, rd);
8156 break;
8158 case 5:
8159 /* load/store register offset. */
8160 rd = insn & 7;
8161 rn = (insn >> 3) & 7;
8162 rm = (insn >> 6) & 7;
8163 op = (insn >> 9) & 7;
8164 addr = load_reg(s, rn);
8165 tmp = load_reg(s, rm);
8166 tcg_gen_add_i32(addr, addr, tmp);
8167 dead_tmp(tmp);
8169 if (op < 3) /* store */
8170 tmp = load_reg(s, rd);
8172 switch (op) {
8173 case 0: /* str */
8174 gen_st32(tmp, addr, IS_USER(s));
8175 break;
8176 case 1: /* strh */
8177 gen_st16(tmp, addr, IS_USER(s));
8178 break;
8179 case 2: /* strb */
8180 gen_st8(tmp, addr, IS_USER(s));
8181 break;
8182 case 3: /* ldrsb */
8183 tmp = gen_ld8s(addr, IS_USER(s));
8184 break;
8185 case 4: /* ldr */
8186 tmp = gen_ld32(addr, IS_USER(s));
8187 break;
8188 case 5: /* ldrh */
8189 tmp = gen_ld16u(addr, IS_USER(s));
8190 break;
8191 case 6: /* ldrb */
8192 tmp = gen_ld8u(addr, IS_USER(s));
8193 break;
8194 case 7: /* ldrsh */
8195 tmp = gen_ld16s(addr, IS_USER(s));
8196 break;
8198 if (op >= 3) /* load */
8199 store_reg(s, rd, tmp);
8200 dead_tmp(addr);
8201 break;
8203 case 6:
8204 /* load/store word immediate offset */
8205 rd = insn & 7;
8206 rn = (insn >> 3) & 7;
8207 addr = load_reg(s, rn);
8208 val = (insn >> 4) & 0x7c;
8209 tcg_gen_addi_i32(addr, addr, val);
8211 if (insn & (1 << 11)) {
8212 /* load */
8213 tmp = gen_ld32(addr, IS_USER(s));
8214 store_reg(s, rd, tmp);
8215 } else {
8216 /* store */
8217 tmp = load_reg(s, rd);
8218 gen_st32(tmp, addr, IS_USER(s));
8220 dead_tmp(addr);
8221 break;
8223 case 7:
8224 /* load/store byte immediate offset */
8225 rd = insn & 7;
8226 rn = (insn >> 3) & 7;
8227 addr = load_reg(s, rn);
8228 val = (insn >> 6) & 0x1f;
8229 tcg_gen_addi_i32(addr, addr, val);
8231 if (insn & (1 << 11)) {
8232 /* load */
8233 tmp = gen_ld8u(addr, IS_USER(s));
8234 store_reg(s, rd, tmp);
8235 } else {
8236 /* store */
8237 tmp = load_reg(s, rd);
8238 gen_st8(tmp, addr, IS_USER(s));
8240 dead_tmp(addr);
8241 break;
8243 case 8:
8244 /* load/store halfword immediate offset */
8245 rd = insn & 7;
8246 rn = (insn >> 3) & 7;
8247 addr = load_reg(s, rn);
8248 val = (insn >> 5) & 0x3e;
8249 tcg_gen_addi_i32(addr, addr, val);
8251 if (insn & (1 << 11)) {
8252 /* load */
8253 tmp = gen_ld16u(addr, IS_USER(s));
8254 store_reg(s, rd, tmp);
8255 } else {
8256 /* store */
8257 tmp = load_reg(s, rd);
8258 gen_st16(tmp, addr, IS_USER(s));
8260 dead_tmp(addr);
8261 break;
8263 case 9:
8264 /* load/store from stack */
8265 rd = (insn >> 8) & 7;
8266 addr = load_reg(s, 13);
8267 val = (insn & 0xff) * 4;
8268 tcg_gen_addi_i32(addr, addr, val);
8270 if (insn & (1 << 11)) {
8271 /* load */
8272 tmp = gen_ld32(addr, IS_USER(s));
8273 store_reg(s, rd, tmp);
8274 } else {
8275 /* store */
8276 tmp = load_reg(s, rd);
8277 gen_st32(tmp, addr, IS_USER(s));
8279 dead_tmp(addr);
8280 break;
8282 case 10:
8283 /* add to high reg */
8284 rd = (insn >> 8) & 7;
8285 if (insn & (1 << 11)) {
8286 /* SP */
8287 tmp = load_reg(s, 13);
8288 } else {
8289 /* PC. bit 1 is ignored. */
8290 tmp = new_tmp();
8291 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8293 val = (insn & 0xff) * 4;
8294 tcg_gen_addi_i32(tmp, tmp, val);
8295 store_reg(s, rd, tmp);
8296 break;
8298 case 11:
8299 /* misc */
8300 op = (insn >> 8) & 0xf;
8301 switch (op) {
8302 case 0:
8303 /* adjust stack pointer */
8304 tmp = load_reg(s, 13);
8305 val = (insn & 0x7f) * 4;
8306 if (insn & (1 << 7))
8307 val = -(int32_t)val;
8308 tcg_gen_addi_i32(tmp, tmp, val);
8309 store_reg(s, 13, tmp);
8310 break;
8312 case 2: /* sign/zero extend. */
8313 ARCH(6);
8314 rd = insn & 7;
8315 rm = (insn >> 3) & 7;
8316 tmp = load_reg(s, rm);
8317 switch ((insn >> 6) & 3) {
8318 case 0: gen_sxth(tmp); break;
8319 case 1: gen_sxtb(tmp); break;
8320 case 2: gen_uxth(tmp); break;
8321 case 3: gen_uxtb(tmp); break;
8323 store_reg(s, rd, tmp);
8324 break;
8325 case 4: case 5: case 0xc: case 0xd:
8326 /* push/pop */
8327 addr = load_reg(s, 13);
8328 if (insn & (1 << 8))
8329 offset = 4;
8330 else
8331 offset = 0;
8332 for (i = 0; i < 8; i++) {
8333 if (insn & (1 << i))
8334 offset += 4;
8336 if ((insn & (1 << 11)) == 0) {
8337 tcg_gen_addi_i32(addr, addr, -offset);
8339 for (i = 0; i < 8; i++) {
8340 if (insn & (1 << i)) {
8341 if (insn & (1 << 11)) {
8342 /* pop */
8343 tmp = gen_ld32(addr, IS_USER(s));
8344 store_reg(s, i, tmp);
8345 } else {
8346 /* push */
8347 tmp = load_reg(s, i);
8348 gen_st32(tmp, addr, IS_USER(s));
8350 /* advance to the next address. */
8351 tcg_gen_addi_i32(addr, addr, 4);
8354 TCGV_UNUSED(tmp);
8355 if (insn & (1 << 8)) {
8356 if (insn & (1 << 11)) {
8357 /* pop pc */
8358 tmp = gen_ld32(addr, IS_USER(s));
8359 /* don't set the pc until the rest of the instruction
8360 has completed */
8361 } else {
8362 /* push lr */
8363 tmp = load_reg(s, 14);
8364 gen_st32(tmp, addr, IS_USER(s));
8366 tcg_gen_addi_i32(addr, addr, 4);
8368 if ((insn & (1 << 11)) == 0) {
8369 tcg_gen_addi_i32(addr, addr, -offset);
8371 /* write back the new stack pointer */
8372 store_reg(s, 13, addr);
8373 /* set the new PC value */
8374 if ((insn & 0x0900) == 0x0900)
8375 gen_bx(s, tmp);
8376 break;
8378 case 1: case 3: case 9: case 11: /* czb */
8379 rm = insn & 7;
8380 tmp = load_reg(s, rm);
8381 s->condlabel = gen_new_label();
8382 s->condjmp = 1;
8383 if (insn & (1 << 11))
8384 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8385 else
8386 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8387 dead_tmp(tmp);
8388 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8389 val = (uint32_t)s->pc + 2;
8390 val += offset;
8391 gen_jmp(s, val);
8392 break;
8394 case 15: /* IT, nop-hint. */
8395 if ((insn & 0xf) == 0) {
8396 gen_nop_hint(s, (insn >> 4) & 0xf);
8397 break;
8399 /* If Then. */
8400 s->condexec_cond = (insn >> 4) & 0xe;
8401 s->condexec_mask = insn & 0x1f;
8402 /* No actual code generated for this insn, just setup state. */
8403 break;
8405 case 0xe: /* bkpt */
8406 gen_set_condexec(s);
8407 gen_set_pc_im(s->pc - 2);
8408 gen_exception(EXCP_BKPT);
8409 s->is_jmp = DISAS_JUMP;
8410 break;
8412 case 0xa: /* rev */
8413 ARCH(6);
8414 rn = (insn >> 3) & 0x7;
8415 rd = insn & 0x7;
8416 tmp = load_reg(s, rn);
8417 switch ((insn >> 6) & 3) {
8418 case 0: tcg_gen_bswap_i32(tmp, tmp); break;
8419 case 1: gen_rev16(tmp); break;
8420 case 3: gen_revsh(tmp); break;
8421 default: goto illegal_op;
8423 store_reg(s, rd, tmp);
8424 break;
8426 case 6: /* cps */
8427 ARCH(6);
8428 if (IS_USER(s))
8429 break;
8430 if (IS_M(env)) {
8431 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8432 /* PRIMASK */
8433 if (insn & 1) {
8434 addr = tcg_const_i32(16);
8435 gen_helper_v7m_msr(cpu_env, addr, tmp);
8437 /* FAULTMASK */
8438 if (insn & 2) {
8439 addr = tcg_const_i32(17);
8440 gen_helper_v7m_msr(cpu_env, addr, tmp);
8442 gen_lookup_tb(s);
8443 } else {
8444 if (insn & (1 << 4))
8445 shift = CPSR_A | CPSR_I | CPSR_F;
8446 else
8447 shift = 0;
8449 val = ((insn & 7) << 6) & shift;
8450 gen_op_movl_T0_im(val);
8451 gen_set_psr_T0(s, shift, 0);
8453 break;
8455 default:
8456 goto undef;
8458 break;
8460 case 12:
8461 /* load/store multiple */
8462 rn = (insn >> 8) & 0x7;
8463 addr = load_reg(s, rn);
8464 for (i = 0; i < 8; i++) {
8465 if (insn & (1 << i)) {
8466 if (insn & (1 << 11)) {
8467 /* load */
8468 tmp = gen_ld32(addr, IS_USER(s));
8469 store_reg(s, i, tmp);
8470 } else {
8471 /* store */
8472 tmp = load_reg(s, i);
8473 gen_st32(tmp, addr, IS_USER(s));
8475 /* advance to the next address */
8476 tcg_gen_addi_i32(addr, addr, 4);
8479 /* Base register writeback. */
8480 if ((insn & (1 << rn)) == 0) {
8481 store_reg(s, rn, addr);
8482 } else {
8483 dead_tmp(addr);
8485 break;
8487 case 13:
8488 /* conditional branch or swi */
8489 cond = (insn >> 8) & 0xf;
8490 if (cond == 0xe)
8491 goto undef;
8493 if (cond == 0xf) {
8494 /* swi */
8495 gen_set_condexec(s);
8496 gen_set_pc_im(s->pc);
8497 s->is_jmp = DISAS_SWI;
8498 break;
8500 /* generate a conditional jump to next instruction */
8501 s->condlabel = gen_new_label();
8502 gen_test_cc(cond ^ 1, s->condlabel);
8503 s->condjmp = 1;
8504 gen_movl_T1_reg(s, 15);
8506 /* jump to the offset */
8507 val = (uint32_t)s->pc + 2;
8508 offset = ((int32_t)insn << 24) >> 24;
8509 val += offset << 1;
8510 gen_jmp(s, val);
8511 break;
8513 case 14:
8514 if (insn & (1 << 11)) {
8515 if (disas_thumb2_insn(env, s, insn))
8516 goto undef32;
8517 break;
8519 /* unconditional branch */
8520 val = (uint32_t)s->pc;
8521 offset = ((int32_t)insn << 21) >> 21;
8522 val += (offset << 1) + 2;
8523 gen_jmp(s, val);
8524 break;
8526 case 15:
8527 if (disas_thumb2_insn(env, s, insn))
8528 goto undef32;
8529 break;
8531 return;
8532 undef32:
8533 gen_set_condexec(s);
8534 gen_set_pc_im(s->pc - 4);
8535 gen_exception(EXCP_UDEF);
8536 s->is_jmp = DISAS_JUMP;
8537 return;
8538 illegal_op:
8539 undef:
8540 gen_set_condexec(s);
8541 gen_set_pc_im(s->pc - 2);
8542 gen_exception(EXCP_UDEF);
8543 s->is_jmp = DISAS_JUMP;
8546 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8547 basic block 'tb'. If search_pc is TRUE, also generate PC
8548 information for each intermediate instruction. */
8549 static inline void gen_intermediate_code_internal(CPUState *env,
8550 TranslationBlock *tb,
8551 int search_pc)
8553 DisasContext dc1, *dc = &dc1;
8554 uint16_t *gen_opc_end;
8555 int j, lj;
8556 target_ulong pc_start;
8557 uint32_t next_page_start;
8558 int num_insns;
8559 int max_insns;
8561 /* generate intermediate code */
8562 num_temps = 0;
8563 memset(temps, 0, sizeof(temps));
8565 pc_start = tb->pc;
8567 dc->tb = tb;
8569 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8571 dc->is_jmp = DISAS_NEXT;
8572 dc->pc = pc_start;
8573 dc->singlestep_enabled = env->singlestep_enabled;
8574 dc->condjmp = 0;
8575 dc->thumb = env->thumb;
8576 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8577 dc->condexec_cond = env->condexec_bits >> 4;
8578 dc->is_mem = 0;
8579 #if !defined(CONFIG_USER_ONLY)
8580 if (IS_M(env)) {
8581 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8582 } else {
8583 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8585 #endif
8586 cpu_F0s = tcg_temp_new(TCG_TYPE_I32);
8587 cpu_F1s = tcg_temp_new(TCG_TYPE_I32);
8588 cpu_F0d = tcg_temp_new(TCG_TYPE_I64);
8589 cpu_F1d = tcg_temp_new(TCG_TYPE_I64);
8590 cpu_V0 = cpu_F0d;
8591 cpu_V1 = cpu_F1d;
8592 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8593 cpu_M0 = tcg_temp_new(TCG_TYPE_I64);
8594 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8595 lj = -1;
8596 num_insns = 0;
8597 max_insns = tb->cflags & CF_COUNT_MASK;
8598 if (max_insns == 0)
8599 max_insns = CF_COUNT_MASK;
8601 gen_icount_start();
8602 /* Reset the conditional execution bits immediately. This avoids
8603 complications trying to do it at the end of the block. */
8604 if (env->condexec_bits)
8606 TCGv tmp = new_tmp();
8607 tcg_gen_movi_i32(tmp, 0);
8608 store_cpu_field(tmp, condexec_bits);
8610 do {
8611 #ifdef CONFIG_USER_ONLY
8612 /* Intercept jump to the magic kernel page. */
8613 if (dc->pc >= 0xffff0000) {
8614 /* We always get here via a jump, so know we are not in a
8615 conditional execution block. */
8616 gen_exception(EXCP_KERNEL_TRAP);
8617 dc->is_jmp = DISAS_UPDATE;
8618 break;
8620 #else
8621 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8622 /* We always get here via a jump, so know we are not in a
8623 conditional execution block. */
8624 gen_exception(EXCP_EXCEPTION_EXIT);
8625 dc->is_jmp = DISAS_UPDATE;
8626 break;
8628 #endif
8630 if (env->nb_breakpoints > 0) {
8631 for(j = 0; j < env->nb_breakpoints; j++) {
8632 if (env->breakpoints[j] == dc->pc) {
8633 gen_set_condexec(dc);
8634 gen_set_pc_im(dc->pc);
8635 gen_exception(EXCP_DEBUG);
8636 dc->is_jmp = DISAS_JUMP;
8637 /* Advance PC so that clearing the breakpoint will
8638 invalidate this TB. */
8639 dc->pc += 2;
8640 goto done_generating;
8641 break;
8645 if (search_pc) {
8646 j = gen_opc_ptr - gen_opc_buf;
8647 if (lj < j) {
8648 lj++;
8649 while (lj < j)
8650 gen_opc_instr_start[lj++] = 0;
8652 gen_opc_pc[lj] = dc->pc;
8653 gen_opc_instr_start[lj] = 1;
8654 gen_opc_icount[lj] = num_insns;
8657 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8658 gen_io_start();
8660 if (env->thumb) {
8661 disas_thumb_insn(env, dc);
8662 if (dc->condexec_mask) {
8663 dc->condexec_cond = (dc->condexec_cond & 0xe)
8664 | ((dc->condexec_mask >> 4) & 1);
8665 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8666 if (dc->condexec_mask == 0) {
8667 dc->condexec_cond = 0;
8670 } else {
8671 disas_arm_insn(env, dc);
8673 if (num_temps) {
8674 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8675 num_temps = 0;
8678 if (dc->condjmp && !dc->is_jmp) {
8679 gen_set_label(dc->condlabel);
8680 dc->condjmp = 0;
8682 /* Terminate the TB on memory ops if watchpoints are present. */
8683 /* FIXME: This should be replacd by the deterministic execution
8684 * IRQ raising bits. */
8685 if (dc->is_mem && env->nb_watchpoints)
8686 break;
8688 /* Translation stops when a conditional branch is enoutered.
8689 * Otherwise the subsequent code could get translated several times.
8690 * Also stop translation when a page boundary is reached. This
8691 * ensures prefetch aborts occur at the right place. */
8692 num_insns ++;
8693 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8694 !env->singlestep_enabled &&
8695 dc->pc < next_page_start &&
8696 num_insns < max_insns);
8698 if (tb->cflags & CF_LAST_IO) {
8699 if (dc->condjmp) {
8700 /* FIXME: This can theoretically happen with self-modifying
8701 code. */
8702 cpu_abort(env, "IO on conditional branch instruction");
8704 gen_io_end();
8707 /* At this stage dc->condjmp will only be set when the skipped
8708 instruction was a conditional branch or trap, and the PC has
8709 already been written. */
8710 if (unlikely(env->singlestep_enabled)) {
8711 /* Make sure the pc is updated, and raise a debug exception. */
8712 if (dc->condjmp) {
8713 gen_set_condexec(dc);
8714 if (dc->is_jmp == DISAS_SWI) {
8715 gen_exception(EXCP_SWI);
8716 } else {
8717 gen_exception(EXCP_DEBUG);
8719 gen_set_label(dc->condlabel);
8721 if (dc->condjmp || !dc->is_jmp) {
8722 gen_set_pc_im(dc->pc);
8723 dc->condjmp = 0;
8725 gen_set_condexec(dc);
8726 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8727 gen_exception(EXCP_SWI);
8728 } else {
8729 /* FIXME: Single stepping a WFI insn will not halt
8730 the CPU. */
8731 gen_exception(EXCP_DEBUG);
8733 } else {
8734 /* While branches must always occur at the end of an IT block,
8735 there are a few other things that can cause us to terminate
8736 the TB in the middel of an IT block:
8737 - Exception generating instructions (bkpt, swi, undefined).
8738 - Page boundaries.
8739 - Hardware watchpoints.
8740 Hardware breakpoints have already been handled and skip this code.
8742 gen_set_condexec(dc);
8743 switch(dc->is_jmp) {
8744 case DISAS_NEXT:
8745 gen_goto_tb(dc, 1, dc->pc);
8746 break;
8747 default:
8748 case DISAS_JUMP:
8749 case DISAS_UPDATE:
8750 /* indicate that the hash table must be used to find the next TB */
8751 tcg_gen_exit_tb(0);
8752 break;
8753 case DISAS_TB_JUMP:
8754 /* nothing more to generate */
8755 break;
8756 case DISAS_WFI:
8757 gen_helper_wfi();
8758 break;
8759 case DISAS_SWI:
8760 gen_exception(EXCP_SWI);
8761 break;
8763 if (dc->condjmp) {
8764 gen_set_label(dc->condlabel);
8765 gen_set_condexec(dc);
8766 gen_goto_tb(dc, 1, dc->pc);
8767 dc->condjmp = 0;
8771 done_generating:
8772 gen_icount_end(tb, num_insns);
8773 *gen_opc_ptr = INDEX_op_end;
8775 #ifdef DEBUG_DISAS
8776 if (loglevel & CPU_LOG_TB_IN_ASM) {
8777 fprintf(logfile, "----------------\n");
8778 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8779 target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
8780 fprintf(logfile, "\n");
8782 #endif
8783 if (search_pc) {
8784 j = gen_opc_ptr - gen_opc_buf;
8785 lj++;
8786 while (lj <= j)
8787 gen_opc_instr_start[lj++] = 0;
8788 } else {
8789 tb->size = dc->pc - pc_start;
8790 tb->icount = num_insns;
8794 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8796 gen_intermediate_code_internal(env, tb, 0);
8799 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8801 gen_intermediate_code_internal(env, tb, 1);
8804 static const char *cpu_mode_names[16] = {
8805 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8806 "???", "???", "???", "und", "???", "???", "???", "sys"
8809 void cpu_dump_state(CPUState *env, FILE *f,
8810 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8811 int flags)
8813 int i;
8814 #if 0
8815 union {
8816 uint32_t i;
8817 float s;
8818 } s0, s1;
8819 CPU_DoubleU d;
8820 /* ??? This assumes float64 and double have the same layout.
8821 Oh well, it's only debug dumps. */
8822 union {
8823 float64 f64;
8824 double d;
8825 } d0;
8826 #endif
8827 uint32_t psr;
8829 for(i=0;i<16;i++) {
8830 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8831 if ((i % 4) == 3)
8832 cpu_fprintf(f, "\n");
8833 else
8834 cpu_fprintf(f, " ");
8836 psr = cpsr_read(env);
8837 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8838 psr,
8839 psr & (1 << 31) ? 'N' : '-',
8840 psr & (1 << 30) ? 'Z' : '-',
8841 psr & (1 << 29) ? 'C' : '-',
8842 psr & (1 << 28) ? 'V' : '-',
8843 psr & CPSR_T ? 'T' : 'A',
8844 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8846 #if 0
8847 for (i = 0; i < 16; i++) {
8848 d.d = env->vfp.regs[i];
8849 s0.i = d.l.lower;
8850 s1.i = d.l.upper;
8851 d0.f64 = d.d;
8852 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8853 i * 2, (int)s0.i, s0.s,
8854 i * 2 + 1, (int)s1.i, s1.s,
8855 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
8856 d0.d);
8858 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
8859 #endif
8862 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8863 unsigned long searched_pc, int pc_pos, void *puc)
8865 env->regs[15] = gen_opc_pc[pc_pos];