More TCG updates for CRIS
[qemu/qemu-JZ.git] / target-arm / translate.c
blobbfe0f213539ad2faea380036899d1590f4a8b746
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"
33 #define GEN_HELPER 1
34 #include "helpers.h"
36 #define ENABLE_ARCH_5J 0
37 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
38 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
39 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
40 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
42 #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
44 /* internal defines */
45 typedef struct DisasContext {
46 target_ulong pc;
47 int is_jmp;
48 /* Nonzero if this instruction has been conditionally skipped. */
49 int condjmp;
50 /* The label that will be jumped to when the instruction is skipped. */
51 int condlabel;
52 /* Thumb-2 condtional execution bits. */
53 int condexec_mask;
54 int condexec_cond;
55 struct TranslationBlock *tb;
56 int singlestep_enabled;
57 int thumb;
58 int is_mem;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 } DisasContext;
64 #if defined(CONFIG_USER_ONLY)
65 #define IS_USER(s) 1
66 #else
67 #define IS_USER(s) (s->user)
68 #endif
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72 #define DISAS_WFI 4
73 #define DISAS_SWI 5
75 /* XXX: move that elsewhere */
76 extern FILE *logfile;
77 extern int loglevel;
79 static TCGv cpu_env;
80 /* We reuse the same 64-bit temporaries for efficiency. */
81 static TCGv cpu_V0, cpu_V1, cpu_M0;
83 /* FIXME: These should be removed. */
84 static TCGv cpu_T[2];
85 static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d;
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_andi_i32(var, var, 0xff)
225 #define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
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_ext8s_i32(tmp1, a);
251 tcg_gen_ext8s_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 /* FIXME: Implement this natively. */
455 static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
457 tcg_gen_xori_i32(t0, t1, ~0);
460 /* FIXME: Implement this natively. */
461 static inline void tcg_gen_neg_i64(TCGv dest, TCGv src)
463 tcg_gen_sub_i64(dest, tcg_const_i64(0), src);
466 /* T0 &= ~T1. Clobbers T1. */
467 /* FIXME: Implement bic natively. */
468 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
470 TCGv tmp = new_tmp();
471 tcg_gen_not_i32(tmp, t1);
472 tcg_gen_and_i32(dest, t0, tmp);
473 dead_tmp(tmp);
475 static inline void gen_op_bicl_T0_T1(void)
477 gen_op_notl_T1();
478 gen_op_andl_T0_T1();
481 /* FIXME: Implement this natively. */
482 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
484 /* FIXME: Implement this natively. */
485 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
487 TCGv tmp;
489 if (i == 0)
490 return;
492 tmp = new_tmp();
493 tcg_gen_shri_i32(tmp, t1, i);
494 tcg_gen_shli_i32(t1, t1, 32 - i);
495 tcg_gen_or_i32(t0, t1, tmp);
496 dead_tmp(tmp);
499 static void shifter_out_im(TCGv var, int shift)
501 TCGv tmp = new_tmp();
502 if (shift == 0) {
503 tcg_gen_andi_i32(tmp, var, 1);
504 } else {
505 tcg_gen_shri_i32(tmp, var, shift);
506 if (shift != 31);
507 tcg_gen_andi_i32(tmp, tmp, 1);
509 gen_set_CF(tmp);
510 dead_tmp(tmp);
513 /* Shift by immediate. Includes special handling for shift == 0. */
514 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
516 switch (shiftop) {
517 case 0: /* LSL */
518 if (shift != 0) {
519 if (flags)
520 shifter_out_im(var, 32 - shift);
521 tcg_gen_shli_i32(var, var, shift);
523 break;
524 case 1: /* LSR */
525 if (shift == 0) {
526 if (flags) {
527 tcg_gen_shri_i32(var, var, 31);
528 gen_set_CF(var);
530 tcg_gen_movi_i32(var, 0);
531 } else {
532 if (flags)
533 shifter_out_im(var, shift - 1);
534 tcg_gen_shri_i32(var, var, shift);
536 break;
537 case 2: /* ASR */
538 if (shift == 0)
539 shift = 32;
540 if (flags)
541 shifter_out_im(var, shift - 1);
542 if (shift == 32)
543 shift = 31;
544 tcg_gen_sari_i32(var, var, shift);
545 break;
546 case 3: /* ROR/RRX */
547 if (shift != 0) {
548 if (flags)
549 shifter_out_im(var, shift - 1);
550 tcg_gen_rori_i32(var, var, shift); break;
551 } else {
552 TCGv tmp = load_cpu_field(CF);
553 if (flags)
554 shifter_out_im(var, 0);
555 tcg_gen_shri_i32(var, var, 1);
556 tcg_gen_shli_i32(tmp, tmp, 31);
557 tcg_gen_or_i32(var, var, tmp);
558 dead_tmp(tmp);
563 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
564 TCGv shift, int flags)
566 if (flags) {
567 switch (shiftop) {
568 case 0: gen_helper_shl_cc(var, var, shift); break;
569 case 1: gen_helper_shr_cc(var, var, shift); break;
570 case 2: gen_helper_sar_cc(var, var, shift); break;
571 case 3: gen_helper_ror_cc(var, var, shift); break;
573 } else {
574 switch (shiftop) {
575 case 0: gen_helper_shl(var, var, shift); break;
576 case 1: gen_helper_shr(var, var, shift); break;
577 case 2: gen_helper_sar(var, var, shift); break;
578 case 3: gen_helper_ror(var, var, shift); break;
581 dead_tmp(shift);
584 #define PAS_OP(pfx) \
585 switch (op2) { \
586 case 0: gen_pas_helper(glue(pfx,add16)); break; \
587 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
588 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
589 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
590 case 4: gen_pas_helper(glue(pfx,add8)); break; \
591 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
593 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
595 TCGv tmp;
597 switch (op1) {
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
599 case 1:
600 tmp = tcg_temp_new(TCG_TYPE_PTR);
601 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
602 PAS_OP(s)
603 break;
604 case 5:
605 tmp = tcg_temp_new(TCG_TYPE_PTR);
606 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
607 PAS_OP(u)
608 break;
609 #undef gen_pas_helper
610 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
611 case 2:
612 PAS_OP(q);
613 break;
614 case 3:
615 PAS_OP(sh);
616 break;
617 case 6:
618 PAS_OP(uq);
619 break;
620 case 7:
621 PAS_OP(uh);
622 break;
623 #undef gen_pas_helper
626 #undef PAS_OP
628 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
629 #define PAS_OP(pfx) \
630 switch (op2) { \
631 case 0: gen_pas_helper(glue(pfx,add8)); break; \
632 case 1: gen_pas_helper(glue(pfx,add16)); break; \
633 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
634 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
635 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
636 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
638 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
640 TCGv tmp;
642 switch (op1) {
643 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
644 case 0:
645 tmp = tcg_temp_new(TCG_TYPE_PTR);
646 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
647 PAS_OP(s)
648 break;
649 case 4:
650 tmp = tcg_temp_new(TCG_TYPE_PTR);
651 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
652 PAS_OP(u)
653 break;
654 #undef gen_pas_helper
655 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
656 case 1:
657 PAS_OP(q);
658 break;
659 case 2:
660 PAS_OP(sh);
661 break;
662 case 5:
663 PAS_OP(uq);
664 break;
665 case 6:
666 PAS_OP(uh);
667 break;
668 #undef gen_pas_helper
671 #undef PAS_OP
673 static void gen_test_cc(int cc, int label)
675 TCGv tmp;
676 TCGv tmp2;
677 TCGv zero;
678 int inv;
680 zero = tcg_const_i32(0);
681 switch (cc) {
682 case 0: /* eq: Z */
683 tmp = load_cpu_field(ZF);
684 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
685 break;
686 case 1: /* ne: !Z */
687 tmp = load_cpu_field(ZF);
688 tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
689 break;
690 case 2: /* cs: C */
691 tmp = load_cpu_field(CF);
692 tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
693 break;
694 case 3: /* cc: !C */
695 tmp = load_cpu_field(CF);
696 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
697 break;
698 case 4: /* mi: N */
699 tmp = load_cpu_field(NF);
700 tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
701 break;
702 case 5: /* pl: !N */
703 tmp = load_cpu_field(NF);
704 tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
705 break;
706 case 6: /* vs: V */
707 tmp = load_cpu_field(VF);
708 tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
709 break;
710 case 7: /* vc: !V */
711 tmp = load_cpu_field(VF);
712 tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
713 break;
714 case 8: /* hi: C && !Z */
715 inv = gen_new_label();
716 tmp = load_cpu_field(CF);
717 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
718 dead_tmp(tmp);
719 tmp = load_cpu_field(ZF);
720 tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
721 gen_set_label(inv);
722 break;
723 case 9: /* ls: !C || Z */
724 tmp = load_cpu_field(CF);
725 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
726 dead_tmp(tmp);
727 tmp = load_cpu_field(ZF);
728 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
729 break;
730 case 10: /* ge: N == V -> N ^ V == 0 */
731 tmp = load_cpu_field(VF);
732 tmp2 = load_cpu_field(NF);
733 tcg_gen_xor_i32(tmp, tmp, tmp2);
734 dead_tmp(tmp2);
735 tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
736 break;
737 case 11: /* lt: N != V -> N ^ V != 0 */
738 tmp = load_cpu_field(VF);
739 tmp2 = load_cpu_field(NF);
740 tcg_gen_xor_i32(tmp, tmp, tmp2);
741 dead_tmp(tmp2);
742 tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
743 break;
744 case 12: /* gt: !Z && N == V */
745 inv = gen_new_label();
746 tmp = load_cpu_field(ZF);
747 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
748 dead_tmp(tmp);
749 tmp = load_cpu_field(VF);
750 tmp2 = load_cpu_field(NF);
751 tcg_gen_xor_i32(tmp, tmp, tmp2);
752 dead_tmp(tmp2);
753 tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
754 gen_set_label(inv);
755 break;
756 case 13: /* le: Z || N != V */
757 tmp = load_cpu_field(ZF);
758 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
759 dead_tmp(tmp);
760 tmp = load_cpu_field(VF);
761 tmp2 = load_cpu_field(NF);
762 tcg_gen_xor_i32(tmp, tmp, tmp2);
763 dead_tmp(tmp2);
764 tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
765 break;
766 default:
767 fprintf(stderr, "Bad condition code 0x%x\n", cc);
768 abort();
770 dead_tmp(tmp);
773 const uint8_t table_logic_cc[16] = {
774 1, /* and */
775 1, /* xor */
776 0, /* sub */
777 0, /* rsb */
778 0, /* add */
779 0, /* adc */
780 0, /* sbc */
781 0, /* rsc */
782 1, /* andl */
783 1, /* xorl */
784 0, /* cmp */
785 0, /* cmn */
786 1, /* orr */
787 1, /* mov */
788 1, /* bic */
789 1, /* mvn */
792 /* Set PC and Thumb state from an immediate address. */
793 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
795 TCGv tmp;
797 s->is_jmp = DISAS_UPDATE;
798 tmp = new_tmp();
799 if (s->thumb != (addr & 1)) {
800 tcg_gen_movi_i32(tmp, addr & 1);
801 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
803 tcg_gen_movi_i32(tmp, addr & ~1);
804 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
805 dead_tmp(tmp);
808 /* Set PC and Thumb state from var. var is marked as dead. */
809 static inline void gen_bx(DisasContext *s, TCGv var)
811 TCGv tmp;
813 s->is_jmp = DISAS_UPDATE;
814 tmp = new_tmp();
815 tcg_gen_andi_i32(tmp, var, 1);
816 store_cpu_field(tmp, thumb);
817 tcg_gen_andi_i32(var, var, ~1);
818 store_cpu_field(var, regs[15]);
821 /* TODO: This should be removed. Use gen_bx instead. */
822 static inline void gen_bx_T0(DisasContext *s)
824 TCGv tmp = new_tmp();
825 tcg_gen_mov_i32(tmp, cpu_T[0]);
826 gen_bx(s, tmp);
829 #if defined(CONFIG_USER_ONLY)
830 #define gen_ldst(name, s) gen_op_##name##_raw()
831 #else
832 #define gen_ldst(name, s) do { \
833 s->is_mem = 1; \
834 if (IS_USER(s)) \
835 gen_op_##name##_user(); \
836 else \
837 gen_op_##name##_kernel(); \
838 } while (0)
839 #endif
840 static inline TCGv gen_ld8s(TCGv addr, int index)
842 TCGv tmp = new_tmp();
843 tcg_gen_qemu_ld8s(tmp, addr, index);
844 return tmp;
846 static inline TCGv gen_ld8u(TCGv addr, int index)
848 TCGv tmp = new_tmp();
849 tcg_gen_qemu_ld8u(tmp, addr, index);
850 return tmp;
852 static inline TCGv gen_ld16s(TCGv addr, int index)
854 TCGv tmp = new_tmp();
855 tcg_gen_qemu_ld16s(tmp, addr, index);
856 return tmp;
858 static inline TCGv gen_ld16u(TCGv addr, int index)
860 TCGv tmp = new_tmp();
861 tcg_gen_qemu_ld16u(tmp, addr, index);
862 return tmp;
864 static inline TCGv gen_ld32(TCGv addr, int index)
866 TCGv tmp = new_tmp();
867 tcg_gen_qemu_ld32u(tmp, addr, index);
868 return tmp;
870 static inline void gen_st8(TCGv val, TCGv addr, int index)
872 tcg_gen_qemu_st8(val, addr, index);
873 dead_tmp(val);
875 static inline void gen_st16(TCGv val, TCGv addr, int index)
877 tcg_gen_qemu_st16(val, addr, index);
878 dead_tmp(val);
880 static inline void gen_st32(TCGv val, TCGv addr, int index)
882 tcg_gen_qemu_st32(val, addr, index);
883 dead_tmp(val);
886 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
888 load_reg_var(s, cpu_T[0], reg);
891 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
893 load_reg_var(s, cpu_T[1], reg);
896 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
898 load_reg_var(s, cpu_T[2], reg);
901 static inline void gen_set_pc_im(uint32_t val)
903 TCGv tmp = new_tmp();
904 tcg_gen_movi_i32(tmp, val);
905 store_cpu_field(tmp, regs[15]);
908 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
910 TCGv tmp;
911 if (reg == 15) {
912 tmp = new_tmp();
913 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
914 } else {
915 tmp = cpu_T[t];
917 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
918 if (reg == 15) {
919 dead_tmp(tmp);
920 s->is_jmp = DISAS_JUMP;
924 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
926 gen_movl_reg_TN(s, reg, 0);
929 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
931 gen_movl_reg_TN(s, reg, 1);
934 /* Force a TB lookup after an instruction that changes the CPU state. */
935 static inline void gen_lookup_tb(DisasContext *s)
937 gen_op_movl_T0_im(s->pc);
938 gen_movl_reg_T0(s, 15);
939 s->is_jmp = DISAS_UPDATE;
942 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
943 TCGv var)
945 int val, rm, shift, shiftop;
946 TCGv offset;
948 if (!(insn & (1 << 25))) {
949 /* immediate */
950 val = insn & 0xfff;
951 if (!(insn & (1 << 23)))
952 val = -val;
953 if (val != 0)
954 tcg_gen_addi_i32(var, var, val);
955 } else {
956 /* shift/register */
957 rm = (insn) & 0xf;
958 shift = (insn >> 7) & 0x1f;
959 shiftop = (insn >> 5) & 3;
960 offset = load_reg(s, rm);
961 gen_arm_shift_im(offset, shiftop, shift, 0);
962 if (!(insn & (1 << 23)))
963 tcg_gen_sub_i32(var, var, offset);
964 else
965 tcg_gen_add_i32(var, var, offset);
966 dead_tmp(offset);
970 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
971 int extra, TCGv var)
973 int val, rm;
974 TCGv offset;
976 if (insn & (1 << 22)) {
977 /* immediate */
978 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
979 if (!(insn & (1 << 23)))
980 val = -val;
981 val += extra;
982 if (val != 0)
983 tcg_gen_addi_i32(var, var, val);
984 } else {
985 /* register */
986 if (extra)
987 tcg_gen_addi_i32(var, var, extra);
988 rm = (insn) & 0xf;
989 offset = load_reg(s, rm);
990 if (!(insn & (1 << 23)))
991 tcg_gen_sub_i32(var, var, offset);
992 else
993 tcg_gen_add_i32(var, var, offset);
994 dead_tmp(offset);
998 #define VFP_OP2(name) \
999 static inline void gen_vfp_##name(int dp) \
1001 if (dp) \
1002 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
1003 else \
1004 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1007 #define VFP_OP1(name) \
1008 static inline void gen_vfp_##name(int dp, int arg) \
1010 if (dp) \
1011 gen_op_vfp_##name##d(arg); \
1012 else \
1013 gen_op_vfp_##name##s(arg); \
1016 VFP_OP2(add)
1017 VFP_OP2(sub)
1018 VFP_OP2(mul)
1019 VFP_OP2(div)
1021 #undef VFP_OP2
1023 static inline void gen_vfp_abs(int dp)
1025 if (dp)
1026 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1027 else
1028 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1031 static inline void gen_vfp_neg(int dp)
1033 if (dp)
1034 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1035 else
1036 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1039 static inline void gen_vfp_sqrt(int dp)
1041 if (dp)
1042 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1043 else
1044 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1047 static inline void gen_vfp_cmp(int dp)
1049 if (dp)
1050 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1051 else
1052 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1055 static inline void gen_vfp_cmpe(int dp)
1057 if (dp)
1058 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1059 else
1060 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1063 static inline void gen_vfp_F1_ld0(int dp)
1065 if (dp)
1066 tcg_gen_movi_i64(cpu_F1d, 0);
1067 else
1068 tcg_gen_movi_i32(cpu_F1s, 0);
1071 static inline void gen_vfp_uito(int dp)
1073 if (dp)
1074 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1075 else
1076 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1079 static inline void gen_vfp_sito(int dp)
1081 if (dp)
1082 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1083 else
1084 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1087 static inline void gen_vfp_toui(int dp)
1089 if (dp)
1090 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1091 else
1092 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1095 static inline void gen_vfp_touiz(int dp)
1097 if (dp)
1098 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1099 else
1100 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1103 static inline void gen_vfp_tosi(int dp)
1105 if (dp)
1106 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1107 else
1108 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1111 static inline void gen_vfp_tosiz(int dp)
1113 if (dp)
1114 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1115 else
1116 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1119 #define VFP_GEN_FIX(name) \
1120 static inline void gen_vfp_##name(int dp, int shift) \
1122 if (dp) \
1123 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1124 else \
1125 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1127 VFP_GEN_FIX(tosh)
1128 VFP_GEN_FIX(tosl)
1129 VFP_GEN_FIX(touh)
1130 VFP_GEN_FIX(toul)
1131 VFP_GEN_FIX(shto)
1132 VFP_GEN_FIX(slto)
1133 VFP_GEN_FIX(uhto)
1134 VFP_GEN_FIX(ulto)
1135 #undef VFP_GEN_FIX
1137 static inline void gen_vfp_ld(DisasContext *s, int dp)
1139 if (dp)
1140 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1141 else
1142 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1145 static inline void gen_vfp_st(DisasContext *s, int dp)
1147 if (dp)
1148 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1149 else
1150 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1153 static inline long
1154 vfp_reg_offset (int dp, int reg)
1156 if (dp)
1157 return offsetof(CPUARMState, vfp.regs[reg]);
1158 else if (reg & 1) {
1159 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1160 + offsetof(CPU_DoubleU, l.upper);
1161 } else {
1162 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1163 + offsetof(CPU_DoubleU, l.lower);
1167 /* Return the offset of a 32-bit piece of a NEON register.
1168 zero is the least significant end of the register. */
1169 static inline long
1170 neon_reg_offset (int reg, int n)
1172 int sreg;
1173 sreg = reg * 2 + n;
1174 return vfp_reg_offset(0, sreg);
1177 /* FIXME: Remove these. */
1178 #define neon_T0 cpu_T[0]
1179 #define neon_T1 cpu_T[1]
1180 #define NEON_GET_REG(T, reg, n) \
1181 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1182 #define NEON_SET_REG(T, reg, n) \
1183 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1185 static TCGv neon_load_reg(int reg, int pass)
1187 TCGv tmp = new_tmp();
1188 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1189 return tmp;
1192 static void neon_store_reg(int reg, int pass, TCGv var)
1194 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1195 dead_tmp(var);
1198 static inline void neon_load_reg64(TCGv var, int reg)
1200 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1203 static inline void neon_store_reg64(TCGv var, int reg)
1205 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1208 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1209 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1210 #define tcg_gen_st_f32 tcg_gen_st_i32
1211 #define tcg_gen_st_f64 tcg_gen_st_i64
1213 static inline void gen_mov_F0_vreg(int dp, int reg)
1215 if (dp)
1216 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1217 else
1218 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1221 static inline void gen_mov_F1_vreg(int dp, int reg)
1223 if (dp)
1224 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1225 else
1226 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1229 static inline void gen_mov_vreg_F0(int dp, int reg)
1231 if (dp)
1232 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1233 else
1234 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1237 #define ARM_CP_RW_BIT (1 << 20)
1239 static inline void iwmmxt_load_reg(TCGv var, int reg)
1241 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1244 static inline void iwmmxt_store_reg(TCGv var, int reg)
1246 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1249 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1251 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1254 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1256 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1259 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1261 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1264 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1266 iwmmxt_store_reg(cpu_M0, rn);
1269 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1271 iwmmxt_load_reg(cpu_M0, rn);
1274 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1276 iwmmxt_load_reg(cpu_V1, rn);
1277 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1280 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1282 iwmmxt_load_reg(cpu_V1, rn);
1283 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1286 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1288 iwmmxt_load_reg(cpu_V1, rn);
1289 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1292 #define IWMMXT_OP(name) \
1293 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1295 iwmmxt_load_reg(cpu_V1, rn); \
1296 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1299 #define IWMMXT_OP_ENV(name) \
1300 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1302 iwmmxt_load_reg(cpu_V1, rn); \
1303 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1306 #define IWMMXT_OP_ENV_SIZE(name) \
1307 IWMMXT_OP_ENV(name##b) \
1308 IWMMXT_OP_ENV(name##w) \
1309 IWMMXT_OP_ENV(name##l)
1311 #define IWMMXT_OP_ENV1(name) \
1312 static inline void gen_op_iwmmxt_##name##_M0(void) \
1314 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1317 IWMMXT_OP(maddsq)
1318 IWMMXT_OP(madduq)
1319 IWMMXT_OP(sadb)
1320 IWMMXT_OP(sadw)
1321 IWMMXT_OP(mulslw)
1322 IWMMXT_OP(mulshw)
1323 IWMMXT_OP(mululw)
1324 IWMMXT_OP(muluhw)
1325 IWMMXT_OP(macsw)
1326 IWMMXT_OP(macuw)
1328 IWMMXT_OP_ENV_SIZE(unpackl)
1329 IWMMXT_OP_ENV_SIZE(unpackh)
1331 IWMMXT_OP_ENV1(unpacklub)
1332 IWMMXT_OP_ENV1(unpackluw)
1333 IWMMXT_OP_ENV1(unpacklul)
1334 IWMMXT_OP_ENV1(unpackhub)
1335 IWMMXT_OP_ENV1(unpackhuw)
1336 IWMMXT_OP_ENV1(unpackhul)
1337 IWMMXT_OP_ENV1(unpacklsb)
1338 IWMMXT_OP_ENV1(unpacklsw)
1339 IWMMXT_OP_ENV1(unpacklsl)
1340 IWMMXT_OP_ENV1(unpackhsb)
1341 IWMMXT_OP_ENV1(unpackhsw)
1342 IWMMXT_OP_ENV1(unpackhsl)
1344 IWMMXT_OP_ENV_SIZE(cmpeq)
1345 IWMMXT_OP_ENV_SIZE(cmpgtu)
1346 IWMMXT_OP_ENV_SIZE(cmpgts)
1348 IWMMXT_OP_ENV_SIZE(mins)
1349 IWMMXT_OP_ENV_SIZE(minu)
1350 IWMMXT_OP_ENV_SIZE(maxs)
1351 IWMMXT_OP_ENV_SIZE(maxu)
1353 IWMMXT_OP_ENV_SIZE(subn)
1354 IWMMXT_OP_ENV_SIZE(addn)
1355 IWMMXT_OP_ENV_SIZE(subu)
1356 IWMMXT_OP_ENV_SIZE(addu)
1357 IWMMXT_OP_ENV_SIZE(subs)
1358 IWMMXT_OP_ENV_SIZE(adds)
1360 IWMMXT_OP_ENV(avgb0)
1361 IWMMXT_OP_ENV(avgb1)
1362 IWMMXT_OP_ENV(avgw0)
1363 IWMMXT_OP_ENV(avgw1)
1365 IWMMXT_OP(msadb)
1367 IWMMXT_OP_ENV(packuw)
1368 IWMMXT_OP_ENV(packul)
1369 IWMMXT_OP_ENV(packuq)
1370 IWMMXT_OP_ENV(packsw)
1371 IWMMXT_OP_ENV(packsl)
1372 IWMMXT_OP_ENV(packsq)
1374 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1376 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1379 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1381 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1384 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1386 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1389 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1391 iwmmxt_load_reg(cpu_V1, rn);
1392 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1395 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1397 TCGv tmp = tcg_const_i32(shift);
1398 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1401 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1403 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1404 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1405 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1408 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1410 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1411 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1412 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1415 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1417 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1418 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1419 if (mask != ~0u)
1420 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1423 static void gen_op_iwmmxt_set_mup(void)
1425 TCGv tmp;
1426 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1427 tcg_gen_ori_i32(tmp, tmp, 2);
1428 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1431 static void gen_op_iwmmxt_set_cup(void)
1433 TCGv tmp;
1434 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1435 tcg_gen_ori_i32(tmp, tmp, 1);
1436 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1439 static void gen_op_iwmmxt_setpsr_nz(void)
1441 TCGv tmp = new_tmp();
1442 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1443 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1446 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1448 iwmmxt_load_reg(cpu_V1, rn);
1449 tcg_gen_andi_i64(cpu_V1, cpu_V1, 0xffffffffu);
1450 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1454 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1456 iwmmxt_load_reg(cpu_V0, rn);
1457 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1458 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1459 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1462 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1464 tcg_gen_extu_i32_i64(cpu_V0, cpu_T[0]);
1465 tcg_gen_extu_i32_i64(cpu_V1, cpu_T[0]);
1466 tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
1467 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
1468 iwmmxt_store_reg(cpu_V0, rn);
1471 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1473 int rd;
1474 uint32_t offset;
1476 rd = (insn >> 16) & 0xf;
1477 gen_movl_T1_reg(s, rd);
1479 offset = (insn & 0xff) << ((insn >> 7) & 2);
1480 if (insn & (1 << 24)) {
1481 /* Pre indexed */
1482 if (insn & (1 << 23))
1483 gen_op_addl_T1_im(offset);
1484 else
1485 gen_op_addl_T1_im(-offset);
1487 if (insn & (1 << 21))
1488 gen_movl_reg_T1(s, rd);
1489 } else if (insn & (1 << 21)) {
1490 /* Post indexed */
1491 if (insn & (1 << 23))
1492 gen_op_movl_T0_im(offset);
1493 else
1494 gen_op_movl_T0_im(- offset);
1495 gen_op_addl_T0_T1();
1496 gen_movl_reg_T0(s, rd);
1497 } else if (!(insn & (1 << 23)))
1498 return 1;
1499 return 0;
1502 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1504 int rd = (insn >> 0) & 0xf;
1506 if (insn & (1 << 8))
1507 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1508 return 1;
1509 else
1510 gen_op_iwmmxt_movl_T0_wCx(rd);
1511 else
1512 gen_iwmmxt_movl_T0_T1_wRn(rd);
1514 gen_op_movl_T1_im(mask);
1515 gen_op_andl_T0_T1();
1516 return 0;
1519 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1520 (ie. an undefined instruction). */
1521 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1523 int rd, wrd;
1524 int rdhi, rdlo, rd0, rd1, i;
1525 TCGv tmp;
1527 if ((insn & 0x0e000e00) == 0x0c000000) {
1528 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1529 wrd = insn & 0xf;
1530 rdlo = (insn >> 12) & 0xf;
1531 rdhi = (insn >> 16) & 0xf;
1532 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1533 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1534 gen_movl_reg_T0(s, rdlo);
1535 gen_movl_reg_T1(s, rdhi);
1536 } else { /* TMCRR */
1537 gen_movl_T0_reg(s, rdlo);
1538 gen_movl_T1_reg(s, rdhi);
1539 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1540 gen_op_iwmmxt_set_mup();
1542 return 0;
1545 wrd = (insn >> 12) & 0xf;
1546 if (gen_iwmmxt_address(s, insn))
1547 return 1;
1548 if (insn & ARM_CP_RW_BIT) {
1549 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1550 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1551 tcg_gen_mov_i32(cpu_T[0], tmp);
1552 dead_tmp(tmp);
1553 gen_op_iwmmxt_movl_wCx_T0(wrd);
1554 } else {
1555 i = 1;
1556 if (insn & (1 << 8)) {
1557 if (insn & (1 << 22)) { /* WLDRD */
1558 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1559 i = 0;
1560 } else { /* WLDRW wRd */
1561 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1563 } else {
1564 if (insn & (1 << 22)) { /* WLDRH */
1565 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1566 } else { /* WLDRB */
1567 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1570 if (i) {
1571 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1572 dead_tmp(tmp);
1574 gen_op_iwmmxt_movq_wRn_M0(wrd);
1576 } else {
1577 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1578 gen_op_iwmmxt_movl_T0_wCx(wrd);
1579 tmp = new_tmp();
1580 tcg_gen_mov_i32(tmp, cpu_T[0]);
1581 gen_st32(tmp, cpu_T[1], IS_USER(s));
1582 } else {
1583 gen_op_iwmmxt_movq_M0_wRn(wrd);
1584 tmp = new_tmp();
1585 if (insn & (1 << 8)) {
1586 if (insn & (1 << 22)) { /* WSTRD */
1587 dead_tmp(tmp);
1588 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1589 } else { /* WSTRW wRd */
1590 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1591 gen_st32(tmp, cpu_T[1], IS_USER(s));
1593 } else {
1594 if (insn & (1 << 22)) { /* WSTRH */
1595 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1596 gen_st16(tmp, cpu_T[1], IS_USER(s));
1597 } else { /* WSTRB */
1598 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1599 gen_st8(tmp, cpu_T[1], IS_USER(s));
1604 return 0;
1607 if ((insn & 0x0f000000) != 0x0e000000)
1608 return 1;
1610 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1611 case 0x000: /* WOR */
1612 wrd = (insn >> 12) & 0xf;
1613 rd0 = (insn >> 0) & 0xf;
1614 rd1 = (insn >> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0);
1616 gen_op_iwmmxt_orq_M0_wRn(rd1);
1617 gen_op_iwmmxt_setpsr_nz();
1618 gen_op_iwmmxt_movq_wRn_M0(wrd);
1619 gen_op_iwmmxt_set_mup();
1620 gen_op_iwmmxt_set_cup();
1621 break;
1622 case 0x011: /* TMCR */
1623 if (insn & 0xf)
1624 return 1;
1625 rd = (insn >> 12) & 0xf;
1626 wrd = (insn >> 16) & 0xf;
1627 switch (wrd) {
1628 case ARM_IWMMXT_wCID:
1629 case ARM_IWMMXT_wCASF:
1630 break;
1631 case ARM_IWMMXT_wCon:
1632 gen_op_iwmmxt_set_cup();
1633 /* Fall through. */
1634 case ARM_IWMMXT_wCSSF:
1635 gen_op_iwmmxt_movl_T0_wCx(wrd);
1636 gen_movl_T1_reg(s, rd);
1637 gen_op_bicl_T0_T1();
1638 gen_op_iwmmxt_movl_wCx_T0(wrd);
1639 break;
1640 case ARM_IWMMXT_wCGR0:
1641 case ARM_IWMMXT_wCGR1:
1642 case ARM_IWMMXT_wCGR2:
1643 case ARM_IWMMXT_wCGR3:
1644 gen_op_iwmmxt_set_cup();
1645 gen_movl_reg_T0(s, rd);
1646 gen_op_iwmmxt_movl_wCx_T0(wrd);
1647 break;
1648 default:
1649 return 1;
1651 break;
1652 case 0x100: /* WXOR */
1653 wrd = (insn >> 12) & 0xf;
1654 rd0 = (insn >> 0) & 0xf;
1655 rd1 = (insn >> 16) & 0xf;
1656 gen_op_iwmmxt_movq_M0_wRn(rd0);
1657 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1658 gen_op_iwmmxt_setpsr_nz();
1659 gen_op_iwmmxt_movq_wRn_M0(wrd);
1660 gen_op_iwmmxt_set_mup();
1661 gen_op_iwmmxt_set_cup();
1662 break;
1663 case 0x111: /* TMRC */
1664 if (insn & 0xf)
1665 return 1;
1666 rd = (insn >> 12) & 0xf;
1667 wrd = (insn >> 16) & 0xf;
1668 gen_op_iwmmxt_movl_T0_wCx(wrd);
1669 gen_movl_reg_T0(s, rd);
1670 break;
1671 case 0x300: /* WANDN */
1672 wrd = (insn >> 12) & 0xf;
1673 rd0 = (insn >> 0) & 0xf;
1674 rd1 = (insn >> 16) & 0xf;
1675 gen_op_iwmmxt_movq_M0_wRn(rd0);
1676 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1677 gen_op_iwmmxt_andq_M0_wRn(rd1);
1678 gen_op_iwmmxt_setpsr_nz();
1679 gen_op_iwmmxt_movq_wRn_M0(wrd);
1680 gen_op_iwmmxt_set_mup();
1681 gen_op_iwmmxt_set_cup();
1682 break;
1683 case 0x200: /* WAND */
1684 wrd = (insn >> 12) & 0xf;
1685 rd0 = (insn >> 0) & 0xf;
1686 rd1 = (insn >> 16) & 0xf;
1687 gen_op_iwmmxt_movq_M0_wRn(rd0);
1688 gen_op_iwmmxt_andq_M0_wRn(rd1);
1689 gen_op_iwmmxt_setpsr_nz();
1690 gen_op_iwmmxt_movq_wRn_M0(wrd);
1691 gen_op_iwmmxt_set_mup();
1692 gen_op_iwmmxt_set_cup();
1693 break;
1694 case 0x810: case 0xa10: /* WMADD */
1695 wrd = (insn >> 12) & 0xf;
1696 rd0 = (insn >> 0) & 0xf;
1697 rd1 = (insn >> 16) & 0xf;
1698 gen_op_iwmmxt_movq_M0_wRn(rd0);
1699 if (insn & (1 << 21))
1700 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1701 else
1702 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1703 gen_op_iwmmxt_movq_wRn_M0(wrd);
1704 gen_op_iwmmxt_set_mup();
1705 break;
1706 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1707 wrd = (insn >> 12) & 0xf;
1708 rd0 = (insn >> 16) & 0xf;
1709 rd1 = (insn >> 0) & 0xf;
1710 gen_op_iwmmxt_movq_M0_wRn(rd0);
1711 switch ((insn >> 22) & 3) {
1712 case 0:
1713 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1714 break;
1715 case 1:
1716 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1717 break;
1718 case 2:
1719 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1720 break;
1721 case 3:
1722 return 1;
1724 gen_op_iwmmxt_movq_wRn_M0(wrd);
1725 gen_op_iwmmxt_set_mup();
1726 gen_op_iwmmxt_set_cup();
1727 break;
1728 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1729 wrd = (insn >> 12) & 0xf;
1730 rd0 = (insn >> 16) & 0xf;
1731 rd1 = (insn >> 0) & 0xf;
1732 gen_op_iwmmxt_movq_M0_wRn(rd0);
1733 switch ((insn >> 22) & 3) {
1734 case 0:
1735 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1736 break;
1737 case 1:
1738 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1739 break;
1740 case 2:
1741 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1742 break;
1743 case 3:
1744 return 1;
1746 gen_op_iwmmxt_movq_wRn_M0(wrd);
1747 gen_op_iwmmxt_set_mup();
1748 gen_op_iwmmxt_set_cup();
1749 break;
1750 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
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 << 22))
1756 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1757 else
1758 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1759 if (!(insn & (1 << 20)))
1760 gen_op_iwmmxt_addl_M0_wRn(wrd);
1761 gen_op_iwmmxt_movq_wRn_M0(wrd);
1762 gen_op_iwmmxt_set_mup();
1763 break;
1764 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1765 wrd = (insn >> 12) & 0xf;
1766 rd0 = (insn >> 16) & 0xf;
1767 rd1 = (insn >> 0) & 0xf;
1768 gen_op_iwmmxt_movq_M0_wRn(rd0);
1769 if (insn & (1 << 21)) {
1770 if (insn & (1 << 20))
1771 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1772 else
1773 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1774 } else {
1775 if (insn & (1 << 20))
1776 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1777 else
1778 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd);
1781 gen_op_iwmmxt_set_mup();
1782 break;
1783 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1784 wrd = (insn >> 12) & 0xf;
1785 rd0 = (insn >> 16) & 0xf;
1786 rd1 = (insn >> 0) & 0xf;
1787 gen_op_iwmmxt_movq_M0_wRn(rd0);
1788 if (insn & (1 << 21))
1789 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1790 else
1791 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1792 if (!(insn & (1 << 20))) {
1793 iwmmxt_load_reg(cpu_V1, wrd);
1794 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1796 gen_op_iwmmxt_movq_wRn_M0(wrd);
1797 gen_op_iwmmxt_set_mup();
1798 break;
1799 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1800 wrd = (insn >> 12) & 0xf;
1801 rd0 = (insn >> 16) & 0xf;
1802 rd1 = (insn >> 0) & 0xf;
1803 gen_op_iwmmxt_movq_M0_wRn(rd0);
1804 switch ((insn >> 22) & 3) {
1805 case 0:
1806 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1807 break;
1808 case 1:
1809 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1810 break;
1811 case 2:
1812 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1813 break;
1814 case 3:
1815 return 1;
1817 gen_op_iwmmxt_movq_wRn_M0(wrd);
1818 gen_op_iwmmxt_set_mup();
1819 gen_op_iwmmxt_set_cup();
1820 break;
1821 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1822 wrd = (insn >> 12) & 0xf;
1823 rd0 = (insn >> 16) & 0xf;
1824 rd1 = (insn >> 0) & 0xf;
1825 gen_op_iwmmxt_movq_M0_wRn(rd0);
1826 if (insn & (1 << 22)) {
1827 if (insn & (1 << 20))
1828 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1829 else
1830 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1831 } else {
1832 if (insn & (1 << 20))
1833 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1834 else
1835 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1837 gen_op_iwmmxt_movq_wRn_M0(wrd);
1838 gen_op_iwmmxt_set_mup();
1839 gen_op_iwmmxt_set_cup();
1840 break;
1841 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1842 wrd = (insn >> 12) & 0xf;
1843 rd0 = (insn >> 16) & 0xf;
1844 rd1 = (insn >> 0) & 0xf;
1845 gen_op_iwmmxt_movq_M0_wRn(rd0);
1846 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1847 gen_op_movl_T1_im(7);
1848 gen_op_andl_T0_T1();
1849 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1850 gen_op_iwmmxt_movq_wRn_M0(wrd);
1851 gen_op_iwmmxt_set_mup();
1852 break;
1853 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1854 rd = (insn >> 12) & 0xf;
1855 wrd = (insn >> 16) & 0xf;
1856 gen_movl_T0_reg(s, rd);
1857 gen_op_iwmmxt_movq_M0_wRn(wrd);
1858 switch ((insn >> 6) & 3) {
1859 case 0:
1860 gen_op_movl_T1_im(0xff);
1861 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1862 break;
1863 case 1:
1864 gen_op_movl_T1_im(0xffff);
1865 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1866 break;
1867 case 2:
1868 gen_op_movl_T1_im(0xffffffff);
1869 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1870 break;
1871 case 3:
1872 return 1;
1874 gen_op_iwmmxt_movq_wRn_M0(wrd);
1875 gen_op_iwmmxt_set_mup();
1876 break;
1877 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1878 rd = (insn >> 12) & 0xf;
1879 wrd = (insn >> 16) & 0xf;
1880 if (rd == 15)
1881 return 1;
1882 gen_op_iwmmxt_movq_M0_wRn(wrd);
1883 switch ((insn >> 22) & 3) {
1884 case 0:
1885 if (insn & 8)
1886 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1887 else {
1888 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1890 break;
1891 case 1:
1892 if (insn & 8)
1893 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1894 else {
1895 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1897 break;
1898 case 2:
1899 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1900 break;
1901 case 3:
1902 return 1;
1904 gen_movl_reg_T0(s, rd);
1905 break;
1906 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1907 if ((insn & 0x000ff008) != 0x0003f000)
1908 return 1;
1909 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1910 switch ((insn >> 22) & 3) {
1911 case 0:
1912 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1913 break;
1914 case 1:
1915 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1916 break;
1917 case 2:
1918 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1919 break;
1920 case 3:
1921 return 1;
1923 gen_op_shll_T1_im(28);
1924 gen_set_nzcv(cpu_T[1]);
1925 break;
1926 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1927 rd = (insn >> 12) & 0xf;
1928 wrd = (insn >> 16) & 0xf;
1929 gen_movl_T0_reg(s, rd);
1930 switch ((insn >> 6) & 3) {
1931 case 0:
1932 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1933 break;
1934 case 1:
1935 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1936 break;
1937 case 2:
1938 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1939 break;
1940 case 3:
1941 return 1;
1943 gen_op_iwmmxt_movq_wRn_M0(wrd);
1944 gen_op_iwmmxt_set_mup();
1945 break;
1946 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1947 if ((insn & 0x000ff00f) != 0x0003f000)
1948 return 1;
1949 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1950 switch ((insn >> 22) & 3) {
1951 case 0:
1952 for (i = 0; i < 7; i ++) {
1953 gen_op_shll_T1_im(4);
1954 gen_op_andl_T0_T1();
1956 break;
1957 case 1:
1958 for (i = 0; i < 3; i ++) {
1959 gen_op_shll_T1_im(8);
1960 gen_op_andl_T0_T1();
1962 break;
1963 case 2:
1964 gen_op_shll_T1_im(16);
1965 gen_op_andl_T0_T1();
1966 break;
1967 case 3:
1968 return 1;
1970 gen_set_nzcv(cpu_T[0]);
1971 break;
1972 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1973 wrd = (insn >> 12) & 0xf;
1974 rd0 = (insn >> 16) & 0xf;
1975 gen_op_iwmmxt_movq_M0_wRn(rd0);
1976 switch ((insn >> 22) & 3) {
1977 case 0:
1978 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1979 break;
1980 case 1:
1981 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1982 break;
1983 case 2:
1984 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1985 break;
1986 case 3:
1987 return 1;
1989 gen_op_iwmmxt_movq_wRn_M0(wrd);
1990 gen_op_iwmmxt_set_mup();
1991 break;
1992 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1993 if ((insn & 0x000ff00f) != 0x0003f000)
1994 return 1;
1995 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1996 switch ((insn >> 22) & 3) {
1997 case 0:
1998 for (i = 0; i < 7; i ++) {
1999 gen_op_shll_T1_im(4);
2000 gen_op_orl_T0_T1();
2002 break;
2003 case 1:
2004 for (i = 0; i < 3; i ++) {
2005 gen_op_shll_T1_im(8);
2006 gen_op_orl_T0_T1();
2008 break;
2009 case 2:
2010 gen_op_shll_T1_im(16);
2011 gen_op_orl_T0_T1();
2012 break;
2013 case 3:
2014 return 1;
2016 gen_set_nzcv(cpu_T[0]);
2017 break;
2018 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2019 rd = (insn >> 12) & 0xf;
2020 rd0 = (insn >> 16) & 0xf;
2021 if ((insn & 0xf) != 0)
2022 return 1;
2023 gen_op_iwmmxt_movq_M0_wRn(rd0);
2024 switch ((insn >> 22) & 3) {
2025 case 0:
2026 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2027 break;
2028 case 1:
2029 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2030 break;
2031 case 2:
2032 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2033 break;
2034 case 3:
2035 return 1;
2037 gen_movl_reg_T0(s, rd);
2038 break;
2039 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2040 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2041 wrd = (insn >> 12) & 0xf;
2042 rd0 = (insn >> 16) & 0xf;
2043 rd1 = (insn >> 0) & 0xf;
2044 gen_op_iwmmxt_movq_M0_wRn(rd0);
2045 switch ((insn >> 22) & 3) {
2046 case 0:
2047 if (insn & (1 << 21))
2048 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2049 else
2050 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2051 break;
2052 case 1:
2053 if (insn & (1 << 21))
2054 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2055 else
2056 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2057 break;
2058 case 2:
2059 if (insn & (1 << 21))
2060 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2061 else
2062 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2063 break;
2064 case 3:
2065 return 1;
2067 gen_op_iwmmxt_movq_wRn_M0(wrd);
2068 gen_op_iwmmxt_set_mup();
2069 gen_op_iwmmxt_set_cup();
2070 break;
2071 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2072 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2073 wrd = (insn >> 12) & 0xf;
2074 rd0 = (insn >> 16) & 0xf;
2075 gen_op_iwmmxt_movq_M0_wRn(rd0);
2076 switch ((insn >> 22) & 3) {
2077 case 0:
2078 if (insn & (1 << 21))
2079 gen_op_iwmmxt_unpacklsb_M0();
2080 else
2081 gen_op_iwmmxt_unpacklub_M0();
2082 break;
2083 case 1:
2084 if (insn & (1 << 21))
2085 gen_op_iwmmxt_unpacklsw_M0();
2086 else
2087 gen_op_iwmmxt_unpackluw_M0();
2088 break;
2089 case 2:
2090 if (insn & (1 << 21))
2091 gen_op_iwmmxt_unpacklsl_M0();
2092 else
2093 gen_op_iwmmxt_unpacklul_M0();
2094 break;
2095 case 3:
2096 return 1;
2098 gen_op_iwmmxt_movq_wRn_M0(wrd);
2099 gen_op_iwmmxt_set_mup();
2100 gen_op_iwmmxt_set_cup();
2101 break;
2102 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2103 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2104 wrd = (insn >> 12) & 0xf;
2105 rd0 = (insn >> 16) & 0xf;
2106 gen_op_iwmmxt_movq_M0_wRn(rd0);
2107 switch ((insn >> 22) & 3) {
2108 case 0:
2109 if (insn & (1 << 21))
2110 gen_op_iwmmxt_unpackhsb_M0();
2111 else
2112 gen_op_iwmmxt_unpackhub_M0();
2113 break;
2114 case 1:
2115 if (insn & (1 << 21))
2116 gen_op_iwmmxt_unpackhsw_M0();
2117 else
2118 gen_op_iwmmxt_unpackhuw_M0();
2119 break;
2120 case 2:
2121 if (insn & (1 << 21))
2122 gen_op_iwmmxt_unpackhsl_M0();
2123 else
2124 gen_op_iwmmxt_unpackhul_M0();
2125 break;
2126 case 3:
2127 return 1;
2129 gen_op_iwmmxt_movq_wRn_M0(wrd);
2130 gen_op_iwmmxt_set_mup();
2131 gen_op_iwmmxt_set_cup();
2132 break;
2133 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2134 case 0x214: case 0x614: case 0xa14: case 0xe14:
2135 wrd = (insn >> 12) & 0xf;
2136 rd0 = (insn >> 16) & 0xf;
2137 gen_op_iwmmxt_movq_M0_wRn(rd0);
2138 if (gen_iwmmxt_shift(insn, 0xff))
2139 return 1;
2140 switch ((insn >> 22) & 3) {
2141 case 0:
2142 return 1;
2143 case 1:
2144 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2145 break;
2146 case 2:
2147 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2148 break;
2149 case 3:
2150 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2151 break;
2153 gen_op_iwmmxt_movq_wRn_M0(wrd);
2154 gen_op_iwmmxt_set_mup();
2155 gen_op_iwmmxt_set_cup();
2156 break;
2157 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2158 case 0x014: case 0x414: case 0x814: case 0xc14:
2159 wrd = (insn >> 12) & 0xf;
2160 rd0 = (insn >> 16) & 0xf;
2161 gen_op_iwmmxt_movq_M0_wRn(rd0);
2162 if (gen_iwmmxt_shift(insn, 0xff))
2163 return 1;
2164 switch ((insn >> 22) & 3) {
2165 case 0:
2166 return 1;
2167 case 1:
2168 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2169 break;
2170 case 2:
2171 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2172 break;
2173 case 3:
2174 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2175 break;
2177 gen_op_iwmmxt_movq_wRn_M0(wrd);
2178 gen_op_iwmmxt_set_mup();
2179 gen_op_iwmmxt_set_cup();
2180 break;
2181 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2182 case 0x114: case 0x514: case 0x914: case 0xd14:
2183 wrd = (insn >> 12) & 0xf;
2184 rd0 = (insn >> 16) & 0xf;
2185 gen_op_iwmmxt_movq_M0_wRn(rd0);
2186 if (gen_iwmmxt_shift(insn, 0xff))
2187 return 1;
2188 switch ((insn >> 22) & 3) {
2189 case 0:
2190 return 1;
2191 case 1:
2192 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2193 break;
2194 case 2:
2195 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2196 break;
2197 case 3:
2198 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2199 break;
2201 gen_op_iwmmxt_movq_wRn_M0(wrd);
2202 gen_op_iwmmxt_set_mup();
2203 gen_op_iwmmxt_set_cup();
2204 break;
2205 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2206 case 0x314: case 0x714: case 0xb14: case 0xf14:
2207 wrd = (insn >> 12) & 0xf;
2208 rd0 = (insn >> 16) & 0xf;
2209 gen_op_iwmmxt_movq_M0_wRn(rd0);
2210 switch ((insn >> 22) & 3) {
2211 case 0:
2212 return 1;
2213 case 1:
2214 if (gen_iwmmxt_shift(insn, 0xf))
2215 return 1;
2216 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2217 break;
2218 case 2:
2219 if (gen_iwmmxt_shift(insn, 0x1f))
2220 return 1;
2221 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2222 break;
2223 case 3:
2224 if (gen_iwmmxt_shift(insn, 0x3f))
2225 return 1;
2226 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2227 break;
2229 gen_op_iwmmxt_movq_wRn_M0(wrd);
2230 gen_op_iwmmxt_set_mup();
2231 gen_op_iwmmxt_set_cup();
2232 break;
2233 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2234 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2235 wrd = (insn >> 12) & 0xf;
2236 rd0 = (insn >> 16) & 0xf;
2237 rd1 = (insn >> 0) & 0xf;
2238 gen_op_iwmmxt_movq_M0_wRn(rd0);
2239 switch ((insn >> 22) & 3) {
2240 case 0:
2241 if (insn & (1 << 21))
2242 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2243 else
2244 gen_op_iwmmxt_minub_M0_wRn(rd1);
2245 break;
2246 case 1:
2247 if (insn & (1 << 21))
2248 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2249 else
2250 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2251 break;
2252 case 2:
2253 if (insn & (1 << 21))
2254 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2255 else
2256 gen_op_iwmmxt_minul_M0_wRn(rd1);
2257 break;
2258 case 3:
2259 return 1;
2261 gen_op_iwmmxt_movq_wRn_M0(wrd);
2262 gen_op_iwmmxt_set_mup();
2263 break;
2264 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2265 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2266 wrd = (insn >> 12) & 0xf;
2267 rd0 = (insn >> 16) & 0xf;
2268 rd1 = (insn >> 0) & 0xf;
2269 gen_op_iwmmxt_movq_M0_wRn(rd0);
2270 switch ((insn >> 22) & 3) {
2271 case 0:
2272 if (insn & (1 << 21))
2273 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2274 else
2275 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2276 break;
2277 case 1:
2278 if (insn & (1 << 21))
2279 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2280 else
2281 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2282 break;
2283 case 2:
2284 if (insn & (1 << 21))
2285 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2286 else
2287 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2288 break;
2289 case 3:
2290 return 1;
2292 gen_op_iwmmxt_movq_wRn_M0(wrd);
2293 gen_op_iwmmxt_set_mup();
2294 break;
2295 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2296 case 0x402: case 0x502: case 0x602: case 0x702:
2297 wrd = (insn >> 12) & 0xf;
2298 rd0 = (insn >> 16) & 0xf;
2299 rd1 = (insn >> 0) & 0xf;
2300 gen_op_iwmmxt_movq_M0_wRn(rd0);
2301 gen_op_movl_T0_im((insn >> 20) & 3);
2302 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2303 gen_op_iwmmxt_movq_wRn_M0(wrd);
2304 gen_op_iwmmxt_set_mup();
2305 break;
2306 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2307 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2308 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2309 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2310 wrd = (insn >> 12) & 0xf;
2311 rd0 = (insn >> 16) & 0xf;
2312 rd1 = (insn >> 0) & 0xf;
2313 gen_op_iwmmxt_movq_M0_wRn(rd0);
2314 switch ((insn >> 20) & 0xf) {
2315 case 0x0:
2316 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2317 break;
2318 case 0x1:
2319 gen_op_iwmmxt_subub_M0_wRn(rd1);
2320 break;
2321 case 0x3:
2322 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2323 break;
2324 case 0x4:
2325 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2326 break;
2327 case 0x5:
2328 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2329 break;
2330 case 0x7:
2331 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2332 break;
2333 case 0x8:
2334 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2335 break;
2336 case 0x9:
2337 gen_op_iwmmxt_subul_M0_wRn(rd1);
2338 break;
2339 case 0xb:
2340 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2341 break;
2342 default:
2343 return 1;
2345 gen_op_iwmmxt_movq_wRn_M0(wrd);
2346 gen_op_iwmmxt_set_mup();
2347 gen_op_iwmmxt_set_cup();
2348 break;
2349 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2350 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2351 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2352 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2353 wrd = (insn >> 12) & 0xf;
2354 rd0 = (insn >> 16) & 0xf;
2355 gen_op_iwmmxt_movq_M0_wRn(rd0);
2356 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2357 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2358 gen_op_iwmmxt_movq_wRn_M0(wrd);
2359 gen_op_iwmmxt_set_mup();
2360 gen_op_iwmmxt_set_cup();
2361 break;
2362 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2363 case 0x418: case 0x518: case 0x618: case 0x718:
2364 case 0x818: case 0x918: case 0xa18: case 0xb18:
2365 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2366 wrd = (insn >> 12) & 0xf;
2367 rd0 = (insn >> 16) & 0xf;
2368 rd1 = (insn >> 0) & 0xf;
2369 gen_op_iwmmxt_movq_M0_wRn(rd0);
2370 switch ((insn >> 20) & 0xf) {
2371 case 0x0:
2372 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2373 break;
2374 case 0x1:
2375 gen_op_iwmmxt_addub_M0_wRn(rd1);
2376 break;
2377 case 0x3:
2378 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2379 break;
2380 case 0x4:
2381 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2382 break;
2383 case 0x5:
2384 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2385 break;
2386 case 0x7:
2387 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2388 break;
2389 case 0x8:
2390 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2391 break;
2392 case 0x9:
2393 gen_op_iwmmxt_addul_M0_wRn(rd1);
2394 break;
2395 case 0xb:
2396 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2397 break;
2398 default:
2399 return 1;
2401 gen_op_iwmmxt_movq_wRn_M0(wrd);
2402 gen_op_iwmmxt_set_mup();
2403 gen_op_iwmmxt_set_cup();
2404 break;
2405 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2406 case 0x408: case 0x508: case 0x608: case 0x708:
2407 case 0x808: case 0x908: case 0xa08: case 0xb08:
2408 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2409 wrd = (insn >> 12) & 0xf;
2410 rd0 = (insn >> 16) & 0xf;
2411 rd1 = (insn >> 0) & 0xf;
2412 gen_op_iwmmxt_movq_M0_wRn(rd0);
2413 if (!(insn & (1 << 20)))
2414 return 1;
2415 switch ((insn >> 22) & 3) {
2416 case 0:
2417 return 1;
2418 case 1:
2419 if (insn & (1 << 21))
2420 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2421 else
2422 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2423 break;
2424 case 2:
2425 if (insn & (1 << 21))
2426 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2427 else
2428 gen_op_iwmmxt_packul_M0_wRn(rd1);
2429 break;
2430 case 3:
2431 if (insn & (1 << 21))
2432 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2433 else
2434 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2435 break;
2437 gen_op_iwmmxt_movq_wRn_M0(wrd);
2438 gen_op_iwmmxt_set_mup();
2439 gen_op_iwmmxt_set_cup();
2440 break;
2441 case 0x201: case 0x203: case 0x205: case 0x207:
2442 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2443 case 0x211: case 0x213: case 0x215: case 0x217:
2444 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2445 wrd = (insn >> 5) & 0xf;
2446 rd0 = (insn >> 12) & 0xf;
2447 rd1 = (insn >> 0) & 0xf;
2448 if (rd0 == 0xf || rd1 == 0xf)
2449 return 1;
2450 gen_op_iwmmxt_movq_M0_wRn(wrd);
2451 switch ((insn >> 16) & 0xf) {
2452 case 0x0: /* TMIA */
2453 gen_movl_T0_reg(s, rd0);
2454 gen_movl_T1_reg(s, rd1);
2455 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2456 break;
2457 case 0x8: /* TMIAPH */
2458 gen_movl_T0_reg(s, rd0);
2459 gen_movl_T1_reg(s, rd1);
2460 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2461 break;
2462 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2463 gen_movl_T1_reg(s, rd0);
2464 if (insn & (1 << 16))
2465 gen_op_shrl_T1_im(16);
2466 gen_op_movl_T0_T1();
2467 gen_movl_T1_reg(s, rd1);
2468 if (insn & (1 << 17))
2469 gen_op_shrl_T1_im(16);
2470 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2471 break;
2472 default:
2473 return 1;
2475 gen_op_iwmmxt_movq_wRn_M0(wrd);
2476 gen_op_iwmmxt_set_mup();
2477 break;
2478 default:
2479 return 1;
2482 return 0;
2485 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2486 (ie. an undefined instruction). */
2487 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2489 int acc, rd0, rd1, rdhi, rdlo;
2491 if ((insn & 0x0ff00f10) == 0x0e200010) {
2492 /* Multiply with Internal Accumulate Format */
2493 rd0 = (insn >> 12) & 0xf;
2494 rd1 = insn & 0xf;
2495 acc = (insn >> 5) & 7;
2497 if (acc != 0)
2498 return 1;
2500 switch ((insn >> 16) & 0xf) {
2501 case 0x0: /* MIA */
2502 gen_movl_T0_reg(s, rd0);
2503 gen_movl_T1_reg(s, rd1);
2504 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2505 break;
2506 case 0x8: /* MIAPH */
2507 gen_movl_T0_reg(s, rd0);
2508 gen_movl_T1_reg(s, rd1);
2509 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2510 break;
2511 case 0xc: /* MIABB */
2512 case 0xd: /* MIABT */
2513 case 0xe: /* MIATB */
2514 case 0xf: /* MIATT */
2515 gen_movl_T1_reg(s, rd0);
2516 if (insn & (1 << 16))
2517 gen_op_shrl_T1_im(16);
2518 gen_op_movl_T0_T1();
2519 gen_movl_T1_reg(s, rd1);
2520 if (insn & (1 << 17))
2521 gen_op_shrl_T1_im(16);
2522 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2523 break;
2524 default:
2525 return 1;
2528 gen_op_iwmmxt_movq_wRn_M0(acc);
2529 return 0;
2532 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2533 /* Internal Accumulator Access Format */
2534 rdhi = (insn >> 16) & 0xf;
2535 rdlo = (insn >> 12) & 0xf;
2536 acc = insn & 7;
2538 if (acc != 0)
2539 return 1;
2541 if (insn & ARM_CP_RW_BIT) { /* MRA */
2542 gen_iwmmxt_movl_T0_T1_wRn(acc);
2543 gen_movl_reg_T0(s, rdlo);
2544 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2545 gen_op_andl_T0_T1();
2546 gen_movl_reg_T0(s, rdhi);
2547 } else { /* MAR */
2548 gen_movl_T0_reg(s, rdlo);
2549 gen_movl_T1_reg(s, rdhi);
2550 gen_iwmmxt_movl_wRn_T0_T1(acc);
2552 return 0;
2555 return 1;
2558 /* Disassemble system coprocessor instruction. Return nonzero if
2559 instruction is not defined. */
2560 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2562 TCGv tmp;
2563 uint32_t rd = (insn >> 12) & 0xf;
2564 uint32_t cp = (insn >> 8) & 0xf;
2565 if (IS_USER(s)) {
2566 return 1;
2569 if (insn & ARM_CP_RW_BIT) {
2570 if (!env->cp[cp].cp_read)
2571 return 1;
2572 gen_set_pc_im(s->pc);
2573 tmp = new_tmp();
2574 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2575 store_reg(s, rd, tmp);
2576 } else {
2577 if (!env->cp[cp].cp_write)
2578 return 1;
2579 gen_set_pc_im(s->pc);
2580 tmp = load_reg(s, rd);
2581 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2583 return 0;
2586 static int cp15_user_ok(uint32_t insn)
2588 int cpn = (insn >> 16) & 0xf;
2589 int cpm = insn & 0xf;
2590 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2592 if (cpn == 13 && cpm == 0) {
2593 /* TLS register. */
2594 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2595 return 1;
2597 if (cpn == 7) {
2598 /* ISB, DSB, DMB. */
2599 if ((cpm == 5 && op == 4)
2600 || (cpm == 10 && (op == 4 || op == 5)))
2601 return 1;
2603 return 0;
2606 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2607 instruction is not defined. */
2608 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2610 uint32_t rd;
2611 TCGv tmp;
2613 /* M profile cores use memory mapped registers instead of cp15. */
2614 if (arm_feature(env, ARM_FEATURE_M))
2615 return 1;
2617 if ((insn & (1 << 25)) == 0) {
2618 if (insn & (1 << 20)) {
2619 /* mrrc */
2620 return 1;
2622 /* mcrr. Used for block cache operations, so implement as no-op. */
2623 return 0;
2625 if ((insn & (1 << 4)) == 0) {
2626 /* cdp */
2627 return 1;
2629 if (IS_USER(s) && !cp15_user_ok(insn)) {
2630 return 1;
2632 if ((insn & 0x0fff0fff) == 0x0e070f90
2633 || (insn & 0x0fff0fff) == 0x0e070f58) {
2634 /* Wait for interrupt. */
2635 gen_set_pc_im(s->pc);
2636 s->is_jmp = DISAS_WFI;
2637 return 0;
2639 rd = (insn >> 12) & 0xf;
2640 if (insn & ARM_CP_RW_BIT) {
2641 tmp = new_tmp();
2642 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2643 /* If the destination register is r15 then sets condition codes. */
2644 if (rd != 15)
2645 store_reg(s, rd, tmp);
2646 else
2647 dead_tmp(tmp);
2648 } else {
2649 tmp = load_reg(s, rd);
2650 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2651 dead_tmp(tmp);
2652 /* Normally we would always end the TB here, but Linux
2653 * arch/arm/mach-pxa/sleep.S expects two instructions following
2654 * an MMU enable to execute from cache. Imitate this behaviour. */
2655 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2656 (insn & 0x0fff0fff) != 0x0e010f10)
2657 gen_lookup_tb(s);
2659 return 0;
2662 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2663 #define VFP_SREG(insn, bigbit, smallbit) \
2664 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2665 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2666 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2667 reg = (((insn) >> (bigbit)) & 0x0f) \
2668 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2669 } else { \
2670 if (insn & (1 << (smallbit))) \
2671 return 1; \
2672 reg = ((insn) >> (bigbit)) & 0x0f; \
2673 }} while (0)
2675 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2676 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2677 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2678 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2679 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2680 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2682 /* Move between integer and VFP cores. */
2683 static TCGv gen_vfp_mrs(void)
2685 TCGv tmp = new_tmp();
2686 tcg_gen_mov_i32(tmp, cpu_F0s);
2687 return tmp;
2690 static void gen_vfp_msr(TCGv tmp)
2692 tcg_gen_mov_i32(cpu_F0s, tmp);
2693 dead_tmp(tmp);
2696 static inline int
2697 vfp_enabled(CPUState * env)
2699 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2702 static void gen_neon_dup_u8(TCGv var, int shift)
2704 TCGv tmp = new_tmp();
2705 if (shift)
2706 tcg_gen_shri_i32(var, var, shift);
2707 tcg_gen_andi_i32(var, var, 0xff);
2708 tcg_gen_shli_i32(tmp, var, 8);
2709 tcg_gen_or_i32(var, var, tmp);
2710 tcg_gen_shli_i32(tmp, var, 16);
2711 tcg_gen_or_i32(var, var, tmp);
2712 dead_tmp(tmp);
2715 static void gen_neon_dup_low16(TCGv var)
2717 TCGv tmp = new_tmp();
2718 tcg_gen_andi_i32(var, var, 0xffff);
2719 tcg_gen_shli_i32(tmp, var, 16);
2720 tcg_gen_or_i32(var, var, tmp);
2721 dead_tmp(tmp);
2724 static void gen_neon_dup_high16(TCGv var)
2726 TCGv tmp = new_tmp();
2727 tcg_gen_andi_i32(var, var, 0xffff0000);
2728 tcg_gen_shri_i32(tmp, var, 16);
2729 tcg_gen_or_i32(var, var, tmp);
2730 dead_tmp(tmp);
2733 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2734 (ie. an undefined instruction). */
2735 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2737 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2738 int dp, veclen;
2739 TCGv tmp;
2740 TCGv tmp2;
2742 if (!arm_feature(env, ARM_FEATURE_VFP))
2743 return 1;
2745 if (!vfp_enabled(env)) {
2746 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2747 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2748 return 1;
2749 rn = (insn >> 16) & 0xf;
2750 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2751 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2752 return 1;
2754 dp = ((insn & 0xf00) == 0xb00);
2755 switch ((insn >> 24) & 0xf) {
2756 case 0xe:
2757 if (insn & (1 << 4)) {
2758 /* single register transfer */
2759 rd = (insn >> 12) & 0xf;
2760 if (dp) {
2761 int size;
2762 int pass;
2764 VFP_DREG_N(rn, insn);
2765 if (insn & 0xf)
2766 return 1;
2767 if (insn & 0x00c00060
2768 && !arm_feature(env, ARM_FEATURE_NEON))
2769 return 1;
2771 pass = (insn >> 21) & 1;
2772 if (insn & (1 << 22)) {
2773 size = 0;
2774 offset = ((insn >> 5) & 3) * 8;
2775 } else if (insn & (1 << 5)) {
2776 size = 1;
2777 offset = (insn & (1 << 6)) ? 16 : 0;
2778 } else {
2779 size = 2;
2780 offset = 0;
2782 if (insn & ARM_CP_RW_BIT) {
2783 /* vfp->arm */
2784 tmp = neon_load_reg(rn, pass);
2785 switch (size) {
2786 case 0:
2787 if (offset)
2788 tcg_gen_shri_i32(tmp, tmp, offset);
2789 if (insn & (1 << 23))
2790 gen_uxtb(tmp);
2791 else
2792 gen_sxtb(tmp);
2793 break;
2794 case 1:
2795 if (insn & (1 << 23)) {
2796 if (offset) {
2797 tcg_gen_shri_i32(tmp, tmp, 16);
2798 } else {
2799 gen_uxth(tmp);
2801 } else {
2802 if (offset) {
2803 tcg_gen_sari_i32(tmp, tmp, 16);
2804 } else {
2805 gen_sxth(tmp);
2808 break;
2809 case 2:
2810 break;
2812 store_reg(s, rd, tmp);
2813 } else {
2814 /* arm->vfp */
2815 tmp = load_reg(s, rd);
2816 if (insn & (1 << 23)) {
2817 /* VDUP */
2818 if (size == 0) {
2819 gen_neon_dup_u8(tmp, 0);
2820 } else if (size == 1) {
2821 gen_neon_dup_low16(tmp);
2823 tmp2 = new_tmp();
2824 tcg_gen_mov_i32(tmp2, tmp);
2825 neon_store_reg(rn, 0, tmp2);
2826 neon_store_reg(rn, 0, tmp);
2827 } else {
2828 /* VMOV */
2829 switch (size) {
2830 case 0:
2831 tmp2 = neon_load_reg(rn, pass);
2832 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2833 dead_tmp(tmp2);
2834 break;
2835 case 1:
2836 tmp2 = neon_load_reg(rn, pass);
2837 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2838 dead_tmp(tmp2);
2839 break;
2840 case 2:
2841 break;
2843 neon_store_reg(rn, pass, tmp);
2846 } else { /* !dp */
2847 if ((insn & 0x6f) != 0x00)
2848 return 1;
2849 rn = VFP_SREG_N(insn);
2850 if (insn & ARM_CP_RW_BIT) {
2851 /* vfp->arm */
2852 if (insn & (1 << 21)) {
2853 /* system register */
2854 rn >>= 1;
2856 switch (rn) {
2857 case ARM_VFP_FPSID:
2858 /* VFP2 allows access to FSID from userspace.
2859 VFP3 restricts all id registers to privileged
2860 accesses. */
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_FPEXC:
2867 if (IS_USER(s))
2868 return 1;
2869 tmp = load_cpu_field(vfp.xregs[rn]);
2870 break;
2871 case ARM_VFP_FPINST:
2872 case ARM_VFP_FPINST2:
2873 /* Not present in VFP3. */
2874 if (IS_USER(s)
2875 || arm_feature(env, ARM_FEATURE_VFP3))
2876 return 1;
2877 tmp = load_cpu_field(vfp.xregs[rn]);
2878 break;
2879 case ARM_VFP_FPSCR:
2880 if (rd == 15) {
2881 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2882 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2883 } else {
2884 tmp = new_tmp();
2885 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2887 break;
2888 case ARM_VFP_MVFR0:
2889 case ARM_VFP_MVFR1:
2890 if (IS_USER(s)
2891 || !arm_feature(env, ARM_FEATURE_VFP3))
2892 return 1;
2893 tmp = load_cpu_field(vfp.xregs[rn]);
2894 break;
2895 default:
2896 return 1;
2898 } else {
2899 gen_mov_F0_vreg(0, rn);
2900 tmp = gen_vfp_mrs();
2902 if (rd == 15) {
2903 /* Set the 4 flag bits in the CPSR. */
2904 gen_set_nzcv(tmp);
2905 dead_tmp(tmp);
2906 } else {
2907 store_reg(s, rd, tmp);
2909 } else {
2910 /* arm->vfp */
2911 tmp = load_reg(s, rd);
2912 if (insn & (1 << 21)) {
2913 rn >>= 1;
2914 /* system register */
2915 switch (rn) {
2916 case ARM_VFP_FPSID:
2917 case ARM_VFP_MVFR0:
2918 case ARM_VFP_MVFR1:
2919 /* Writes are ignored. */
2920 break;
2921 case ARM_VFP_FPSCR:
2922 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2923 dead_tmp(tmp);
2924 gen_lookup_tb(s);
2925 break;
2926 case ARM_VFP_FPEXC:
2927 if (IS_USER(s))
2928 return 1;
2929 store_cpu_field(tmp, vfp.xregs[rn]);
2930 gen_lookup_tb(s);
2931 break;
2932 case ARM_VFP_FPINST:
2933 case ARM_VFP_FPINST2:
2934 store_cpu_field(tmp, vfp.xregs[rn]);
2935 break;
2936 default:
2937 return 1;
2939 } else {
2940 gen_vfp_msr(tmp);
2941 gen_mov_vreg_F0(0, rn);
2945 } else {
2946 /* data processing */
2947 /* The opcode is in bits 23, 21, 20 and 6. */
2948 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2949 if (dp) {
2950 if (op == 15) {
2951 /* rn is opcode */
2952 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2953 } else {
2954 /* rn is register number */
2955 VFP_DREG_N(rn, insn);
2958 if (op == 15 && (rn == 15 || rn > 17)) {
2959 /* Integer or single precision destination. */
2960 rd = VFP_SREG_D(insn);
2961 } else {
2962 VFP_DREG_D(rd, insn);
2965 if (op == 15 && (rn == 16 || rn == 17)) {
2966 /* Integer source. */
2967 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2968 } else {
2969 VFP_DREG_M(rm, insn);
2971 } else {
2972 rn = VFP_SREG_N(insn);
2973 if (op == 15 && rn == 15) {
2974 /* Double precision destination. */
2975 VFP_DREG_D(rd, insn);
2976 } else {
2977 rd = VFP_SREG_D(insn);
2979 rm = VFP_SREG_M(insn);
2982 veclen = env->vfp.vec_len;
2983 if (op == 15 && rn > 3)
2984 veclen = 0;
2986 /* Shut up compiler warnings. */
2987 delta_m = 0;
2988 delta_d = 0;
2989 bank_mask = 0;
2991 if (veclen > 0) {
2992 if (dp)
2993 bank_mask = 0xc;
2994 else
2995 bank_mask = 0x18;
2997 /* Figure out what type of vector operation this is. */
2998 if ((rd & bank_mask) == 0) {
2999 /* scalar */
3000 veclen = 0;
3001 } else {
3002 if (dp)
3003 delta_d = (env->vfp.vec_stride >> 1) + 1;
3004 else
3005 delta_d = env->vfp.vec_stride + 1;
3007 if ((rm & bank_mask) == 0) {
3008 /* mixed scalar/vector */
3009 delta_m = 0;
3010 } else {
3011 /* vector */
3012 delta_m = delta_d;
3017 /* Load the initial operands. */
3018 if (op == 15) {
3019 switch (rn) {
3020 case 16:
3021 case 17:
3022 /* Integer source */
3023 gen_mov_F0_vreg(0, rm);
3024 break;
3025 case 8:
3026 case 9:
3027 /* Compare */
3028 gen_mov_F0_vreg(dp, rd);
3029 gen_mov_F1_vreg(dp, rm);
3030 break;
3031 case 10:
3032 case 11:
3033 /* Compare with zero */
3034 gen_mov_F0_vreg(dp, rd);
3035 gen_vfp_F1_ld0(dp);
3036 break;
3037 case 20:
3038 case 21:
3039 case 22:
3040 case 23:
3041 /* Source and destination the same. */
3042 gen_mov_F0_vreg(dp, rd);
3043 break;
3044 default:
3045 /* One source operand. */
3046 gen_mov_F0_vreg(dp, rm);
3047 break;
3049 } else {
3050 /* Two source operands. */
3051 gen_mov_F0_vreg(dp, rn);
3052 gen_mov_F1_vreg(dp, rm);
3055 for (;;) {
3056 /* Perform the calculation. */
3057 switch (op) {
3058 case 0: /* mac: fd + (fn * fm) */
3059 gen_vfp_mul(dp);
3060 gen_mov_F1_vreg(dp, rd);
3061 gen_vfp_add(dp);
3062 break;
3063 case 1: /* nmac: fd - (fn * fm) */
3064 gen_vfp_mul(dp);
3065 gen_vfp_neg(dp);
3066 gen_mov_F1_vreg(dp, rd);
3067 gen_vfp_add(dp);
3068 break;
3069 case 2: /* msc: -fd + (fn * fm) */
3070 gen_vfp_mul(dp);
3071 gen_mov_F1_vreg(dp, rd);
3072 gen_vfp_sub(dp);
3073 break;
3074 case 3: /* nmsc: -fd - (fn * fm) */
3075 gen_vfp_mul(dp);
3076 gen_mov_F1_vreg(dp, rd);
3077 gen_vfp_add(dp);
3078 gen_vfp_neg(dp);
3079 break;
3080 case 4: /* mul: fn * fm */
3081 gen_vfp_mul(dp);
3082 break;
3083 case 5: /* nmul: -(fn * fm) */
3084 gen_vfp_mul(dp);
3085 gen_vfp_neg(dp);
3086 break;
3087 case 6: /* add: fn + fm */
3088 gen_vfp_add(dp);
3089 break;
3090 case 7: /* sub: fn - fm */
3091 gen_vfp_sub(dp);
3092 break;
3093 case 8: /* div: fn / fm */
3094 gen_vfp_div(dp);
3095 break;
3096 case 14: /* fconst */
3097 if (!arm_feature(env, ARM_FEATURE_VFP3))
3098 return 1;
3100 n = (insn << 12) & 0x80000000;
3101 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3102 if (dp) {
3103 if (i & 0x40)
3104 i |= 0x3f80;
3105 else
3106 i |= 0x4000;
3107 n |= i << 16;
3108 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3109 } else {
3110 if (i & 0x40)
3111 i |= 0x780;
3112 else
3113 i |= 0x800;
3114 n |= i << 19;
3115 tcg_gen_movi_i32(cpu_F0s, n);
3117 break;
3118 case 15: /* extension space */
3119 switch (rn) {
3120 case 0: /* cpy */
3121 /* no-op */
3122 break;
3123 case 1: /* abs */
3124 gen_vfp_abs(dp);
3125 break;
3126 case 2: /* neg */
3127 gen_vfp_neg(dp);
3128 break;
3129 case 3: /* sqrt */
3130 gen_vfp_sqrt(dp);
3131 break;
3132 case 8: /* cmp */
3133 gen_vfp_cmp(dp);
3134 break;
3135 case 9: /* cmpe */
3136 gen_vfp_cmpe(dp);
3137 break;
3138 case 10: /* cmpz */
3139 gen_vfp_cmp(dp);
3140 break;
3141 case 11: /* cmpez */
3142 gen_vfp_F1_ld0(dp);
3143 gen_vfp_cmpe(dp);
3144 break;
3145 case 15: /* single<->double conversion */
3146 if (dp)
3147 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3148 else
3149 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3150 break;
3151 case 16: /* fuito */
3152 gen_vfp_uito(dp);
3153 break;
3154 case 17: /* fsito */
3155 gen_vfp_sito(dp);
3156 break;
3157 case 20: /* fshto */
3158 if (!arm_feature(env, ARM_FEATURE_VFP3))
3159 return 1;
3160 gen_vfp_shto(dp, rm);
3161 break;
3162 case 21: /* fslto */
3163 if (!arm_feature(env, ARM_FEATURE_VFP3))
3164 return 1;
3165 gen_vfp_slto(dp, rm);
3166 break;
3167 case 22: /* fuhto */
3168 if (!arm_feature(env, ARM_FEATURE_VFP3))
3169 return 1;
3170 gen_vfp_uhto(dp, rm);
3171 break;
3172 case 23: /* fulto */
3173 if (!arm_feature(env, ARM_FEATURE_VFP3))
3174 return 1;
3175 gen_vfp_ulto(dp, rm);
3176 break;
3177 case 24: /* ftoui */
3178 gen_vfp_toui(dp);
3179 break;
3180 case 25: /* ftouiz */
3181 gen_vfp_touiz(dp);
3182 break;
3183 case 26: /* ftosi */
3184 gen_vfp_tosi(dp);
3185 break;
3186 case 27: /* ftosiz */
3187 gen_vfp_tosiz(dp);
3188 break;
3189 case 28: /* ftosh */
3190 if (!arm_feature(env, ARM_FEATURE_VFP3))
3191 return 1;
3192 gen_vfp_tosh(dp, rm);
3193 break;
3194 case 29: /* ftosl */
3195 if (!arm_feature(env, ARM_FEATURE_VFP3))
3196 return 1;
3197 gen_vfp_tosl(dp, rm);
3198 break;
3199 case 30: /* ftouh */
3200 if (!arm_feature(env, ARM_FEATURE_VFP3))
3201 return 1;
3202 gen_vfp_touh(dp, rm);
3203 break;
3204 case 31: /* ftoul */
3205 if (!arm_feature(env, ARM_FEATURE_VFP3))
3206 return 1;
3207 gen_vfp_toul(dp, rm);
3208 break;
3209 default: /* undefined */
3210 printf ("rn:%d\n", rn);
3211 return 1;
3213 break;
3214 default: /* undefined */
3215 printf ("op:%d\n", op);
3216 return 1;
3219 /* Write back the result. */
3220 if (op == 15 && (rn >= 8 && rn <= 11))
3221 ; /* Comparison, do nothing. */
3222 else if (op == 15 && rn > 17)
3223 /* Integer result. */
3224 gen_mov_vreg_F0(0, rd);
3225 else if (op == 15 && rn == 15)
3226 /* conversion */
3227 gen_mov_vreg_F0(!dp, rd);
3228 else
3229 gen_mov_vreg_F0(dp, rd);
3231 /* break out of the loop if we have finished */
3232 if (veclen == 0)
3233 break;
3235 if (op == 15 && delta_m == 0) {
3236 /* single source one-many */
3237 while (veclen--) {
3238 rd = ((rd + delta_d) & (bank_mask - 1))
3239 | (rd & bank_mask);
3240 gen_mov_vreg_F0(dp, rd);
3242 break;
3244 /* Setup the next operands. */
3245 veclen--;
3246 rd = ((rd + delta_d) & (bank_mask - 1))
3247 | (rd & bank_mask);
3249 if (op == 15) {
3250 /* One source operand. */
3251 rm = ((rm + delta_m) & (bank_mask - 1))
3252 | (rm & bank_mask);
3253 gen_mov_F0_vreg(dp, rm);
3254 } else {
3255 /* Two source operands. */
3256 rn = ((rn + delta_d) & (bank_mask - 1))
3257 | (rn & bank_mask);
3258 gen_mov_F0_vreg(dp, rn);
3259 if (delta_m) {
3260 rm = ((rm + delta_m) & (bank_mask - 1))
3261 | (rm & bank_mask);
3262 gen_mov_F1_vreg(dp, rm);
3267 break;
3268 case 0xc:
3269 case 0xd:
3270 if (dp && (insn & 0x03e00000) == 0x00400000) {
3271 /* two-register transfer */
3272 rn = (insn >> 16) & 0xf;
3273 rd = (insn >> 12) & 0xf;
3274 if (dp) {
3275 VFP_DREG_M(rm, insn);
3276 } else {
3277 rm = VFP_SREG_M(insn);
3280 if (insn & ARM_CP_RW_BIT) {
3281 /* vfp->arm */
3282 if (dp) {
3283 gen_mov_F0_vreg(0, rm * 2);
3284 tmp = gen_vfp_mrs();
3285 store_reg(s, rd, tmp);
3286 gen_mov_F0_vreg(0, rm * 2 + 1);
3287 tmp = gen_vfp_mrs();
3288 store_reg(s, rn, tmp);
3289 } else {
3290 gen_mov_F0_vreg(0, rm);
3291 tmp = gen_vfp_mrs();
3292 store_reg(s, rn, tmp);
3293 gen_mov_F0_vreg(0, rm + 1);
3294 tmp = gen_vfp_mrs();
3295 store_reg(s, rd, tmp);
3297 } else {
3298 /* arm->vfp */
3299 if (dp) {
3300 tmp = load_reg(s, rd);
3301 gen_vfp_msr(tmp);
3302 gen_mov_vreg_F0(0, rm * 2);
3303 tmp = load_reg(s, rn);
3304 gen_vfp_msr(tmp);
3305 gen_mov_vreg_F0(0, rm * 2 + 1);
3306 } else {
3307 tmp = load_reg(s, rn);
3308 gen_vfp_msr(tmp);
3309 gen_mov_vreg_F0(0, rm);
3310 tmp = load_reg(s, rd);
3311 gen_vfp_msr(tmp);
3312 gen_mov_vreg_F0(0, rm + 1);
3315 } else {
3316 /* Load/store */
3317 rn = (insn >> 16) & 0xf;
3318 if (dp)
3319 VFP_DREG_D(rd, insn);
3320 else
3321 rd = VFP_SREG_D(insn);
3322 if (s->thumb && rn == 15) {
3323 gen_op_movl_T1_im(s->pc & ~2);
3324 } else {
3325 gen_movl_T1_reg(s, rn);
3327 if ((insn & 0x01200000) == 0x01000000) {
3328 /* Single load/store */
3329 offset = (insn & 0xff) << 2;
3330 if ((insn & (1 << 23)) == 0)
3331 offset = -offset;
3332 gen_op_addl_T1_im(offset);
3333 if (insn & (1 << 20)) {
3334 gen_vfp_ld(s, dp);
3335 gen_mov_vreg_F0(dp, rd);
3336 } else {
3337 gen_mov_F0_vreg(dp, rd);
3338 gen_vfp_st(s, dp);
3340 } else {
3341 /* load/store multiple */
3342 if (dp)
3343 n = (insn >> 1) & 0x7f;
3344 else
3345 n = insn & 0xff;
3347 if (insn & (1 << 24)) /* pre-decrement */
3348 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3350 if (dp)
3351 offset = 8;
3352 else
3353 offset = 4;
3354 for (i = 0; i < n; i++) {
3355 if (insn & ARM_CP_RW_BIT) {
3356 /* load */
3357 gen_vfp_ld(s, dp);
3358 gen_mov_vreg_F0(dp, rd + i);
3359 } else {
3360 /* store */
3361 gen_mov_F0_vreg(dp, rd + i);
3362 gen_vfp_st(s, dp);
3364 gen_op_addl_T1_im(offset);
3366 if (insn & (1 << 21)) {
3367 /* writeback */
3368 if (insn & (1 << 24))
3369 offset = -offset * n;
3370 else if (dp && (insn & 1))
3371 offset = 4;
3372 else
3373 offset = 0;
3375 if (offset != 0)
3376 gen_op_addl_T1_im(offset);
3377 gen_movl_reg_T1(s, rn);
3381 break;
3382 default:
3383 /* Should never happen. */
3384 return 1;
3386 return 0;
3389 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3391 TranslationBlock *tb;
3393 tb = s->tb;
3394 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3395 tcg_gen_goto_tb(n);
3396 gen_set_pc_im(dest);
3397 tcg_gen_exit_tb((long)tb + n);
3398 } else {
3399 gen_set_pc_im(dest);
3400 tcg_gen_exit_tb(0);
3404 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3406 if (__builtin_expect(s->singlestep_enabled, 0)) {
3407 /* An indirect jump so that we still trigger the debug exception. */
3408 if (s->thumb)
3409 dest |= 1;
3410 gen_bx_im(s, dest);
3411 } else {
3412 gen_goto_tb(s, 0, dest);
3413 s->is_jmp = DISAS_TB_JUMP;
3417 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3419 if (x)
3420 tcg_gen_sari_i32(t0, t0, 16);
3421 else
3422 gen_sxth(t0);
3423 if (y)
3424 tcg_gen_sari_i32(t1, t1, 16);
3425 else
3426 gen_sxth(t1);
3427 tcg_gen_mul_i32(t0, t0, t1);
3430 /* Return the mask of PSR bits set by a MSR instruction. */
3431 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3432 uint32_t mask;
3434 mask = 0;
3435 if (flags & (1 << 0))
3436 mask |= 0xff;
3437 if (flags & (1 << 1))
3438 mask |= 0xff00;
3439 if (flags & (1 << 2))
3440 mask |= 0xff0000;
3441 if (flags & (1 << 3))
3442 mask |= 0xff000000;
3444 /* Mask out undefined bits. */
3445 mask &= ~CPSR_RESERVED;
3446 if (!arm_feature(env, ARM_FEATURE_V6))
3447 mask &= ~(CPSR_E | CPSR_GE);
3448 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3449 mask &= ~CPSR_IT;
3450 /* Mask out execution state bits. */
3451 if (!spsr)
3452 mask &= ~CPSR_EXEC;
3453 /* Mask out privileged bits. */
3454 if (IS_USER(s))
3455 mask &= CPSR_USER;
3456 return mask;
3459 /* Returns nonzero if access to the PSR is not permitted. */
3460 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3462 TCGv tmp;
3463 if (spsr) {
3464 /* ??? This is also undefined in system mode. */
3465 if (IS_USER(s))
3466 return 1;
3468 tmp = load_cpu_field(spsr);
3469 tcg_gen_andi_i32(tmp, tmp, ~mask);
3470 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3471 tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3472 store_cpu_field(tmp, spsr);
3473 } else {
3474 gen_set_cpsr(cpu_T[0], mask);
3476 gen_lookup_tb(s);
3477 return 0;
3480 /* Generate an old-style exception return. */
3481 static void gen_exception_return(DisasContext *s)
3483 TCGv tmp;
3484 gen_movl_reg_T0(s, 15);
3485 tmp = load_cpu_field(spsr);
3486 gen_set_cpsr(tmp, 0xffffffff);
3487 dead_tmp(tmp);
3488 s->is_jmp = DISAS_UPDATE;
3491 /* Generate a v6 exception return. Marks both values as dead. */
3492 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3494 gen_set_cpsr(cpsr, 0xffffffff);
3495 dead_tmp(cpsr);
3496 store_reg(s, 15, pc);
3497 s->is_jmp = DISAS_UPDATE;
3500 static inline void
3501 gen_set_condexec (DisasContext *s)
3503 if (s->condexec_mask) {
3504 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3505 TCGv tmp = new_tmp();
3506 tcg_gen_movi_i32(tmp, val);
3507 store_cpu_field(tmp, condexec_bits);
3511 static void gen_nop_hint(DisasContext *s, int val)
3513 switch (val) {
3514 case 3: /* wfi */
3515 gen_set_pc_im(s->pc);
3516 s->is_jmp = DISAS_WFI;
3517 break;
3518 case 2: /* wfe */
3519 case 4: /* sev */
3520 /* TODO: Implement SEV and WFE. May help SMP performance. */
3521 default: /* nop */
3522 break;
3526 /* These macros help make the code more readable when migrating from the
3527 old dyngen helpers. They should probably be removed when
3528 T0/T1 are removed. */
3529 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3530 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3532 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3534 static inline int gen_neon_add(int size)
3536 switch (size) {
3537 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3538 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3539 case 2: gen_op_addl_T0_T1(); break;
3540 default: return 1;
3542 return 0;
3545 static inline void gen_neon_rsb(int size)
3547 switch (size) {
3548 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3549 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3550 case 2: gen_op_rsbl_T0_T1(); break;
3551 default: return;
3555 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3556 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3557 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3558 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3559 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3561 /* FIXME: This is wrong. They set the wrong overflow bit. */
3562 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3563 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3564 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3565 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3567 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3568 switch ((size << 1) | u) { \
3569 case 0: \
3570 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3571 break; \
3572 case 1: \
3573 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3574 break; \
3575 case 2: \
3576 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3577 break; \
3578 case 3: \
3579 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3580 break; \
3581 case 4: \
3582 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3583 break; \
3584 case 5: \
3585 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3586 break; \
3587 default: return 1; \
3588 }} while (0)
3590 #define GEN_NEON_INTEGER_OP(name) do { \
3591 switch ((size << 1) | u) { \
3592 case 0: \
3593 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3594 break; \
3595 case 1: \
3596 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3597 break; \
3598 case 2: \
3599 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3600 break; \
3601 case 3: \
3602 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3603 break; \
3604 case 4: \
3605 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3606 break; \
3607 case 5: \
3608 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3609 break; \
3610 default: return 1; \
3611 }} while (0)
3613 static inline void
3614 gen_neon_movl_scratch_T0(int scratch)
3616 uint32_t offset;
3618 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3619 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3622 static inline void
3623 gen_neon_movl_scratch_T1(int scratch)
3625 uint32_t offset;
3627 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3628 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3631 static inline void
3632 gen_neon_movl_T0_scratch(int scratch)
3634 uint32_t offset;
3636 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3637 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3640 static inline void
3641 gen_neon_movl_T1_scratch(int scratch)
3643 uint32_t offset;
3645 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3646 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3649 static inline void gen_neon_get_scalar(int size, int reg)
3651 if (size == 1) {
3652 NEON_GET_REG(T0, reg >> 1, reg & 1);
3653 } else {
3654 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3655 if (reg & 1)
3656 gen_neon_dup_low16(cpu_T[0]);
3657 else
3658 gen_neon_dup_high16(cpu_T[0]);
3662 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3664 int n;
3666 for (n = 0; n < q + 1; n += 2) {
3667 NEON_GET_REG(T0, reg, n);
3668 NEON_GET_REG(T0, reg, n + n);
3669 switch (size) {
3670 case 0: gen_helper_neon_unzip_u8(); break;
3671 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3672 case 2: /* no-op */; break;
3673 default: abort();
3675 gen_neon_movl_scratch_T0(tmp + n);
3676 gen_neon_movl_scratch_T1(tmp + n + 1);
3680 static struct {
3681 int nregs;
3682 int interleave;
3683 int spacing;
3684 } neon_ls_element_type[11] = {
3685 {4, 4, 1},
3686 {4, 4, 2},
3687 {4, 1, 1},
3688 {4, 2, 1},
3689 {3, 3, 1},
3690 {3, 3, 2},
3691 {3, 1, 1},
3692 {1, 1, 1},
3693 {2, 2, 1},
3694 {2, 2, 2},
3695 {2, 1, 1}
3698 /* Translate a NEON load/store element instruction. Return nonzero if the
3699 instruction is invalid. */
3700 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3702 int rd, rn, rm;
3703 int op;
3704 int nregs;
3705 int interleave;
3706 int stride;
3707 int size;
3708 int reg;
3709 int pass;
3710 int load;
3711 int shift;
3712 int n;
3713 TCGv tmp;
3714 TCGv tmp2;
3716 if (!vfp_enabled(env))
3717 return 1;
3718 VFP_DREG_D(rd, insn);
3719 rn = (insn >> 16) & 0xf;
3720 rm = insn & 0xf;
3721 load = (insn & (1 << 21)) != 0;
3722 if ((insn & (1 << 23)) == 0) {
3723 /* Load store all elements. */
3724 op = (insn >> 8) & 0xf;
3725 size = (insn >> 6) & 3;
3726 if (op > 10 || size == 3)
3727 return 1;
3728 nregs = neon_ls_element_type[op].nregs;
3729 interleave = neon_ls_element_type[op].interleave;
3730 gen_movl_T1_reg(s, rn);
3731 stride = (1 << size) * interleave;
3732 for (reg = 0; reg < nregs; reg++) {
3733 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3734 gen_movl_T1_reg(s, rn);
3735 gen_op_addl_T1_im((1 << size) * reg);
3736 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3737 gen_movl_T1_reg(s, rn);
3738 gen_op_addl_T1_im(1 << size);
3740 for (pass = 0; pass < 2; pass++) {
3741 if (size == 2) {
3742 if (load) {
3743 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3744 neon_store_reg(rd, pass, tmp);
3745 } else {
3746 tmp = neon_load_reg(rd, pass);
3747 gen_st32(tmp, cpu_T[1], IS_USER(s));
3749 gen_op_addl_T1_im(stride);
3750 } else if (size == 1) {
3751 if (load) {
3752 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3753 gen_op_addl_T1_im(stride);
3754 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3755 gen_op_addl_T1_im(stride);
3756 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3757 dead_tmp(tmp2);
3758 neon_store_reg(rd, pass, tmp);
3759 } else {
3760 tmp = neon_load_reg(rd, pass);
3761 tmp2 = new_tmp();
3762 tcg_gen_shri_i32(tmp2, tmp, 16);
3763 gen_st16(tmp, cpu_T[1], IS_USER(s));
3764 gen_op_addl_T1_im(stride);
3765 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3766 gen_op_addl_T1_im(stride);
3768 } else /* size == 0 */ {
3769 if (load) {
3770 for (n = 0; n < 4; n++) {
3771 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3772 gen_op_addl_T1_im(stride);
3773 if (n == 0) {
3774 tmp2 = tmp;
3775 } else {
3776 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3777 dead_tmp(tmp);
3780 neon_store_reg(rd, pass, tmp2);
3781 } else {
3782 tmp2 = neon_load_reg(rd, pass);
3783 for (n = 0; n < 4; n++) {
3784 tmp = new_tmp();
3785 if (n == 0) {
3786 tcg_gen_mov_i32(tmp, tmp2);
3787 } else {
3788 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3790 gen_st8(tmp, cpu_T[1], IS_USER(s));
3791 gen_op_addl_T1_im(stride);
3793 dead_tmp(tmp2);
3797 rd += neon_ls_element_type[op].spacing;
3799 stride = nregs * 8;
3800 } else {
3801 size = (insn >> 10) & 3;
3802 if (size == 3) {
3803 /* Load single element to all lanes. */
3804 if (!load)
3805 return 1;
3806 size = (insn >> 6) & 3;
3807 nregs = ((insn >> 8) & 3) + 1;
3808 stride = (insn & (1 << 5)) ? 2 : 1;
3809 gen_movl_T1_reg(s, rn);
3810 for (reg = 0; reg < nregs; reg++) {
3811 switch (size) {
3812 case 0:
3813 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3814 gen_neon_dup_u8(tmp, 0);
3815 break;
3816 case 1:
3817 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3818 gen_neon_dup_low16(tmp);
3819 break;
3820 case 2:
3821 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3822 break;
3823 case 3:
3824 return 1;
3826 gen_op_addl_T1_im(1 << size);
3827 tmp2 = new_tmp();
3828 tcg_gen_mov_i32(tmp2, tmp);
3829 neon_store_reg(rd, 0, tmp2);
3830 neon_store_reg(rd, 0, tmp);
3831 rd += stride;
3833 stride = (1 << size) * nregs;
3834 } else {
3835 /* Single element. */
3836 pass = (insn >> 7) & 1;
3837 switch (size) {
3838 case 0:
3839 shift = ((insn >> 5) & 3) * 8;
3840 stride = 1;
3841 break;
3842 case 1:
3843 shift = ((insn >> 6) & 1) * 16;
3844 stride = (insn & (1 << 5)) ? 2 : 1;
3845 break;
3846 case 2:
3847 shift = 0;
3848 stride = (insn & (1 << 6)) ? 2 : 1;
3849 break;
3850 default:
3851 abort();
3853 nregs = ((insn >> 8) & 3) + 1;
3854 gen_movl_T1_reg(s, rn);
3855 for (reg = 0; reg < nregs; reg++) {
3856 if (load) {
3857 switch (size) {
3858 case 0:
3859 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3860 break;
3861 case 1:
3862 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3863 break;
3864 case 2:
3865 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3866 break;
3868 if (size != 2) {
3869 tmp2 = neon_load_reg(rd, pass);
3870 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3871 dead_tmp(tmp2);
3873 neon_store_reg(rd, pass, tmp);
3874 } else { /* Store */
3875 tmp = neon_load_reg(rd, pass);
3876 if (shift)
3877 tcg_gen_shri_i32(tmp, tmp, shift);
3878 switch (size) {
3879 case 0:
3880 gen_st8(tmp, cpu_T[1], IS_USER(s));
3881 break;
3882 case 1:
3883 gen_st16(tmp, cpu_T[1], IS_USER(s));
3884 break;
3885 case 2:
3886 gen_st32(tmp, cpu_T[1], IS_USER(s));
3887 break;
3890 rd += stride;
3891 gen_op_addl_T1_im(1 << size);
3893 stride = nregs * (1 << size);
3896 if (rm != 15) {
3897 TCGv base;
3899 base = load_reg(s, rn);
3900 if (rm == 13) {
3901 tcg_gen_addi_i32(base, base, stride);
3902 } else {
3903 TCGv index;
3904 index = load_reg(s, rm);
3905 tcg_gen_add_i32(base, base, index);
3906 dead_tmp(index);
3908 store_reg(s, rn, base);
3910 return 0;
3913 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3914 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3916 tcg_gen_and_i32(t, t, c);
3917 tcg_gen_bic_i32(f, f, c);
3918 tcg_gen_or_i32(dest, t, f);
3921 static inline void gen_neon_narrow(int size, TCGv dest, TCGv src)
3923 switch (size) {
3924 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3925 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3926 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3927 default: abort();
3931 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv src)
3933 switch (size) {
3934 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3935 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3936 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3937 default: abort();
3941 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv src)
3943 switch (size) {
3944 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3945 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3946 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3947 default: abort();
3951 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3952 int q, int u)
3954 if (q) {
3955 if (u) {
3956 switch (size) {
3957 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3958 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3959 default: abort();
3961 } else {
3962 switch (size) {
3963 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3964 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3965 default: abort();
3968 } else {
3969 if (u) {
3970 switch (size) {
3971 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3972 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3973 default: abort();
3975 } else {
3976 switch (size) {
3977 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3978 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3979 default: abort();
3985 static inline void gen_neon_widen(TCGv dest, TCGv src, int size, int u)
3987 if (u) {
3988 switch (size) {
3989 case 0: gen_helper_neon_widen_u8(dest, src); break;
3990 case 1: gen_helper_neon_widen_u16(dest, src); break;
3991 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3992 default: abort();
3994 } else {
3995 switch (size) {
3996 case 0: gen_helper_neon_widen_s8(dest, src); break;
3997 case 1: gen_helper_neon_widen_s16(dest, src); break;
3998 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3999 default: abort();
4002 dead_tmp(src);
4005 static inline void gen_neon_addl(int size)
4007 switch (size) {
4008 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4009 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4010 case 2: tcg_gen_add_i64(CPU_V001); break;
4011 default: abort();
4015 static inline void gen_neon_subl(int size)
4017 switch (size) {
4018 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4019 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4020 case 2: tcg_gen_sub_i64(CPU_V001); break;
4021 default: abort();
4025 static inline void gen_neon_negl(TCGv var, int size)
4027 switch (size) {
4028 case 0: gen_helper_neon_negl_u16(var, var); break;
4029 case 1: gen_helper_neon_negl_u32(var, var); break;
4030 case 2: gen_helper_neon_negl_u64(var, var); break;
4031 default: abort();
4035 static inline void gen_neon_addl_saturate(TCGv op0, TCGv op1, int size)
4037 switch (size) {
4038 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4039 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4040 default: abort();
4044 static inline void gen_neon_mull(TCGv dest, TCGv a, TCGv b, int size, int u)
4046 TCGv tmp;
4048 switch ((size << 1) | u) {
4049 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4050 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4051 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4052 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4053 case 4:
4054 tmp = gen_muls_i64_i32(a, b);
4055 tcg_gen_mov_i64(dest, tmp);
4056 break;
4057 case 5:
4058 tmp = gen_mulu_i64_i32(a, b);
4059 tcg_gen_mov_i64(dest, tmp);
4060 break;
4061 default: abort();
4063 if (size < 2) {
4064 dead_tmp(b);
4065 dead_tmp(a);
4069 /* Translate a NEON data processing instruction. Return nonzero if the
4070 instruction is invalid.
4071 We process data in a mixture of 32-bit and 64-bit chunks.
4072 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4074 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4076 int op;
4077 int q;
4078 int rd, rn, rm;
4079 int size;
4080 int shift;
4081 int pass;
4082 int count;
4083 int pairwise;
4084 int u;
4085 int n;
4086 uint32_t imm;
4087 TCGv tmp;
4088 TCGv tmp2;
4089 TCGv tmp3;
4091 if (!vfp_enabled(env))
4092 return 1;
4093 q = (insn & (1 << 6)) != 0;
4094 u = (insn >> 24) & 1;
4095 VFP_DREG_D(rd, insn);
4096 VFP_DREG_N(rn, insn);
4097 VFP_DREG_M(rm, insn);
4098 size = (insn >> 20) & 3;
4099 if ((insn & (1 << 23)) == 0) {
4100 /* Three register same length. */
4101 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4102 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4103 || op == 10 || op == 11 || op == 16)) {
4104 /* 64-bit element instructions. */
4105 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4106 neon_load_reg64(cpu_V0, rn + pass);
4107 neon_load_reg64(cpu_V1, rm + pass);
4108 switch (op) {
4109 case 1: /* VQADD */
4110 if (u) {
4111 gen_helper_neon_add_saturate_u64(CPU_V001);
4112 } else {
4113 gen_helper_neon_add_saturate_s64(CPU_V001);
4115 break;
4116 case 5: /* VQSUB */
4117 if (u) {
4118 gen_helper_neon_sub_saturate_u64(CPU_V001);
4119 } else {
4120 gen_helper_neon_sub_saturate_s64(CPU_V001);
4122 break;
4123 case 8: /* VSHL */
4124 if (u) {
4125 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4126 } else {
4127 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4129 break;
4130 case 9: /* VQSHL */
4131 if (u) {
4132 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4133 cpu_V0, cpu_V0);
4134 } else {
4135 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4136 cpu_V1, cpu_V0);
4138 break;
4139 case 10: /* VRSHL */
4140 if (u) {
4141 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4142 } else {
4143 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4145 break;
4146 case 11: /* VQRSHL */
4147 if (u) {
4148 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4149 cpu_V1, cpu_V0);
4150 } else {
4151 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4152 cpu_V1, cpu_V0);
4154 break;
4155 case 16:
4156 if (u) {
4157 tcg_gen_sub_i64(CPU_V001);
4158 } else {
4159 tcg_gen_add_i64(CPU_V001);
4161 break;
4162 default:
4163 abort();
4165 neon_store_reg64(cpu_V0, rd + pass);
4167 return 0;
4169 switch (op) {
4170 case 8: /* VSHL */
4171 case 9: /* VQSHL */
4172 case 10: /* VRSHL */
4173 case 11: /* VQRSHL */
4175 int rtmp;
4176 /* Shift instruction operands are reversed. */
4177 rtmp = rn;
4178 rn = rm;
4179 rm = rtmp;
4180 pairwise = 0;
4182 break;
4183 case 20: /* VPMAX */
4184 case 21: /* VPMIN */
4185 case 23: /* VPADD */
4186 pairwise = 1;
4187 break;
4188 case 26: /* VPADD (float) */
4189 pairwise = (u && size < 2);
4190 break;
4191 case 30: /* VPMIN/VPMAX (float) */
4192 pairwise = u;
4193 break;
4194 default:
4195 pairwise = 0;
4196 break;
4198 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4200 if (pairwise) {
4201 /* Pairwise. */
4202 if (q)
4203 n = (pass & 1) * 2;
4204 else
4205 n = 0;
4206 if (pass < q + 1) {
4207 NEON_GET_REG(T0, rn, n);
4208 NEON_GET_REG(T1, rn, n + 1);
4209 } else {
4210 NEON_GET_REG(T0, rm, n);
4211 NEON_GET_REG(T1, rm, n + 1);
4213 } else {
4214 /* Elementwise. */
4215 NEON_GET_REG(T0, rn, pass);
4216 NEON_GET_REG(T1, rm, pass);
4218 switch (op) {
4219 case 0: /* VHADD */
4220 GEN_NEON_INTEGER_OP(hadd);
4221 break;
4222 case 1: /* VQADD */
4223 GEN_NEON_INTEGER_OP_ENV(qadd);
4224 break;
4225 case 2: /* VRHADD */
4226 GEN_NEON_INTEGER_OP(rhadd);
4227 break;
4228 case 3: /* Logic ops. */
4229 switch ((u << 2) | size) {
4230 case 0: /* VAND */
4231 gen_op_andl_T0_T1();
4232 break;
4233 case 1: /* BIC */
4234 gen_op_bicl_T0_T1();
4235 break;
4236 case 2: /* VORR */
4237 gen_op_orl_T0_T1();
4238 break;
4239 case 3: /* VORN */
4240 gen_op_notl_T1();
4241 gen_op_orl_T0_T1();
4242 break;
4243 case 4: /* VEOR */
4244 gen_op_xorl_T0_T1();
4245 break;
4246 case 5: /* VBSL */
4247 tmp = neon_load_reg(rd, pass);
4248 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4249 dead_tmp(tmp);
4250 break;
4251 case 6: /* VBIT */
4252 tmp = neon_load_reg(rd, pass);
4253 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4254 dead_tmp(tmp);
4255 break;
4256 case 7: /* VBIF */
4257 tmp = neon_load_reg(rd, pass);
4258 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4259 dead_tmp(tmp);
4260 break;
4262 break;
4263 case 4: /* VHSUB */
4264 GEN_NEON_INTEGER_OP(hsub);
4265 break;
4266 case 5: /* VQSUB */
4267 GEN_NEON_INTEGER_OP_ENV(qsub);
4268 break;
4269 case 6: /* VCGT */
4270 GEN_NEON_INTEGER_OP(cgt);
4271 break;
4272 case 7: /* VCGE */
4273 GEN_NEON_INTEGER_OP(cge);
4274 break;
4275 case 8: /* VSHL */
4276 GEN_NEON_INTEGER_OP(shl);
4277 break;
4278 case 9: /* VQSHL */
4279 GEN_NEON_INTEGER_OP_ENV(qshl);
4280 break;
4281 case 10: /* VRSHL */
4282 GEN_NEON_INTEGER_OP(rshl);
4283 break;
4284 case 11: /* VQRSHL */
4285 GEN_NEON_INTEGER_OP_ENV(qrshl);
4286 break;
4287 case 12: /* VMAX */
4288 GEN_NEON_INTEGER_OP(max);
4289 break;
4290 case 13: /* VMIN */
4291 GEN_NEON_INTEGER_OP(min);
4292 break;
4293 case 14: /* VABD */
4294 GEN_NEON_INTEGER_OP(abd);
4295 break;
4296 case 15: /* VABA */
4297 GEN_NEON_INTEGER_OP(abd);
4298 NEON_GET_REG(T1, rd, pass);
4299 gen_neon_add(size);
4300 break;
4301 case 16:
4302 if (!u) { /* VADD */
4303 if (gen_neon_add(size))
4304 return 1;
4305 } else { /* VSUB */
4306 switch (size) {
4307 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4308 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4309 case 2: gen_op_subl_T0_T1(); break;
4310 default: return 1;
4313 break;
4314 case 17:
4315 if (!u) { /* VTST */
4316 switch (size) {
4317 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4318 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4319 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4320 default: return 1;
4322 } else { /* VCEQ */
4323 switch (size) {
4324 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4325 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4326 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4327 default: return 1;
4330 break;
4331 case 18: /* Multiply. */
4332 switch (size) {
4333 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4334 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4335 case 2: gen_op_mul_T0_T1(); break;
4336 default: return 1;
4338 NEON_GET_REG(T1, rd, pass);
4339 if (u) { /* VMLS */
4340 gen_neon_rsb(size);
4341 } else { /* VMLA */
4342 gen_neon_add(size);
4344 break;
4345 case 19: /* VMUL */
4346 if (u) { /* polynomial */
4347 gen_helper_neon_mul_p8(CPU_T001);
4348 } else { /* Integer */
4349 switch (size) {
4350 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4351 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4352 case 2: gen_op_mul_T0_T1(); break;
4353 default: return 1;
4356 break;
4357 case 20: /* VPMAX */
4358 GEN_NEON_INTEGER_OP(pmax);
4359 break;
4360 case 21: /* VPMIN */
4361 GEN_NEON_INTEGER_OP(pmin);
4362 break;
4363 case 22: /* Hultiply high. */
4364 if (!u) { /* VQDMULH */
4365 switch (size) {
4366 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4367 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4368 default: return 1;
4370 } else { /* VQRDHMUL */
4371 switch (size) {
4372 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4373 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4374 default: return 1;
4377 break;
4378 case 23: /* VPADD */
4379 if (u)
4380 return 1;
4381 switch (size) {
4382 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4383 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4384 case 2: gen_op_addl_T0_T1(); break;
4385 default: return 1;
4387 break;
4388 case 26: /* Floating point arithnetic. */
4389 switch ((u << 2) | size) {
4390 case 0: /* VADD */
4391 gen_helper_neon_add_f32(CPU_T001);
4392 break;
4393 case 2: /* VSUB */
4394 gen_helper_neon_sub_f32(CPU_T001);
4395 break;
4396 case 4: /* VPADD */
4397 gen_helper_neon_add_f32(CPU_T001);
4398 break;
4399 case 6: /* VABD */
4400 gen_helper_neon_abd_f32(CPU_T001);
4401 break;
4402 default:
4403 return 1;
4405 break;
4406 case 27: /* Float multiply. */
4407 gen_helper_neon_mul_f32(CPU_T001);
4408 if (!u) {
4409 NEON_GET_REG(T1, rd, pass);
4410 if (size == 0) {
4411 gen_helper_neon_add_f32(CPU_T001);
4412 } else {
4413 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4416 break;
4417 case 28: /* Float compare. */
4418 if (!u) {
4419 gen_helper_neon_ceq_f32(CPU_T001);
4420 } else {
4421 if (size == 0)
4422 gen_helper_neon_cge_f32(CPU_T001);
4423 else
4424 gen_helper_neon_cgt_f32(CPU_T001);
4426 break;
4427 case 29: /* Float compare absolute. */
4428 if (!u)
4429 return 1;
4430 if (size == 0)
4431 gen_helper_neon_acge_f32(CPU_T001);
4432 else
4433 gen_helper_neon_acgt_f32(CPU_T001);
4434 break;
4435 case 30: /* Float min/max. */
4436 if (size == 0)
4437 gen_helper_neon_max_f32(CPU_T001);
4438 else
4439 gen_helper_neon_min_f32(CPU_T001);
4440 break;
4441 case 31:
4442 if (size == 0)
4443 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4444 else
4445 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4446 break;
4447 default:
4448 abort();
4450 /* Save the result. For elementwise operations we can put it
4451 straight into the destination register. For pairwise operations
4452 we have to be careful to avoid clobbering the source operands. */
4453 if (pairwise && rd == rm) {
4454 gen_neon_movl_scratch_T0(pass);
4455 } else {
4456 NEON_SET_REG(T0, rd, pass);
4459 } /* for pass */
4460 if (pairwise && rd == rm) {
4461 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4462 gen_neon_movl_T0_scratch(pass);
4463 NEON_SET_REG(T0, rd, pass);
4466 /* End of 3 register same size operations. */
4467 } else if (insn & (1 << 4)) {
4468 if ((insn & 0x00380080) != 0) {
4469 /* Two registers and shift. */
4470 op = (insn >> 8) & 0xf;
4471 if (insn & (1 << 7)) {
4472 /* 64-bit shift. */
4473 size = 3;
4474 } else {
4475 size = 2;
4476 while ((insn & (1 << (size + 19))) == 0)
4477 size--;
4479 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4480 /* To avoid excessive dumplication of ops we implement shift
4481 by immediate using the variable shift operations. */
4482 if (op < 8) {
4483 /* Shift by immediate:
4484 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4485 /* Right shifts are encoded as N - shift, where N is the
4486 element size in bits. */
4487 if (op <= 4)
4488 shift = shift - (1 << (size + 3));
4489 if (size == 3) {
4490 count = q + 1;
4491 } else {
4492 count = q ? 4: 2;
4494 switch (size) {
4495 case 0:
4496 imm = (uint8_t) shift;
4497 imm |= imm << 8;
4498 imm |= imm << 16;
4499 break;
4500 case 1:
4501 imm = (uint16_t) shift;
4502 imm |= imm << 16;
4503 break;
4504 case 2:
4505 case 3:
4506 imm = shift;
4507 break;
4508 default:
4509 abort();
4512 for (pass = 0; pass < count; pass++) {
4513 if (size == 3) {
4514 neon_load_reg64(cpu_V0, rm + pass);
4515 tcg_gen_movi_i64(cpu_V1, imm);
4516 switch (op) {
4517 case 0: /* VSHR */
4518 case 1: /* VSRA */
4519 if (u)
4520 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4521 else
4522 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4523 break;
4524 case 2: /* VRSHR */
4525 case 3: /* VRSRA */
4526 if (u)
4527 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4528 else
4529 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4530 break;
4531 case 4: /* VSRI */
4532 if (!u)
4533 return 1;
4534 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4535 break;
4536 case 5: /* VSHL, VSLI */
4537 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4538 break;
4539 case 6: /* VQSHL */
4540 if (u)
4541 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4542 else
4543 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4544 break;
4545 case 7: /* VQSHLU */
4546 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4547 break;
4549 if (op == 1 || op == 3) {
4550 /* Accumulate. */
4551 neon_load_reg64(cpu_V0, rd + pass);
4552 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4553 } else if (op == 4 || (op == 5 && u)) {
4554 /* Insert */
4555 cpu_abort(env, "VS[LR]I.64 not implemented");
4557 neon_store_reg64(cpu_V0, rd + pass);
4558 } else { /* size < 3 */
4559 /* Operands in T0 and T1. */
4560 gen_op_movl_T1_im(imm);
4561 NEON_GET_REG(T0, rm, pass);
4562 switch (op) {
4563 case 0: /* VSHR */
4564 case 1: /* VSRA */
4565 GEN_NEON_INTEGER_OP(shl);
4566 break;
4567 case 2: /* VRSHR */
4568 case 3: /* VRSRA */
4569 GEN_NEON_INTEGER_OP(rshl);
4570 break;
4571 case 4: /* VSRI */
4572 if (!u)
4573 return 1;
4574 GEN_NEON_INTEGER_OP(shl);
4575 break;
4576 case 5: /* VSHL, VSLI */
4577 switch (size) {
4578 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4579 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4580 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4581 default: return 1;
4583 break;
4584 case 6: /* VQSHL */
4585 GEN_NEON_INTEGER_OP_ENV(qshl);
4586 break;
4587 case 7: /* VQSHLU */
4588 switch (size) {
4589 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4590 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4591 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4592 default: return 1;
4594 break;
4597 if (op == 1 || op == 3) {
4598 /* Accumulate. */
4599 NEON_GET_REG(T1, rd, pass);
4600 gen_neon_add(size);
4601 } else if (op == 4 || (op == 5 && u)) {
4602 /* Insert */
4603 switch (size) {
4604 case 0:
4605 if (op == 4)
4606 imm = 0xff >> -shift;
4607 else
4608 imm = (uint8_t)(0xff << shift);
4609 imm |= imm << 8;
4610 imm |= imm << 16;
4611 break;
4612 case 1:
4613 if (op == 4)
4614 imm = 0xffff >> -shift;
4615 else
4616 imm = (uint16_t)(0xffff << shift);
4617 imm |= imm << 16;
4618 break;
4619 case 2:
4620 if (op == 4)
4621 imm = 0xffffffffu >> -shift;
4622 else
4623 imm = 0xffffffffu << shift;
4624 break;
4625 default:
4626 abort();
4628 tmp = neon_load_reg(rd, pass);
4629 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4630 tcg_gen_andi_i32(tmp, tmp, ~imm);
4631 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4633 NEON_SET_REG(T0, rd, pass);
4635 } /* for pass */
4636 } else if (op < 10) {
4637 /* Shift by immediate and narrow:
4638 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4639 shift = shift - (1 << (size + 3));
4640 size++;
4641 switch (size) {
4642 case 1:
4643 imm = (uint16_t)shift;
4644 imm |= imm << 16;
4645 tmp2 = tcg_const_i32(imm);
4646 break;
4647 case 2:
4648 imm = (uint32_t)shift;
4649 tmp2 = tcg_const_i32(imm);
4650 case 3:
4651 tmp2 = tcg_const_i64(shift);
4652 break;
4653 default:
4654 abort();
4657 for (pass = 0; pass < 2; pass++) {
4658 if (size == 3) {
4659 neon_load_reg64(cpu_V0, rm + pass);
4660 if (q) {
4661 if (u)
4662 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp2);
4663 else
4664 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp2);
4665 } else {
4666 if (u)
4667 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp2);
4668 else
4669 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp2);
4671 } else {
4672 tmp = neon_load_reg(rm + pass, 0);
4673 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4674 tcg_gen_extu_i32_i64(cpu_V0, tmp);
4675 dead_tmp(tmp);
4676 tmp = neon_load_reg(rm + pass, 1);
4677 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4678 tcg_gen_extu_i32_i64(cpu_V1, tmp);
4679 dead_tmp(tmp);
4680 tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
4681 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4683 tmp = new_tmp();
4684 if (op == 8 && !u) {
4685 gen_neon_narrow(size - 1, tmp, cpu_V0);
4686 } else {
4687 if (op == 8)
4688 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4689 else
4690 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4692 if (pass == 0) {
4693 tmp2 = tmp;
4694 } else {
4695 neon_store_reg(rd, 0, tmp2);
4696 neon_store_reg(rd, 1, tmp);
4698 } /* for pass */
4699 } else if (op == 10) {
4700 /* VSHLL */
4701 if (q || size == 3)
4702 return 1;
4703 tmp = neon_load_reg(rm, 0);
4704 tmp2 = neon_load_reg(rm, 1);
4705 for (pass = 0; pass < 2; pass++) {
4706 if (pass == 1)
4707 tmp = tmp2;
4709 gen_neon_widen(cpu_V0, tmp, size, u);
4711 if (shift != 0) {
4712 /* The shift is less than the width of the source
4713 type, so we can just shift the whole register. */
4714 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4715 if (size < 2 || !u) {
4716 uint64_t imm64;
4717 if (size == 0) {
4718 imm = (0xffu >> (8 - shift));
4719 imm |= imm << 16;
4720 } else {
4721 imm = 0xffff >> (16 - shift);
4723 imm64 = imm | (((uint64_t)imm) << 32);
4724 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4727 neon_store_reg64(cpu_V0, rd + pass);
4729 } else if (op == 15 || op == 16) {
4730 /* VCVT fixed-point. */
4731 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4732 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4733 if (op & 1) {
4734 if (u)
4735 gen_vfp_ulto(0, shift);
4736 else
4737 gen_vfp_slto(0, shift);
4738 } else {
4739 if (u)
4740 gen_vfp_toul(0, shift);
4741 else
4742 gen_vfp_tosl(0, shift);
4744 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4746 } else {
4747 return 1;
4749 } else { /* (insn & 0x00380080) == 0 */
4750 int invert;
4752 op = (insn >> 8) & 0xf;
4753 /* One register and immediate. */
4754 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4755 invert = (insn & (1 << 5)) != 0;
4756 switch (op) {
4757 case 0: case 1:
4758 /* no-op */
4759 break;
4760 case 2: case 3:
4761 imm <<= 8;
4762 break;
4763 case 4: case 5:
4764 imm <<= 16;
4765 break;
4766 case 6: case 7:
4767 imm <<= 24;
4768 break;
4769 case 8: case 9:
4770 imm |= imm << 16;
4771 break;
4772 case 10: case 11:
4773 imm = (imm << 8) | (imm << 24);
4774 break;
4775 case 12:
4776 imm = (imm < 8) | 0xff;
4777 break;
4778 case 13:
4779 imm = (imm << 16) | 0xffff;
4780 break;
4781 case 14:
4782 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4783 if (invert)
4784 imm = ~imm;
4785 break;
4786 case 15:
4787 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4788 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4789 break;
4791 if (invert)
4792 imm = ~imm;
4794 if (op != 14 || !invert)
4795 gen_op_movl_T1_im(imm);
4797 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4798 if (op & 1 && op < 12) {
4799 tmp = neon_load_reg(rd, pass);
4800 if (invert) {
4801 /* The immediate value has already been inverted, so
4802 BIC becomes AND. */
4803 tcg_gen_andi_i32(tmp, tmp, imm);
4804 } else {
4805 tcg_gen_ori_i32(tmp, tmp, imm);
4807 } else {
4808 /* VMOV, VMVN. */
4809 tmp = new_tmp();
4810 if (op == 14 && invert) {
4811 uint32_t val;
4812 val = 0;
4813 for (n = 0; n < 4; n++) {
4814 if (imm & (1 << (n + (pass & 1) * 4)))
4815 val |= 0xff << (n * 8);
4817 tcg_gen_movi_i32(tmp, val);
4818 } else {
4819 tcg_gen_movi_i32(tmp, imm);
4822 neon_store_reg(rd, pass, tmp);
4825 } else { /* (insn & 0x00800010 == 0x00800010) */
4826 if (size != 3) {
4827 op = (insn >> 8) & 0xf;
4828 if ((insn & (1 << 6)) == 0) {
4829 /* Three registers of different lengths. */
4830 int src1_wide;
4831 int src2_wide;
4832 int prewiden;
4833 /* prewiden, src1_wide, src2_wide */
4834 static const int neon_3reg_wide[16][3] = {
4835 {1, 0, 0}, /* VADDL */
4836 {1, 1, 0}, /* VADDW */
4837 {1, 0, 0}, /* VSUBL */
4838 {1, 1, 0}, /* VSUBW */
4839 {0, 1, 1}, /* VADDHN */
4840 {0, 0, 0}, /* VABAL */
4841 {0, 1, 1}, /* VSUBHN */
4842 {0, 0, 0}, /* VABDL */
4843 {0, 0, 0}, /* VMLAL */
4844 {0, 0, 0}, /* VQDMLAL */
4845 {0, 0, 0}, /* VMLSL */
4846 {0, 0, 0}, /* VQDMLSL */
4847 {0, 0, 0}, /* Integer VMULL */
4848 {0, 0, 0}, /* VQDMULL */
4849 {0, 0, 0} /* Polynomial VMULL */
4852 prewiden = neon_3reg_wide[op][0];
4853 src1_wide = neon_3reg_wide[op][1];
4854 src2_wide = neon_3reg_wide[op][2];
4856 if (size == 0 && (op == 9 || op == 11 || op == 13))
4857 return 1;
4859 /* Avoid overlapping operands. Wide source operands are
4860 always aligned so will never overlap with wide
4861 destinations in problematic ways. */
4862 if (rd == rm && !src2_wide) {
4863 NEON_GET_REG(T0, rm, 1);
4864 gen_neon_movl_scratch_T0(2);
4865 } else if (rd == rn && !src1_wide) {
4866 NEON_GET_REG(T0, rn, 1);
4867 gen_neon_movl_scratch_T0(2);
4869 for (pass = 0; pass < 2; pass++) {
4870 if (src1_wide) {
4871 neon_load_reg64(cpu_V0, rn + pass);
4872 } else {
4873 if (pass == 1 && rd == rn) {
4874 gen_neon_movl_T0_scratch(2);
4875 tmp = new_tmp();
4876 tcg_gen_mov_i32(tmp, cpu_T[0]);
4877 } else {
4878 tmp = neon_load_reg(rn, pass);
4880 if (prewiden) {
4881 gen_neon_widen(cpu_V0, tmp, size, u);
4884 if (src2_wide) {
4885 neon_load_reg64(cpu_V1, rm + pass);
4886 } else {
4887 if (pass == 1 && rd == rm) {
4888 gen_neon_movl_T0_scratch(2);
4889 tmp2 = new_tmp();
4890 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4891 } else {
4892 tmp2 = neon_load_reg(rm, pass);
4894 if (prewiden) {
4895 gen_neon_widen(cpu_V1, tmp2, size, u);
4898 switch (op) {
4899 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4900 gen_neon_addl(size);
4901 break;
4902 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4903 gen_neon_subl(size);
4904 break;
4905 case 5: case 7: /* VABAL, VABDL */
4906 switch ((size << 1) | u) {
4907 case 0:
4908 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4909 break;
4910 case 1:
4911 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4912 break;
4913 case 2:
4914 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4915 break;
4916 case 3:
4917 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4918 break;
4919 case 4:
4920 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4921 break;
4922 case 5:
4923 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4924 break;
4925 default: abort();
4927 dead_tmp(tmp2);
4928 dead_tmp(tmp);
4929 break;
4930 case 8: case 9: case 10: case 11: case 12: case 13:
4931 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4932 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4933 break;
4934 case 14: /* Polynomial VMULL */
4935 cpu_abort(env, "Polynomial VMULL not implemented");
4937 default: /* 15 is RESERVED. */
4938 return 1;
4940 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4941 /* Accumulate. */
4942 if (op == 10 || op == 11) {
4943 gen_neon_negl(cpu_V0, size);
4946 if (op != 13) {
4947 neon_load_reg64(cpu_V1, rd + pass);
4950 switch (op) {
4951 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4952 gen_neon_addl(size);
4953 break;
4954 case 9: case 11: /* VQDMLAL, VQDMLSL */
4955 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4956 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4957 break;
4958 /* Fall through. */
4959 case 13: /* VQDMULL */
4960 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4961 break;
4962 default:
4963 abort();
4965 neon_store_reg64(cpu_V0, rd + pass);
4966 } else if (op == 4 || op == 6) {
4967 /* Narrowing operation. */
4968 tmp = new_tmp();
4969 if (u) {
4970 switch (size) {
4971 case 0:
4972 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4973 break;
4974 case 1:
4975 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4976 break;
4977 case 2:
4978 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4979 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4980 break;
4981 default: abort();
4983 } else {
4984 switch (size) {
4985 case 0:
4986 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4987 break;
4988 case 1:
4989 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4990 break;
4991 case 2:
4992 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4993 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4994 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4995 break;
4996 default: abort();
4999 if (pass == 0) {
5000 tmp3 = tmp;
5001 } else {
5002 neon_store_reg(rd, 0, tmp3);
5003 neon_store_reg(rd, 1, tmp);
5005 } else {
5006 /* Write back the result. */
5007 neon_store_reg64(cpu_V0, rd + pass);
5010 } else {
5011 /* Two registers and a scalar. */
5012 switch (op) {
5013 case 0: /* Integer VMLA scalar */
5014 case 1: /* Float VMLA scalar */
5015 case 4: /* Integer VMLS scalar */
5016 case 5: /* Floating point VMLS scalar */
5017 case 8: /* Integer VMUL scalar */
5018 case 9: /* Floating point VMUL scalar */
5019 case 12: /* VQDMULH scalar */
5020 case 13: /* VQRDMULH scalar */
5021 gen_neon_get_scalar(size, rm);
5022 gen_neon_movl_scratch_T0(0);
5023 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5024 if (pass != 0)
5025 gen_neon_movl_T0_scratch(0);
5026 NEON_GET_REG(T1, rn, pass);
5027 if (op == 12) {
5028 if (size == 1) {
5029 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5030 } else {
5031 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5033 } else if (op == 13) {
5034 if (size == 1) {
5035 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5036 } else {
5037 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5039 } else if (op & 1) {
5040 gen_helper_neon_mul_f32(CPU_T001);
5041 } else {
5042 switch (size) {
5043 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5044 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5045 case 2: gen_op_mul_T0_T1(); break;
5046 default: return 1;
5049 if (op < 8) {
5050 /* Accumulate. */
5051 NEON_GET_REG(T1, rd, pass);
5052 switch (op) {
5053 case 0:
5054 gen_neon_add(size);
5055 break;
5056 case 1:
5057 gen_helper_neon_add_f32(CPU_T001);
5058 break;
5059 case 4:
5060 gen_neon_rsb(size);
5061 break;
5062 case 5:
5063 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5064 break;
5065 default:
5066 abort();
5069 NEON_SET_REG(T0, rd, pass);
5071 break;
5072 case 2: /* VMLAL sclar */
5073 case 3: /* VQDMLAL scalar */
5074 case 6: /* VMLSL scalar */
5075 case 7: /* VQDMLSL scalar */
5076 case 10: /* VMULL scalar */
5077 case 11: /* VQDMULL scalar */
5078 if (size == 0 && (op == 3 || op == 7 || op == 11))
5079 return 1;
5081 gen_neon_get_scalar(size, rm);
5082 NEON_GET_REG(T1, rn, 1);
5084 for (pass = 0; pass < 2; pass++) {
5085 if (pass == 0) {
5086 tmp = neon_load_reg(rn, 0);
5087 } else {
5088 tmp = new_tmp();
5089 tcg_gen_mov_i32(tmp, cpu_T[1]);
5091 tmp2 = new_tmp();
5092 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5093 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5094 if (op == 6 || op == 7) {
5095 gen_neon_negl(cpu_V0, size);
5097 if (op != 11) {
5098 neon_load_reg64(cpu_V1, rd + pass);
5100 switch (op) {
5101 case 2: case 6:
5102 gen_neon_addl(size);
5103 break;
5104 case 3: case 7:
5105 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5106 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5107 break;
5108 case 10:
5109 /* no-op */
5110 break;
5111 case 11:
5112 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5113 break;
5114 default:
5115 abort();
5117 neon_store_reg64(cpu_V0, rd + pass);
5119 break;
5120 default: /* 14 and 15 are RESERVED */
5121 return 1;
5124 } else { /* size == 3 */
5125 if (!u) {
5126 /* Extract. */
5127 imm = (insn >> 8) & 0xf;
5128 count = q + 1;
5130 if (imm > 7 && !q)
5131 return 1;
5133 if (imm == 0) {
5134 neon_load_reg64(cpu_V0, rn);
5135 if (q) {
5136 neon_load_reg64(cpu_V1, rn + 1);
5138 } else if (imm == 8) {
5139 neon_load_reg64(cpu_V0, rn + 1);
5140 if (q) {
5141 neon_load_reg64(cpu_V1, rm);
5143 } else if (q) {
5144 tmp = tcg_temp_new(TCG_TYPE_I64);
5145 if (imm < 8) {
5146 neon_load_reg64(cpu_V0, rn);
5147 neon_load_reg64(tmp, rn + 1);
5148 } else {
5149 neon_load_reg64(cpu_V0, rn + 1);
5150 neon_load_reg64(tmp, rm);
5152 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5153 tcg_gen_shli_i64(cpu_V1, tmp, 64 - ((imm & 7) * 8));
5154 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5155 if (imm < 8) {
5156 neon_load_reg64(cpu_V1, rm);
5157 } else {
5158 neon_load_reg64(cpu_V1, rm + 1);
5159 imm -= 8;
5161 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5162 tcg_gen_shri_i64(tmp, tmp, imm * 8);
5163 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp);
5164 } else {
5165 neon_load_reg64(cpu_V0, rn);
5166 tcg_gen_shri_i32(cpu_V0, cpu_V0, imm * 8);
5167 neon_load_reg64(cpu_V1, rm);
5168 tcg_gen_shli_i32(cpu_V1, cpu_V1, 64 - (imm * 8));
5169 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5171 neon_store_reg64(cpu_V0, rd);
5172 if (q) {
5173 neon_store_reg64(cpu_V1, rd + 1);
5175 } else if ((insn & (1 << 11)) == 0) {
5176 /* Two register misc. */
5177 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5178 size = (insn >> 18) & 3;
5179 switch (op) {
5180 case 0: /* VREV64 */
5181 if (size == 3)
5182 return 1;
5183 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5184 NEON_GET_REG(T0, rm, pass * 2);
5185 NEON_GET_REG(T1, rm, pass * 2 + 1);
5186 switch (size) {
5187 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5188 case 1: gen_swap_half(cpu_T[0]); break;
5189 case 2: /* no-op */ break;
5190 default: abort();
5192 NEON_SET_REG(T0, rd, pass * 2 + 1);
5193 if (size == 2) {
5194 NEON_SET_REG(T1, rd, pass * 2);
5195 } else {
5196 gen_op_movl_T0_T1();
5197 switch (size) {
5198 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5199 case 1: gen_swap_half(cpu_T[0]); break;
5200 default: abort();
5202 NEON_SET_REG(T0, rd, pass * 2);
5205 break;
5206 case 4: case 5: /* VPADDL */
5207 case 12: case 13: /* VPADAL */
5208 if (size == 3)
5209 return 1;
5210 for (pass = 0; pass < q + 1; pass++) {
5211 tmp = neon_load_reg(rm, pass * 2);
5212 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5213 tmp = neon_load_reg(rm, pass * 2 + 1);
5214 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5215 switch (size) {
5216 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5217 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5218 case 2: tcg_gen_add_i64(CPU_V001); break;
5219 default: abort();
5221 if (op >= 12) {
5222 /* Accumulate. */
5223 neon_load_reg64(cpu_V1, rd + pass);
5224 gen_neon_addl(size);
5226 neon_store_reg64(cpu_V0, rd + pass);
5228 break;
5229 case 33: /* VTRN */
5230 if (size == 2) {
5231 for (n = 0; n < (q ? 4 : 2); n += 2) {
5232 NEON_GET_REG(T0, rm, n);
5233 NEON_GET_REG(T1, rd, n + 1);
5234 NEON_SET_REG(T1, rm, n);
5235 NEON_SET_REG(T0, rd, n + 1);
5237 } else {
5238 goto elementwise;
5240 break;
5241 case 34: /* VUZP */
5242 /* Reg Before After
5243 Rd A3 A2 A1 A0 B2 B0 A2 A0
5244 Rm B3 B2 B1 B0 B3 B1 A3 A1
5246 if (size == 3)
5247 return 1;
5248 gen_neon_unzip(rd, q, 0, size);
5249 gen_neon_unzip(rm, q, 4, size);
5250 if (q) {
5251 static int unzip_order_q[8] =
5252 {0, 2, 4, 6, 1, 3, 5, 7};
5253 for (n = 0; n < 8; n++) {
5254 int reg = (n < 4) ? rd : rm;
5255 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5256 NEON_SET_REG(T0, reg, n % 4);
5258 } else {
5259 static int unzip_order[4] =
5260 {0, 4, 1, 5};
5261 for (n = 0; n < 4; n++) {
5262 int reg = (n < 2) ? rd : rm;
5263 gen_neon_movl_T0_scratch(unzip_order[n]);
5264 NEON_SET_REG(T0, reg, n % 2);
5267 break;
5268 case 35: /* VZIP */
5269 /* Reg Before After
5270 Rd A3 A2 A1 A0 B1 A1 B0 A0
5271 Rm B3 B2 B1 B0 B3 A3 B2 A2
5273 if (size == 3)
5274 return 1;
5275 count = (q ? 4 : 2);
5276 for (n = 0; n < count; n++) {
5277 NEON_GET_REG(T0, rd, n);
5278 NEON_GET_REG(T1, rd, n);
5279 switch (size) {
5280 case 0: gen_helper_neon_zip_u8(); break;
5281 case 1: gen_helper_neon_zip_u16(); break;
5282 case 2: /* no-op */; break;
5283 default: abort();
5285 gen_neon_movl_scratch_T0(n * 2);
5286 gen_neon_movl_scratch_T1(n * 2 + 1);
5288 for (n = 0; n < count * 2; n++) {
5289 int reg = (n < count) ? rd : rm;
5290 gen_neon_movl_T0_scratch(n);
5291 NEON_SET_REG(T0, reg, n % count);
5293 break;
5294 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5295 if (size == 3)
5296 return 1;
5297 for (pass = 0; pass < 2; pass++) {
5298 neon_load_reg64(cpu_V0, rm + pass);
5299 tmp = new_tmp();
5300 if (op == 36 && q == 0) {
5301 gen_neon_narrow(size, tmp, cpu_V0);
5302 } else if (q) {
5303 gen_neon_narrow_satu(size, tmp, cpu_V0);
5304 } else {
5305 gen_neon_narrow_sats(size, tmp, cpu_V0);
5307 if (pass == 0) {
5308 tmp2 = tmp;
5309 } else {
5310 neon_store_reg(rd, 0, tmp2);
5311 neon_store_reg(rd, 1, tmp);
5314 break;
5315 case 38: /* VSHLL */
5316 if (q || size == 3)
5317 return 1;
5318 tmp = neon_load_reg(rm, 0);
5319 tmp2 = neon_load_reg(rm, 1);
5320 for (pass = 0; pass < 2; pass++) {
5321 if (pass == 1)
5322 tmp = tmp2;
5323 gen_neon_widen(cpu_V0, tmp, size, 1);
5324 neon_store_reg64(cpu_V0, rd + pass);
5326 break;
5327 default:
5328 elementwise:
5329 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5330 if (op == 30 || op == 31 || op >= 58) {
5331 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5332 neon_reg_offset(rm, pass));
5333 } else {
5334 NEON_GET_REG(T0, rm, pass);
5336 switch (op) {
5337 case 1: /* VREV32 */
5338 switch (size) {
5339 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5340 case 1: gen_swap_half(cpu_T[0]); break;
5341 default: return 1;
5343 break;
5344 case 2: /* VREV16 */
5345 if (size != 0)
5346 return 1;
5347 gen_rev16(cpu_T[0]);
5348 break;
5349 case 8: /* CLS */
5350 switch (size) {
5351 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5352 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5353 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5354 default: return 1;
5356 break;
5357 case 9: /* CLZ */
5358 switch (size) {
5359 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5360 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5361 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5362 default: return 1;
5364 break;
5365 case 10: /* CNT */
5366 if (size != 0)
5367 return 1;
5368 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5369 break;
5370 case 11: /* VNOT */
5371 if (size != 0)
5372 return 1;
5373 gen_op_notl_T0();
5374 break;
5375 case 14: /* VQABS */
5376 switch (size) {
5377 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5378 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5379 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5380 default: return 1;
5382 break;
5383 case 15: /* VQNEG */
5384 switch (size) {
5385 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5386 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5387 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5388 default: return 1;
5390 break;
5391 case 16: case 19: /* VCGT #0, VCLE #0 */
5392 gen_op_movl_T1_im(0);
5393 switch(size) {
5394 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5395 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5396 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5397 default: return 1;
5399 if (op == 19)
5400 gen_op_notl_T0();
5401 break;
5402 case 17: case 20: /* VCGE #0, VCLT #0 */
5403 gen_op_movl_T1_im(0);
5404 switch(size) {
5405 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5406 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5407 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5408 default: return 1;
5410 if (op == 20)
5411 gen_op_notl_T0();
5412 break;
5413 case 18: /* VCEQ #0 */
5414 gen_op_movl_T1_im(0);
5415 switch(size) {
5416 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5417 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5418 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5419 default: return 1;
5421 break;
5422 case 22: /* VABS */
5423 switch(size) {
5424 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5425 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5426 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5427 default: return 1;
5429 break;
5430 case 23: /* VNEG */
5431 gen_op_movl_T1_im(0);
5432 if (size == 3)
5433 return 1;
5434 gen_neon_rsb(size);
5435 break;
5436 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5437 gen_op_movl_T1_im(0);
5438 gen_helper_neon_cgt_f32(CPU_T001);
5439 if (op == 27)
5440 gen_op_notl_T0();
5441 break;
5442 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5443 gen_op_movl_T1_im(0);
5444 gen_helper_neon_cge_f32(CPU_T001);
5445 if (op == 28)
5446 gen_op_notl_T0();
5447 break;
5448 case 26: /* Float VCEQ #0 */
5449 gen_op_movl_T1_im(0);
5450 gen_helper_neon_ceq_f32(CPU_T001);
5451 break;
5452 case 30: /* Float VABS */
5453 gen_vfp_abs(0);
5454 break;
5455 case 31: /* Float VNEG */
5456 gen_vfp_neg(0);
5457 break;
5458 case 32: /* VSWP */
5459 NEON_GET_REG(T1, rd, pass);
5460 NEON_SET_REG(T1, rm, pass);
5461 break;
5462 case 33: /* VTRN */
5463 NEON_GET_REG(T1, rd, pass);
5464 switch (size) {
5465 case 0: gen_helper_neon_trn_u8(); break;
5466 case 1: gen_helper_neon_trn_u16(); break;
5467 case 2: abort();
5468 default: return 1;
5470 NEON_SET_REG(T1, rm, pass);
5471 break;
5472 case 56: /* Integer VRECPE */
5473 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5474 break;
5475 case 57: /* Integer VRSQRTE */
5476 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5477 break;
5478 case 58: /* Float VRECPE */
5479 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5480 break;
5481 case 59: /* Float VRSQRTE */
5482 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5483 break;
5484 case 60: /* VCVT.F32.S32 */
5485 gen_vfp_tosiz(0);
5486 break;
5487 case 61: /* VCVT.F32.U32 */
5488 gen_vfp_touiz(0);
5489 break;
5490 case 62: /* VCVT.S32.F32 */
5491 gen_vfp_sito(0);
5492 break;
5493 case 63: /* VCVT.U32.F32 */
5494 gen_vfp_uito(0);
5495 break;
5496 default:
5497 /* Reserved: 21, 29, 39-56 */
5498 return 1;
5500 if (op == 30 || op == 31 || op >= 58) {
5501 tcg_gen_st_f32(cpu_F0s, cpu_env,
5502 neon_reg_offset(rd, pass));
5503 } else {
5504 NEON_SET_REG(T0, rd, pass);
5507 break;
5509 } else if ((insn & (1 << 10)) == 0) {
5510 /* VTBL, VTBX. */
5511 n = (insn >> 5) & 0x18;
5512 if (insn & (1 << 6)) {
5513 tmp = neon_load_reg(rd, 0);
5514 } else {
5515 tmp = new_tmp();
5516 tcg_gen_movi_i32(tmp, 0);
5518 tmp2 = neon_load_reg(rm, 0);
5519 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5520 tcg_const_i32(n));
5521 if (insn & (1 << 6)) {
5522 tmp = neon_load_reg(rd, 1);
5523 } else {
5524 tmp = new_tmp();
5525 tcg_gen_movi_i32(tmp, 0);
5527 tmp3 = neon_load_reg(rm, 1);
5528 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5529 tcg_const_i32(n));
5530 neon_store_reg(rd, 0, tmp2);
5531 neon_store_reg(rd, 1, tmp2);
5532 } else if ((insn & 0x380) == 0) {
5533 /* VDUP */
5534 if (insn & (1 << 19)) {
5535 NEON_SET_REG(T0, rm, 1);
5536 } else {
5537 NEON_SET_REG(T0, rm, 0);
5539 if (insn & (1 << 16)) {
5540 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5541 } else if (insn & (1 << 17)) {
5542 if ((insn >> 18) & 1)
5543 gen_neon_dup_high16(cpu_T[0]);
5544 else
5545 gen_neon_dup_low16(cpu_T[0]);
5547 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5548 NEON_SET_REG(T0, rd, pass);
5550 } else {
5551 return 1;
5555 return 0;
5558 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5560 int cpnum;
5562 cpnum = (insn >> 8) & 0xf;
5563 if (arm_feature(env, ARM_FEATURE_XSCALE)
5564 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5565 return 1;
5567 switch (cpnum) {
5568 case 0:
5569 case 1:
5570 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5571 return disas_iwmmxt_insn(env, s, insn);
5572 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5573 return disas_dsp_insn(env, s, insn);
5575 return 1;
5576 case 10:
5577 case 11:
5578 return disas_vfp_insn (env, s, insn);
5579 case 15:
5580 return disas_cp15_insn (env, s, insn);
5581 default:
5582 /* Unknown coprocessor. See if the board has hooked it. */
5583 return disas_cp_insn (env, s, insn);
5588 /* Store a 64-bit value to a register pair. Clobbers val. */
5589 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv val)
5591 TCGv tmp;
5592 tmp = new_tmp();
5593 tcg_gen_trunc_i64_i32(tmp, val);
5594 store_reg(s, rlow, tmp);
5595 tmp = new_tmp();
5596 tcg_gen_shri_i64(val, val, 32);
5597 tcg_gen_trunc_i64_i32(tmp, val);
5598 store_reg(s, rhigh, tmp);
5601 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5602 static void gen_addq_lo(DisasContext *s, TCGv val, int rlow)
5604 TCGv tmp;
5605 TCGv tmp2;
5607 /* Load 64-bit value rd:rn. */
5608 tmp = tcg_temp_new(TCG_TYPE_I64);
5609 tmp2 = load_reg(s, rlow);
5610 tcg_gen_extu_i32_i64(tmp, tmp2);
5611 dead_tmp(tmp2);
5612 tcg_gen_add_i64(val, val, tmp);
5615 /* load and add a 64-bit value from a register pair. */
5616 static void gen_addq(DisasContext *s, TCGv val, int rlow, int rhigh)
5618 TCGv tmp;
5619 TCGv tmp2;
5621 /* Load 64-bit value rd:rn. */
5622 tmp = tcg_temp_new(TCG_TYPE_I64);
5623 tmp2 = load_reg(s, rhigh);
5624 tcg_gen_extu_i32_i64(tmp, tmp2);
5625 dead_tmp(tmp2);
5626 tcg_gen_shli_i64(tmp, tmp, 32);
5627 tcg_gen_add_i64(val, val, tmp);
5629 tmp2 = load_reg(s, rlow);
5630 tcg_gen_extu_i32_i64(tmp, tmp2);
5631 dead_tmp(tmp2);
5632 tcg_gen_add_i64(val, val, tmp);
5635 /* Set N and Z flags from a 64-bit value. */
5636 static void gen_logicq_cc(TCGv val)
5638 TCGv tmp = new_tmp();
5639 gen_helper_logicq_cc(tmp, val);
5640 gen_logic_CC(tmp);
5641 dead_tmp(tmp);
5644 static void disas_arm_insn(CPUState * env, DisasContext *s)
5646 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5647 TCGv tmp;
5648 TCGv tmp2;
5649 TCGv tmp3;
5650 TCGv addr;
5652 insn = ldl_code(s->pc);
5653 s->pc += 4;
5655 /* M variants do not implement ARM mode. */
5656 if (IS_M(env))
5657 goto illegal_op;
5658 cond = insn >> 28;
5659 if (cond == 0xf){
5660 /* Unconditional instructions. */
5661 if (((insn >> 25) & 7) == 1) {
5662 /* NEON Data processing. */
5663 if (!arm_feature(env, ARM_FEATURE_NEON))
5664 goto illegal_op;
5666 if (disas_neon_data_insn(env, s, insn))
5667 goto illegal_op;
5668 return;
5670 if ((insn & 0x0f100000) == 0x04000000) {
5671 /* NEON load/store. */
5672 if (!arm_feature(env, ARM_FEATURE_NEON))
5673 goto illegal_op;
5675 if (disas_neon_ls_insn(env, s, insn))
5676 goto illegal_op;
5677 return;
5679 if ((insn & 0x0d70f000) == 0x0550f000)
5680 return; /* PLD */
5681 else if ((insn & 0x0ffffdff) == 0x01010000) {
5682 ARCH(6);
5683 /* setend */
5684 if (insn & (1 << 9)) {
5685 /* BE8 mode not implemented. */
5686 goto illegal_op;
5688 return;
5689 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5690 switch ((insn >> 4) & 0xf) {
5691 case 1: /* clrex */
5692 ARCH(6K);
5693 gen_helper_clrex(cpu_env);
5694 return;
5695 case 4: /* dsb */
5696 case 5: /* dmb */
5697 case 6: /* isb */
5698 ARCH(7);
5699 /* We don't emulate caches so these are a no-op. */
5700 return;
5701 default:
5702 goto illegal_op;
5704 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5705 /* srs */
5706 uint32_t offset;
5707 if (IS_USER(s))
5708 goto illegal_op;
5709 ARCH(6);
5710 op1 = (insn & 0x1f);
5711 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5712 addr = load_reg(s, 13);
5713 } else {
5714 addr = new_tmp();
5715 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5717 i = (insn >> 23) & 3;
5718 switch (i) {
5719 case 0: offset = -4; break; /* DA */
5720 case 1: offset = -8; break; /* DB */
5721 case 2: offset = 0; break; /* IA */
5722 case 3: offset = 4; break; /* IB */
5723 default: abort();
5725 if (offset)
5726 tcg_gen_addi_i32(addr, addr, offset);
5727 tmp = load_reg(s, 14);
5728 gen_st32(tmp, addr, 0);
5729 tmp = new_tmp();
5730 gen_helper_cpsr_read(tmp);
5731 tcg_gen_addi_i32(addr, addr, 4);
5732 gen_st32(tmp, addr, 0);
5733 if (insn & (1 << 21)) {
5734 /* Base writeback. */
5735 switch (i) {
5736 case 0: offset = -8; break;
5737 case 1: offset = -4; break;
5738 case 2: offset = 4; break;
5739 case 3: offset = 0; break;
5740 default: abort();
5742 if (offset)
5743 tcg_gen_addi_i32(addr, tmp, offset);
5744 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5745 gen_movl_reg_T1(s, 13);
5746 } else {
5747 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5749 } else {
5750 dead_tmp(addr);
5752 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5753 /* rfe */
5754 uint32_t offset;
5755 if (IS_USER(s))
5756 goto illegal_op;
5757 ARCH(6);
5758 rn = (insn >> 16) & 0xf;
5759 addr = load_reg(s, rn);
5760 i = (insn >> 23) & 3;
5761 switch (i) {
5762 case 0: offset = -4; break; /* DA */
5763 case 1: offset = -8; break; /* DB */
5764 case 2: offset = 0; break; /* IA */
5765 case 3: offset = 4; break; /* IB */
5766 default: abort();
5768 if (offset)
5769 tcg_gen_addi_i32(addr, addr, offset);
5770 /* Load PC into tmp and CPSR into tmp2. */
5771 tmp = gen_ld32(addr, 0);
5772 tcg_gen_addi_i32(addr, addr, 4);
5773 tmp2 = gen_ld32(addr, 0);
5774 if (insn & (1 << 21)) {
5775 /* Base writeback. */
5776 switch (i) {
5777 case 0: offset = -8; break;
5778 case 1: offset = -4; break;
5779 case 2: offset = 4; break;
5780 case 3: offset = 0; break;
5781 default: abort();
5783 if (offset)
5784 tcg_gen_addi_i32(addr, addr, offset);
5785 store_reg(s, rn, addr);
5786 } else {
5787 dead_tmp(addr);
5789 gen_rfe(s, tmp, tmp2);
5790 } else if ((insn & 0x0e000000) == 0x0a000000) {
5791 /* branch link and change to thumb (blx <offset>) */
5792 int32_t offset;
5794 val = (uint32_t)s->pc;
5795 tmp = new_tmp();
5796 tcg_gen_movi_i32(tmp, val);
5797 store_reg(s, 14, tmp);
5798 /* Sign-extend the 24-bit offset */
5799 offset = (((int32_t)insn) << 8) >> 8;
5800 /* offset * 4 + bit24 * 2 + (thumb bit) */
5801 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5802 /* pipeline offset */
5803 val += 4;
5804 gen_bx_im(s, val);
5805 return;
5806 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5807 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5808 /* iWMMXt register transfer. */
5809 if (env->cp15.c15_cpar & (1 << 1))
5810 if (!disas_iwmmxt_insn(env, s, insn))
5811 return;
5813 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5814 /* Coprocessor double register transfer. */
5815 } else if ((insn & 0x0f000010) == 0x0e000010) {
5816 /* Additional coprocessor register transfer. */
5817 } else if ((insn & 0x0ff10010) == 0x01000000) {
5818 uint32_t mask;
5819 uint32_t val;
5820 /* cps (privileged) */
5821 if (IS_USER(s))
5822 return;
5823 mask = val = 0;
5824 if (insn & (1 << 19)) {
5825 if (insn & (1 << 8))
5826 mask |= CPSR_A;
5827 if (insn & (1 << 7))
5828 mask |= CPSR_I;
5829 if (insn & (1 << 6))
5830 mask |= CPSR_F;
5831 if (insn & (1 << 18))
5832 val |= mask;
5834 if (insn & (1 << 14)) {
5835 mask |= CPSR_M;
5836 val |= (insn & 0x1f);
5838 if (mask) {
5839 gen_op_movl_T0_im(val);
5840 gen_set_psr_T0(s, mask, 0);
5842 return;
5844 goto illegal_op;
5846 if (cond != 0xe) {
5847 /* if not always execute, we generate a conditional jump to
5848 next instruction */
5849 s->condlabel = gen_new_label();
5850 gen_test_cc(cond ^ 1, s->condlabel);
5851 s->condjmp = 1;
5853 if ((insn & 0x0f900000) == 0x03000000) {
5854 if ((insn & (1 << 21)) == 0) {
5855 ARCH(6T2);
5856 rd = (insn >> 12) & 0xf;
5857 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5858 if ((insn & (1 << 22)) == 0) {
5859 /* MOVW */
5860 tmp = new_tmp();
5861 tcg_gen_movi_i32(tmp, val);
5862 } else {
5863 /* MOVT */
5864 tmp = load_reg(s, rd);
5865 tcg_gen_andi_i32(tmp, tmp, 0xffff);
5866 tcg_gen_ori_i32(tmp, tmp, val << 16);
5868 store_reg(s, rd, tmp);
5869 } else {
5870 if (((insn >> 12) & 0xf) != 0xf)
5871 goto illegal_op;
5872 if (((insn >> 16) & 0xf) == 0) {
5873 gen_nop_hint(s, insn & 0xff);
5874 } else {
5875 /* CPSR = immediate */
5876 val = insn & 0xff;
5877 shift = ((insn >> 8) & 0xf) * 2;
5878 if (shift)
5879 val = (val >> shift) | (val << (32 - shift));
5880 gen_op_movl_T0_im(val);
5881 i = ((insn & (1 << 22)) != 0);
5882 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5883 goto illegal_op;
5886 } else if ((insn & 0x0f900000) == 0x01000000
5887 && (insn & 0x00000090) != 0x00000090) {
5888 /* miscellaneous instructions */
5889 op1 = (insn >> 21) & 3;
5890 sh = (insn >> 4) & 0xf;
5891 rm = insn & 0xf;
5892 switch (sh) {
5893 case 0x0: /* move program status register */
5894 if (op1 & 1) {
5895 /* PSR = reg */
5896 gen_movl_T0_reg(s, rm);
5897 i = ((op1 & 2) != 0);
5898 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5899 goto illegal_op;
5900 } else {
5901 /* reg = PSR */
5902 rd = (insn >> 12) & 0xf;
5903 if (op1 & 2) {
5904 if (IS_USER(s))
5905 goto illegal_op;
5906 tmp = load_cpu_field(spsr);
5907 } else {
5908 tmp = new_tmp();
5909 gen_helper_cpsr_read(tmp);
5911 store_reg(s, rd, tmp);
5913 break;
5914 case 0x1:
5915 if (op1 == 1) {
5916 /* branch/exchange thumb (bx). */
5917 tmp = load_reg(s, rm);
5918 gen_bx(s, tmp);
5919 } else if (op1 == 3) {
5920 /* clz */
5921 rd = (insn >> 12) & 0xf;
5922 tmp = load_reg(s, rm);
5923 gen_helper_clz(tmp, tmp);
5924 store_reg(s, rd, tmp);
5925 } else {
5926 goto illegal_op;
5928 break;
5929 case 0x2:
5930 if (op1 == 1) {
5931 ARCH(5J); /* bxj */
5932 /* Trivial implementation equivalent to bx. */
5933 tmp = load_reg(s, rm);
5934 gen_bx(s, tmp);
5935 } else {
5936 goto illegal_op;
5938 break;
5939 case 0x3:
5940 if (op1 != 1)
5941 goto illegal_op;
5943 /* branch link/exchange thumb (blx) */
5944 tmp = load_reg(s, rm);
5945 tmp2 = new_tmp();
5946 tcg_gen_movi_i32(tmp2, s->pc);
5947 store_reg(s, 14, tmp2);
5948 gen_bx(s, tmp);
5949 break;
5950 case 0x5: /* saturating add/subtract */
5951 rd = (insn >> 12) & 0xf;
5952 rn = (insn >> 16) & 0xf;
5953 tmp = load_reg(s, rn);
5954 tmp2 = load_reg(s, rn);
5955 if (op1 & 2)
5956 gen_helper_double_saturate(tmp2, tmp2);
5957 if (op1 & 1)
5958 gen_helper_sub_saturate(tmp, tmp, tmp2);
5959 else
5960 gen_helper_add_saturate(tmp, tmp, tmp2);
5961 dead_tmp(tmp2);
5962 store_reg(s, rd, tmp);
5963 break;
5964 case 7: /* bkpt */
5965 gen_set_condexec(s);
5966 gen_set_pc_im(s->pc - 4);
5967 gen_exception(EXCP_BKPT);
5968 s->is_jmp = DISAS_JUMP;
5969 break;
5970 case 0x8: /* signed multiply */
5971 case 0xa:
5972 case 0xc:
5973 case 0xe:
5974 rs = (insn >> 8) & 0xf;
5975 rn = (insn >> 12) & 0xf;
5976 rd = (insn >> 16) & 0xf;
5977 if (op1 == 1) {
5978 /* (32 * 16) >> 16 */
5979 tmp = load_reg(s, rm);
5980 tmp2 = load_reg(s, rs);
5981 if (sh & 4)
5982 tcg_gen_sari_i32(tmp2, tmp2, 16);
5983 else
5984 gen_sxth(tmp2);
5985 tmp2 = gen_muls_i64_i32(tmp, tmp2);
5986 tcg_gen_shri_i64(tmp2, tmp2, 16);
5987 tmp = new_tmp();
5988 tcg_gen_trunc_i64_i32(tmp, tmp2);
5989 if ((sh & 2) == 0) {
5990 tmp2 = load_reg(s, rn);
5991 gen_helper_add_setq(tmp, tmp, tmp2);
5992 dead_tmp(tmp2);
5994 store_reg(s, rd, tmp);
5995 } else {
5996 /* 16 * 16 */
5997 tmp = load_reg(s, rm);
5998 tmp2 = load_reg(s, rs);
5999 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6000 dead_tmp(tmp2);
6001 if (op1 == 2) {
6002 tmp = tcg_temp_new(TCG_TYPE_I64);
6003 tcg_gen_ext_i32_i64(tmp, cpu_T[0]);
6004 gen_addq(s, tmp, rn, rd);
6005 gen_storeq_reg(s, rn, rd, tmp);
6006 } else {
6007 if (op1 == 0) {
6008 tmp2 = load_reg(s, rn);
6009 gen_helper_add_setq(tmp, tmp, tmp2);
6010 dead_tmp(tmp2);
6012 store_reg(s, rd, tmp);
6015 break;
6016 default:
6017 goto illegal_op;
6019 } else if (((insn & 0x0e000000) == 0 &&
6020 (insn & 0x00000090) != 0x90) ||
6021 ((insn & 0x0e000000) == (1 << 25))) {
6022 int set_cc, logic_cc, shiftop;
6024 op1 = (insn >> 21) & 0xf;
6025 set_cc = (insn >> 20) & 1;
6026 logic_cc = table_logic_cc[op1] & set_cc;
6028 /* data processing instruction */
6029 if (insn & (1 << 25)) {
6030 /* immediate operand */
6031 val = insn & 0xff;
6032 shift = ((insn >> 8) & 0xf) * 2;
6033 if (shift)
6034 val = (val >> shift) | (val << (32 - shift));
6035 gen_op_movl_T1_im(val);
6036 if (logic_cc && shift)
6037 gen_set_CF_bit31(cpu_T[1]);
6038 } else {
6039 /* register */
6040 rm = (insn) & 0xf;
6041 gen_movl_T1_reg(s, rm);
6042 shiftop = (insn >> 5) & 3;
6043 if (!(insn & (1 << 4))) {
6044 shift = (insn >> 7) & 0x1f;
6045 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
6046 } else {
6047 rs = (insn >> 8) & 0xf;
6048 tmp = load_reg(s, rs);
6049 gen_arm_shift_reg(cpu_T[1], shiftop, tmp, logic_cc);
6052 if (op1 != 0x0f && op1 != 0x0d) {
6053 rn = (insn >> 16) & 0xf;
6054 gen_movl_T0_reg(s, rn);
6056 rd = (insn >> 12) & 0xf;
6057 switch(op1) {
6058 case 0x00:
6059 gen_op_andl_T0_T1();
6060 gen_movl_reg_T0(s, rd);
6061 if (logic_cc)
6062 gen_op_logic_T0_cc();
6063 break;
6064 case 0x01:
6065 gen_op_xorl_T0_T1();
6066 gen_movl_reg_T0(s, rd);
6067 if (logic_cc)
6068 gen_op_logic_T0_cc();
6069 break;
6070 case 0x02:
6071 if (set_cc && rd == 15) {
6072 /* SUBS r15, ... is used for exception return. */
6073 if (IS_USER(s))
6074 goto illegal_op;
6075 gen_op_subl_T0_T1_cc();
6076 gen_exception_return(s);
6077 } else {
6078 if (set_cc)
6079 gen_op_subl_T0_T1_cc();
6080 else
6081 gen_op_subl_T0_T1();
6082 gen_movl_reg_T0(s, rd);
6084 break;
6085 case 0x03:
6086 if (set_cc)
6087 gen_op_rsbl_T0_T1_cc();
6088 else
6089 gen_op_rsbl_T0_T1();
6090 gen_movl_reg_T0(s, rd);
6091 break;
6092 case 0x04:
6093 if (set_cc)
6094 gen_op_addl_T0_T1_cc();
6095 else
6096 gen_op_addl_T0_T1();
6097 gen_movl_reg_T0(s, rd);
6098 break;
6099 case 0x05:
6100 if (set_cc)
6101 gen_op_adcl_T0_T1_cc();
6102 else
6103 gen_adc_T0_T1();
6104 gen_movl_reg_T0(s, rd);
6105 break;
6106 case 0x06:
6107 if (set_cc)
6108 gen_op_sbcl_T0_T1_cc();
6109 else
6110 gen_sbc_T0_T1();
6111 gen_movl_reg_T0(s, rd);
6112 break;
6113 case 0x07:
6114 if (set_cc)
6115 gen_op_rscl_T0_T1_cc();
6116 else
6117 gen_rsc_T0_T1();
6118 gen_movl_reg_T0(s, rd);
6119 break;
6120 case 0x08:
6121 if (set_cc) {
6122 gen_op_andl_T0_T1();
6123 gen_op_logic_T0_cc();
6125 break;
6126 case 0x09:
6127 if (set_cc) {
6128 gen_op_xorl_T0_T1();
6129 gen_op_logic_T0_cc();
6131 break;
6132 case 0x0a:
6133 if (set_cc) {
6134 gen_op_subl_T0_T1_cc();
6136 break;
6137 case 0x0b:
6138 if (set_cc) {
6139 gen_op_addl_T0_T1_cc();
6141 break;
6142 case 0x0c:
6143 gen_op_orl_T0_T1();
6144 gen_movl_reg_T0(s, rd);
6145 if (logic_cc)
6146 gen_op_logic_T0_cc();
6147 break;
6148 case 0x0d:
6149 if (logic_cc && rd == 15) {
6150 /* MOVS r15, ... is used for exception return. */
6151 if (IS_USER(s))
6152 goto illegal_op;
6153 gen_op_movl_T0_T1();
6154 gen_exception_return(s);
6155 } else {
6156 gen_movl_reg_T1(s, rd);
6157 if (logic_cc)
6158 gen_op_logic_T1_cc();
6160 break;
6161 case 0x0e:
6162 gen_op_bicl_T0_T1();
6163 gen_movl_reg_T0(s, rd);
6164 if (logic_cc)
6165 gen_op_logic_T0_cc();
6166 break;
6167 default:
6168 case 0x0f:
6169 gen_op_notl_T1();
6170 gen_movl_reg_T1(s, rd);
6171 if (logic_cc)
6172 gen_op_logic_T1_cc();
6173 break;
6175 } else {
6176 /* other instructions */
6177 op1 = (insn >> 24) & 0xf;
6178 switch(op1) {
6179 case 0x0:
6180 case 0x1:
6181 /* multiplies, extra load/stores */
6182 sh = (insn >> 5) & 3;
6183 if (sh == 0) {
6184 if (op1 == 0x0) {
6185 rd = (insn >> 16) & 0xf;
6186 rn = (insn >> 12) & 0xf;
6187 rs = (insn >> 8) & 0xf;
6188 rm = (insn) & 0xf;
6189 op1 = (insn >> 20) & 0xf;
6190 switch (op1) {
6191 case 0: case 1: case 2: case 3: case 6:
6192 /* 32 bit mul */
6193 tmp = load_reg(s, rs);
6194 tmp2 = load_reg(s, rm);
6195 tcg_gen_mul_i32(tmp, tmp, tmp2);
6196 dead_tmp(tmp2);
6197 if (insn & (1 << 22)) {
6198 /* Subtract (mls) */
6199 ARCH(6T2);
6200 tmp2 = load_reg(s, rn);
6201 tcg_gen_sub_i32(tmp, tmp2, tmp);
6202 dead_tmp(tmp2);
6203 } else if (insn & (1 << 21)) {
6204 /* Add */
6205 tmp2 = load_reg(s, rn);
6206 tcg_gen_add_i32(tmp, tmp, tmp2);
6207 dead_tmp(tmp2);
6209 if (insn & (1 << 20))
6210 gen_logic_CC(tmp);
6211 store_reg(s, rd, tmp);
6212 break;
6213 default:
6214 /* 64 bit mul */
6215 tmp = load_reg(s, rs);
6216 tmp2 = load_reg(s, rm);
6217 if (insn & (1 << 22))
6218 tmp = gen_muls_i64_i32(tmp, tmp2);
6219 else
6220 tmp = gen_mulu_i64_i32(tmp, tmp2);
6221 if (insn & (1 << 21)) /* mult accumulate */
6222 gen_addq(s, tmp, rn, rd);
6223 if (!(insn & (1 << 23))) { /* double accumulate */
6224 ARCH(6);
6225 gen_addq_lo(s, tmp, rn);
6226 gen_addq_lo(s, tmp, rd);
6228 if (insn & (1 << 20))
6229 gen_logicq_cc(tmp);
6230 gen_storeq_reg(s, rn, rd, tmp);
6231 break;
6233 } else {
6234 rn = (insn >> 16) & 0xf;
6235 rd = (insn >> 12) & 0xf;
6236 if (insn & (1 << 23)) {
6237 /* load/store exclusive */
6238 gen_movl_T1_reg(s, rn);
6239 addr = cpu_T[1];
6240 if (insn & (1 << 20)) {
6241 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6242 tmp = gen_ld32(addr, IS_USER(s));
6243 store_reg(s, rd, tmp);
6244 } else {
6245 int label = gen_new_label();
6246 rm = insn & 0xf;
6247 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6248 tcg_gen_brcond_i32(TCG_COND_NE, cpu_T[0],
6249 tcg_const_i32(0), label);
6250 tmp = load_reg(s,rm);
6251 gen_st32(tmp, cpu_T[1], IS_USER(s));
6252 gen_set_label(label);
6253 gen_movl_reg_T0(s, rd);
6255 } else {
6256 /* SWP instruction */
6257 rm = (insn) & 0xf;
6259 /* ??? This is not really atomic. However we know
6260 we never have multiple CPUs running in parallel,
6261 so it is good enough. */
6262 addr = load_reg(s, rn);
6263 tmp = load_reg(s, rm);
6264 if (insn & (1 << 22)) {
6265 tmp2 = gen_ld8u(addr, IS_USER(s));
6266 gen_st8(tmp, addr, IS_USER(s));
6267 } else {
6268 tmp2 = gen_ld32(addr, IS_USER(s));
6269 gen_st32(tmp, addr, IS_USER(s));
6271 dead_tmp(addr);
6272 store_reg(s, rd, tmp2);
6275 } else {
6276 int address_offset;
6277 int load;
6278 /* Misc load/store */
6279 rn = (insn >> 16) & 0xf;
6280 rd = (insn >> 12) & 0xf;
6281 addr = load_reg(s, rn);
6282 if (insn & (1 << 24))
6283 gen_add_datah_offset(s, insn, 0, addr);
6284 address_offset = 0;
6285 if (insn & (1 << 20)) {
6286 /* load */
6287 switch(sh) {
6288 case 1:
6289 tmp = gen_ld16u(addr, IS_USER(s));
6290 break;
6291 case 2:
6292 tmp = gen_ld8s(addr, IS_USER(s));
6293 break;
6294 default:
6295 case 3:
6296 tmp = gen_ld16s(addr, IS_USER(s));
6297 break;
6299 load = 1;
6300 } else if (sh & 2) {
6301 /* doubleword */
6302 if (sh & 1) {
6303 /* store */
6304 tmp = load_reg(s, rd);
6305 gen_st32(tmp, addr, IS_USER(s));
6306 tcg_gen_addi_i32(addr, addr, 4);
6307 tmp = load_reg(s, rd + 1);
6308 gen_st32(tmp, addr, IS_USER(s));
6309 load = 0;
6310 } else {
6311 /* load */
6312 tmp = gen_ld32(addr, IS_USER(s));
6313 store_reg(s, rd, tmp);
6314 tcg_gen_addi_i32(addr, addr, 4);
6315 tmp = gen_ld32(addr, IS_USER(s));
6316 rd++;
6317 load = 1;
6319 address_offset = -4;
6320 } else {
6321 /* store */
6322 tmp = load_reg(s, rd);
6323 gen_st16(tmp, addr, IS_USER(s));
6324 load = 0;
6326 /* Perform base writeback before the loaded value to
6327 ensure correct behavior with overlapping index registers.
6328 ldrd with base writeback is is undefined if the
6329 destination and index registers overlap. */
6330 if (!(insn & (1 << 24))) {
6331 gen_add_datah_offset(s, insn, address_offset, addr);
6332 store_reg(s, rn, addr);
6333 } else if (insn & (1 << 21)) {
6334 if (address_offset)
6335 tcg_gen_addi_i32(addr, addr, address_offset);
6336 store_reg(s, rn, addr);
6337 } else {
6338 dead_tmp(addr);
6340 if (load) {
6341 /* Complete the load. */
6342 store_reg(s, rd, tmp);
6345 break;
6346 case 0x4:
6347 case 0x5:
6348 goto do_ldst;
6349 case 0x6:
6350 case 0x7:
6351 if (insn & (1 << 4)) {
6352 ARCH(6);
6353 /* Armv6 Media instructions. */
6354 rm = insn & 0xf;
6355 rn = (insn >> 16) & 0xf;
6356 rd = (insn >> 12) & 0xf;
6357 rs = (insn >> 8) & 0xf;
6358 switch ((insn >> 23) & 3) {
6359 case 0: /* Parallel add/subtract. */
6360 op1 = (insn >> 20) & 7;
6361 tmp = load_reg(s, rn);
6362 tmp2 = load_reg(s, rm);
6363 sh = (insn >> 5) & 7;
6364 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6365 goto illegal_op;
6366 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6367 dead_tmp(tmp2);
6368 store_reg(s, rd, tmp);
6369 break;
6370 case 1:
6371 if ((insn & 0x00700020) == 0) {
6372 /* Halfword pack. */
6373 tmp = load_reg(s, rn);
6374 tmp2 = load_reg(s, rm);
6375 shift = (insn >> 7) & 0x1f;
6376 if (shift)
6377 tcg_gen_shli_i32(tmp2, tmp2, shift);
6378 if (insn & (1 << 6)) {
6379 /* pkhtb */
6380 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6381 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
6382 } else {
6383 /* pkhbt */
6384 tcg_gen_andi_i32(tmp, tmp, 0xffff);
6385 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6387 tcg_gen_or_i32(tmp, tmp, tmp2);
6388 store_reg(s, rd, tmp);
6389 } else if ((insn & 0x00200020) == 0x00200000) {
6390 /* [us]sat */
6391 tmp = load_reg(s, rm);
6392 shift = (insn >> 7) & 0x1f;
6393 if (insn & (1 << 6)) {
6394 if (shift == 0)
6395 shift = 31;
6396 tcg_gen_sari_i32(tmp, tmp, shift);
6397 } else {
6398 tcg_gen_shli_i32(tmp, tmp, shift);
6400 sh = (insn >> 16) & 0x1f;
6401 if (sh != 0) {
6402 if (insn & (1 << 22))
6403 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6404 else
6405 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6407 store_reg(s, rd, tmp);
6408 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6409 /* [us]sat16 */
6410 tmp = load_reg(s, rm);
6411 sh = (insn >> 16) & 0x1f;
6412 if (sh != 0) {
6413 if (insn & (1 << 22))
6414 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6415 else
6416 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6418 store_reg(s, rd, tmp);
6419 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6420 /* Select bytes. */
6421 tmp = load_reg(s, rn);
6422 tmp2 = load_reg(s, rm);
6423 tmp3 = new_tmp();
6424 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6425 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6426 dead_tmp(tmp3);
6427 dead_tmp(tmp2);
6428 store_reg(s, rd, tmp);
6429 } else if ((insn & 0x000003e0) == 0x00000060) {
6430 tmp = load_reg(s, rm);
6431 shift = (insn >> 10) & 3;
6432 /* ??? In many cases it's not neccessary to do a
6433 rotate, a shift is sufficient. */
6434 if (shift != 0)
6435 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6436 op1 = (insn >> 20) & 7;
6437 switch (op1) {
6438 case 0: gen_sxtb16(tmp); break;
6439 case 2: gen_sxtb(tmp); break;
6440 case 3: gen_sxth(tmp); break;
6441 case 4: gen_uxtb16(tmp); break;
6442 case 6: gen_uxtb(tmp); break;
6443 case 7: gen_uxth(tmp); break;
6444 default: goto illegal_op;
6446 if (rn != 15) {
6447 tmp2 = load_reg(s, rn);
6448 if ((op1 & 3) == 0) {
6449 gen_add16(tmp, tmp2);
6450 } else {
6451 tcg_gen_add_i32(tmp, tmp, tmp2);
6452 dead_tmp(tmp2);
6455 store_reg(s, rd, tmp);
6456 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6457 /* rev */
6458 tmp = load_reg(s, rm);
6459 if (insn & (1 << 22)) {
6460 if (insn & (1 << 7)) {
6461 gen_revsh(tmp);
6462 } else {
6463 ARCH(6T2);
6464 gen_helper_rbit(tmp, tmp);
6466 } else {
6467 if (insn & (1 << 7))
6468 gen_rev16(tmp);
6469 else
6470 tcg_gen_bswap_i32(tmp, tmp);
6472 store_reg(s, rd, tmp);
6473 } else {
6474 goto illegal_op;
6476 break;
6477 case 2: /* Multiplies (Type 3). */
6478 tmp = load_reg(s, rm);
6479 tmp2 = load_reg(s, rs);
6480 if (insn & (1 << 20)) {
6481 /* Signed multiply most significant [accumulate]. */
6482 tmp2 = gen_muls_i64_i32(tmp, tmp2);
6483 if (insn & (1 << 5))
6484 tcg_gen_addi_i64(tmp2, tmp2, 0x80000000u);
6485 tcg_gen_shri_i64(tmp2, tmp2, 32);
6486 tmp = new_tmp();
6487 tcg_gen_trunc_i64_i32(tmp, tmp2);
6488 if (rn != 15) {
6489 tmp2 = load_reg(s, rn);
6490 if (insn & (1 << 6)) {
6491 tcg_gen_sub_i32(tmp, tmp, tmp2);
6492 } else {
6493 tcg_gen_add_i32(tmp, tmp, tmp2);
6495 dead_tmp(tmp2);
6497 store_reg(s, rd, tmp);
6498 } else {
6499 if (insn & (1 << 5))
6500 gen_swap_half(tmp2);
6501 gen_smul_dual(tmp, tmp2);
6502 /* This addition cannot overflow. */
6503 if (insn & (1 << 6)) {
6504 tcg_gen_sub_i32(tmp, tmp, tmp2);
6505 } else {
6506 tcg_gen_add_i32(tmp, tmp, tmp2);
6508 dead_tmp(tmp2);
6509 if (insn & (1 << 22)) {
6510 /* smlald, smlsld */
6511 tmp2 = tcg_temp_new(TCG_TYPE_I64);
6512 tcg_gen_ext_i32_i64(tmp2, tmp);
6513 dead_tmp(tmp);
6514 gen_addq(s, tmp2, rn, rd);
6515 gen_storeq_reg(s, rn, rd, tmp2);
6516 } else {
6517 /* smuad, smusd, smlad, smlsd */
6518 if (rn != 15)
6520 tmp2 = load_reg(s, rn);
6521 gen_helper_add_setq(tmp, tmp, tmp2);
6522 dead_tmp(tmp2);
6524 store_reg(s, rd, tmp);
6527 break;
6528 case 3:
6529 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6530 switch (op1) {
6531 case 0: /* Unsigned sum of absolute differences. */
6532 ARCH(6);
6533 tmp = load_reg(s, rm);
6534 tmp2 = load_reg(s, rs);
6535 gen_helper_usad8(tmp, tmp, tmp2);
6536 dead_tmp(tmp2);
6537 if (rn != 15) {
6538 tmp2 = load_reg(s, rn);
6539 tcg_gen_add_i32(tmp, tmp, tmp2);
6540 dead_tmp(tmp2);
6542 store_reg(s, rd, tmp);
6543 break;
6544 case 0x20: case 0x24: case 0x28: case 0x2c:
6545 /* Bitfield insert/clear. */
6546 ARCH(6T2);
6547 shift = (insn >> 7) & 0x1f;
6548 i = (insn >> 16) & 0x1f;
6549 i = i + 1 - shift;
6550 if (rm == 15) {
6551 tmp = new_tmp();
6552 tcg_gen_movi_i32(tmp, 0);
6553 } else {
6554 tmp = load_reg(s, rm);
6556 if (i != 32) {
6557 tmp2 = load_reg(s, rd);
6558 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6559 dead_tmp(tmp2);
6561 store_reg(s, rd, tmp);
6562 break;
6563 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6564 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6565 tmp = load_reg(s, rm);
6566 shift = (insn >> 7) & 0x1f;
6567 i = ((insn >> 16) & 0x1f) + 1;
6568 if (shift + i > 32)
6569 goto illegal_op;
6570 if (i < 32) {
6571 if (op1 & 0x20) {
6572 gen_ubfx(tmp, shift, (1u << i) - 1);
6573 } else {
6574 gen_sbfx(tmp, shift, i);
6577 store_reg(s, rd, tmp);
6578 break;
6579 default:
6580 goto illegal_op;
6582 break;
6584 break;
6586 do_ldst:
6587 /* Check for undefined extension instructions
6588 * per the ARM Bible IE:
6589 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6591 sh = (0xf << 20) | (0xf << 4);
6592 if (op1 == 0x7 && ((insn & sh) == sh))
6594 goto illegal_op;
6596 /* load/store byte/word */
6597 rn = (insn >> 16) & 0xf;
6598 rd = (insn >> 12) & 0xf;
6599 tmp2 = load_reg(s, rn);
6600 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6601 if (insn & (1 << 24))
6602 gen_add_data_offset(s, insn, tmp2);
6603 if (insn & (1 << 20)) {
6604 /* load */
6605 s->is_mem = 1;
6606 if (insn & (1 << 22)) {
6607 tmp = gen_ld8u(tmp2, i);
6608 } else {
6609 tmp = gen_ld32(tmp2, i);
6611 } else {
6612 /* store */
6613 tmp = load_reg(s, rd);
6614 if (insn & (1 << 22))
6615 gen_st8(tmp, tmp2, i);
6616 else
6617 gen_st32(tmp, tmp2, i);
6619 if (!(insn & (1 << 24))) {
6620 gen_add_data_offset(s, insn, tmp2);
6621 store_reg(s, rn, tmp2);
6622 } else if (insn & (1 << 21)) {
6623 store_reg(s, rn, tmp2);
6624 } else {
6625 dead_tmp(tmp2);
6627 if (insn & (1 << 20)) {
6628 /* Complete the load. */
6629 if (rd == 15)
6630 gen_bx(s, tmp);
6631 else
6632 store_reg(s, rd, tmp);
6634 break;
6635 case 0x08:
6636 case 0x09:
6638 int j, n, user, loaded_base;
6639 TCGv loaded_var;
6640 /* load/store multiple words */
6641 /* XXX: store correct base if write back */
6642 user = 0;
6643 if (insn & (1 << 22)) {
6644 if (IS_USER(s))
6645 goto illegal_op; /* only usable in supervisor mode */
6647 if ((insn & (1 << 15)) == 0)
6648 user = 1;
6650 rn = (insn >> 16) & 0xf;
6651 addr = load_reg(s, rn);
6653 /* compute total size */
6654 loaded_base = 0;
6655 n = 0;
6656 for(i=0;i<16;i++) {
6657 if (insn & (1 << i))
6658 n++;
6660 /* XXX: test invalid n == 0 case ? */
6661 if (insn & (1 << 23)) {
6662 if (insn & (1 << 24)) {
6663 /* pre increment */
6664 tcg_gen_addi_i32(addr, addr, 4);
6665 } else {
6666 /* post increment */
6668 } else {
6669 if (insn & (1 << 24)) {
6670 /* pre decrement */
6671 tcg_gen_addi_i32(addr, addr, -(n * 4));
6672 } else {
6673 /* post decrement */
6674 if (n != 1)
6675 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6678 j = 0;
6679 for(i=0;i<16;i++) {
6680 if (insn & (1 << i)) {
6681 if (insn & (1 << 20)) {
6682 /* load */
6683 tmp = gen_ld32(addr, IS_USER(s));
6684 if (i == 15) {
6685 gen_bx(s, tmp);
6686 } else if (user) {
6687 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6688 dead_tmp(tmp);
6689 } else if (i == rn) {
6690 loaded_var = tmp;
6691 loaded_base = 1;
6692 } else {
6693 store_reg(s, i, tmp);
6695 } else {
6696 /* store */
6697 if (i == 15) {
6698 /* special case: r15 = PC + 8 */
6699 val = (long)s->pc + 4;
6700 tmp = new_tmp();
6701 tcg_gen_movi_i32(tmp, val);
6702 } else if (user) {
6703 tmp = new_tmp();
6704 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6705 } else {
6706 tmp = load_reg(s, i);
6708 gen_st32(tmp, addr, IS_USER(s));
6710 j++;
6711 /* no need to add after the last transfer */
6712 if (j != n)
6713 tcg_gen_addi_i32(addr, addr, 4);
6716 if (insn & (1 << 21)) {
6717 /* write back */
6718 if (insn & (1 << 23)) {
6719 if (insn & (1 << 24)) {
6720 /* pre increment */
6721 } else {
6722 /* post increment */
6723 tcg_gen_addi_i32(addr, addr, 4);
6725 } else {
6726 if (insn & (1 << 24)) {
6727 /* pre decrement */
6728 if (n != 1)
6729 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6730 } else {
6731 /* post decrement */
6732 tcg_gen_addi_i32(addr, addr, -(n * 4));
6735 store_reg(s, rn, addr);
6736 } else {
6737 dead_tmp(addr);
6739 if (loaded_base) {
6740 store_reg(s, rn, loaded_var);
6742 if ((insn & (1 << 22)) && !user) {
6743 /* Restore CPSR from SPSR. */
6744 tmp = load_cpu_field(spsr);
6745 gen_set_cpsr(tmp, 0xffffffff);
6746 dead_tmp(tmp);
6747 s->is_jmp = DISAS_UPDATE;
6750 break;
6751 case 0xa:
6752 case 0xb:
6754 int32_t offset;
6756 /* branch (and link) */
6757 val = (int32_t)s->pc;
6758 if (insn & (1 << 24)) {
6759 tmp = new_tmp();
6760 tcg_gen_movi_i32(tmp, val);
6761 store_reg(s, 14, tmp);
6763 offset = (((int32_t)insn << 8) >> 8);
6764 val += (offset << 2) + 4;
6765 gen_jmp(s, val);
6767 break;
6768 case 0xc:
6769 case 0xd:
6770 case 0xe:
6771 /* Coprocessor. */
6772 if (disas_coproc_insn(env, s, insn))
6773 goto illegal_op;
6774 break;
6775 case 0xf:
6776 /* swi */
6777 gen_set_pc_im(s->pc);
6778 s->is_jmp = DISAS_SWI;
6779 break;
6780 default:
6781 illegal_op:
6782 gen_set_condexec(s);
6783 gen_set_pc_im(s->pc - 4);
6784 gen_exception(EXCP_UDEF);
6785 s->is_jmp = DISAS_JUMP;
6786 break;
6791 /* Return true if this is a Thumb-2 logical op. */
6792 static int
6793 thumb2_logic_op(int op)
6795 return (op < 8);
6798 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6799 then set condition code flags based on the result of the operation.
6800 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6801 to the high bit of T1.
6802 Returns zero if the opcode is valid. */
6804 static int
6805 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6807 int logic_cc;
6809 logic_cc = 0;
6810 switch (op) {
6811 case 0: /* and */
6812 gen_op_andl_T0_T1();
6813 logic_cc = conds;
6814 break;
6815 case 1: /* bic */
6816 gen_op_bicl_T0_T1();
6817 logic_cc = conds;
6818 break;
6819 case 2: /* orr */
6820 gen_op_orl_T0_T1();
6821 logic_cc = conds;
6822 break;
6823 case 3: /* orn */
6824 gen_op_notl_T1();
6825 gen_op_orl_T0_T1();
6826 logic_cc = conds;
6827 break;
6828 case 4: /* eor */
6829 gen_op_xorl_T0_T1();
6830 logic_cc = conds;
6831 break;
6832 case 8: /* add */
6833 if (conds)
6834 gen_op_addl_T0_T1_cc();
6835 else
6836 gen_op_addl_T0_T1();
6837 break;
6838 case 10: /* adc */
6839 if (conds)
6840 gen_op_adcl_T0_T1_cc();
6841 else
6842 gen_adc_T0_T1();
6843 break;
6844 case 11: /* sbc */
6845 if (conds)
6846 gen_op_sbcl_T0_T1_cc();
6847 else
6848 gen_sbc_T0_T1();
6849 break;
6850 case 13: /* sub */
6851 if (conds)
6852 gen_op_subl_T0_T1_cc();
6853 else
6854 gen_op_subl_T0_T1();
6855 break;
6856 case 14: /* rsb */
6857 if (conds)
6858 gen_op_rsbl_T0_T1_cc();
6859 else
6860 gen_op_rsbl_T0_T1();
6861 break;
6862 default: /* 5, 6, 7, 9, 12, 15. */
6863 return 1;
6865 if (logic_cc) {
6866 gen_op_logic_T0_cc();
6867 if (shifter_out)
6868 gen_set_CF_bit31(cpu_T[1]);
6870 return 0;
6873 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6874 is not legal. */
6875 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6877 uint32_t insn, imm, shift, offset;
6878 uint32_t rd, rn, rm, rs;
6879 TCGv tmp;
6880 TCGv tmp2;
6881 TCGv tmp3;
6882 TCGv addr;
6883 int op;
6884 int shiftop;
6885 int conds;
6886 int logic_cc;
6888 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
6889 || arm_feature (env, ARM_FEATURE_M))) {
6890 /* Thumb-1 cores may need to treat bl and blx as a pair of
6891 16-bit instructions to get correct prefetch abort behavior. */
6892 insn = insn_hw1;
6893 if ((insn & (1 << 12)) == 0) {
6894 /* Second half of blx. */
6895 offset = ((insn & 0x7ff) << 1);
6896 tmp = load_reg(s, 14);
6897 tcg_gen_addi_i32(tmp, tmp, offset);
6898 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
6900 tmp2 = new_tmp();
6901 tcg_gen_movi_i32(tmp2, s->pc | 1);
6902 store_reg(s, 14, tmp2);
6903 gen_bx(s, tmp);
6904 return 0;
6906 if (insn & (1 << 11)) {
6907 /* Second half of bl. */
6908 offset = ((insn & 0x7ff) << 1) | 1;
6909 tmp = load_reg(s, 14);
6910 tcg_gen_addi_i32(tmp, tmp, offset);
6912 tmp2 = new_tmp();
6913 tcg_gen_movi_i32(tmp2, s->pc | 1);
6914 store_reg(s, 14, tmp2);
6915 gen_bx(s, tmp);
6916 return 0;
6918 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6919 /* Instruction spans a page boundary. Implement it as two
6920 16-bit instructions in case the second half causes an
6921 prefetch abort. */
6922 offset = ((int32_t)insn << 21) >> 9;
6923 gen_op_movl_T0_im(s->pc + 2 + offset);
6924 gen_movl_reg_T0(s, 14);
6925 return 0;
6927 /* Fall through to 32-bit decode. */
6930 insn = lduw_code(s->pc);
6931 s->pc += 2;
6932 insn |= (uint32_t)insn_hw1 << 16;
6934 if ((insn & 0xf800e800) != 0xf000e800) {
6935 ARCH(6T2);
6938 rn = (insn >> 16) & 0xf;
6939 rs = (insn >> 12) & 0xf;
6940 rd = (insn >> 8) & 0xf;
6941 rm = insn & 0xf;
6942 switch ((insn >> 25) & 0xf) {
6943 case 0: case 1: case 2: case 3:
6944 /* 16-bit instructions. Should never happen. */
6945 abort();
6946 case 4:
6947 if (insn & (1 << 22)) {
6948 /* Other load/store, table branch. */
6949 if (insn & 0x01200000) {
6950 /* Load/store doubleword. */
6951 if (rn == 15) {
6952 addr = new_tmp();
6953 tcg_gen_movi_i32(addr, s->pc & ~3);
6954 } else {
6955 addr = load_reg(s, rn);
6957 offset = (insn & 0xff) * 4;
6958 if ((insn & (1 << 23)) == 0)
6959 offset = -offset;
6960 if (insn & (1 << 24)) {
6961 tcg_gen_addi_i32(addr, addr, offset);
6962 offset = 0;
6964 if (insn & (1 << 20)) {
6965 /* ldrd */
6966 tmp = gen_ld32(addr, IS_USER(s));
6967 store_reg(s, rs, tmp);
6968 tcg_gen_addi_i32(addr, addr, 4);
6969 tmp = gen_ld32(addr, IS_USER(s));
6970 store_reg(s, rd, tmp);
6971 } else {
6972 /* strd */
6973 tmp = load_reg(s, rs);
6974 gen_st32(tmp, addr, IS_USER(s));
6975 tcg_gen_addi_i32(addr, addr, 4);
6976 tmp = load_reg(s, rd);
6977 gen_st32(tmp, addr, IS_USER(s));
6979 if (insn & (1 << 21)) {
6980 /* Base writeback. */
6981 if (rn == 15)
6982 goto illegal_op;
6983 tcg_gen_addi_i32(addr, addr, offset - 4);
6984 store_reg(s, rn, addr);
6985 } else {
6986 dead_tmp(addr);
6988 } else if ((insn & (1 << 23)) == 0) {
6989 /* Load/store exclusive word. */
6990 gen_movl_T1_reg(s, rn);
6991 addr = cpu_T[1];
6992 if (insn & (1 << 20)) {
6993 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6994 tmp = gen_ld32(addr, IS_USER(s));
6995 store_reg(s, rd, tmp);
6996 } else {
6997 int label = gen_new_label();
6998 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6999 tcg_gen_brcond_i32(TCG_COND_NE, cpu_T[0],
7000 tcg_const_i32(0), label);
7001 tmp = load_reg(s, rs);
7002 gen_st32(tmp, cpu_T[1], IS_USER(s));
7003 gen_set_label(label);
7004 gen_movl_reg_T0(s, rd);
7006 } else if ((insn & (1 << 6)) == 0) {
7007 /* Table Branch. */
7008 if (rn == 15) {
7009 addr = new_tmp();
7010 tcg_gen_movi_i32(addr, s->pc);
7011 } else {
7012 addr = load_reg(s, rn);
7014 tmp = load_reg(s, rm);
7015 tcg_gen_add_i32(addr, addr, tmp);
7016 if (insn & (1 << 4)) {
7017 /* tbh */
7018 tcg_gen_add_i32(addr, addr, tmp);
7019 dead_tmp(tmp);
7020 tmp = gen_ld16u(addr, IS_USER(s));
7021 } else { /* tbb */
7022 dead_tmp(tmp);
7023 tmp = gen_ld8u(addr, IS_USER(s));
7025 dead_tmp(addr);
7026 tcg_gen_shli_i32(tmp, tmp, 1);
7027 tcg_gen_addi_i32(tmp, tmp, s->pc);
7028 store_reg(s, 15, tmp);
7029 } else {
7030 /* Load/store exclusive byte/halfword/doubleword. */
7031 /* ??? These are not really atomic. However we know
7032 we never have multiple CPUs running in parallel,
7033 so it is good enough. */
7034 op = (insn >> 4) & 0x3;
7035 /* Must use a global reg for the address because we have
7036 a conditional branch in the store instruction. */
7037 gen_movl_T1_reg(s, rn);
7038 addr = cpu_T[1];
7039 if (insn & (1 << 20)) {
7040 gen_helper_mark_exclusive(cpu_env, addr);
7041 switch (op) {
7042 case 0:
7043 tmp = gen_ld8u(addr, IS_USER(s));
7044 break;
7045 case 1:
7046 tmp = gen_ld16u(addr, IS_USER(s));
7047 break;
7048 case 3:
7049 tmp = gen_ld32(addr, IS_USER(s));
7050 tcg_gen_addi_i32(addr, addr, 4);
7051 tmp2 = gen_ld32(addr, IS_USER(s));
7052 store_reg(s, rd, tmp2);
7053 break;
7054 default:
7055 goto illegal_op;
7057 store_reg(s, rs, tmp);
7058 } else {
7059 int label = gen_new_label();
7060 /* Must use a global that is not killed by the branch. */
7061 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7062 tcg_gen_brcond_i32(TCG_COND_NE, cpu_T[0], tcg_const_i32(0),
7063 label);
7064 tmp = load_reg(s, rs);
7065 switch (op) {
7066 case 0:
7067 gen_st8(tmp, addr, IS_USER(s));
7068 break;
7069 case 1:
7070 gen_st16(tmp, addr, IS_USER(s));
7071 break;
7072 case 3:
7073 gen_st32(tmp, addr, IS_USER(s));
7074 tcg_gen_addi_i32(addr, addr, 4);
7075 tmp = load_reg(s, rd);
7076 gen_st32(tmp, addr, IS_USER(s));
7077 break;
7078 default:
7079 goto illegal_op;
7081 gen_set_label(label);
7082 gen_movl_reg_T0(s, rm);
7085 } else {
7086 /* Load/store multiple, RFE, SRS. */
7087 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7088 /* Not available in user mode. */
7089 if (IS_USER(s))
7090 goto illegal_op;
7091 if (insn & (1 << 20)) {
7092 /* rfe */
7093 addr = load_reg(s, rn);
7094 if ((insn & (1 << 24)) == 0)
7095 tcg_gen_addi_i32(addr, addr, -8);
7096 /* Load PC into tmp and CPSR into tmp2. */
7097 tmp = gen_ld32(addr, 0);
7098 tcg_gen_addi_i32(addr, addr, 4);
7099 tmp2 = gen_ld32(addr, 0);
7100 if (insn & (1 << 21)) {
7101 /* Base writeback. */
7102 if (insn & (1 << 24)) {
7103 tcg_gen_addi_i32(addr, addr, 4);
7104 } else {
7105 tcg_gen_addi_i32(addr, addr, -4);
7107 store_reg(s, rn, addr);
7108 } else {
7109 dead_tmp(addr);
7111 gen_rfe(s, tmp, tmp2);
7112 } else {
7113 /* srs */
7114 op = (insn & 0x1f);
7115 if (op == (env->uncached_cpsr & CPSR_M)) {
7116 addr = load_reg(s, 13);
7117 } else {
7118 addr = new_tmp();
7119 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7121 if ((insn & (1 << 24)) == 0) {
7122 tcg_gen_addi_i32(addr, addr, -8);
7124 tmp = load_reg(s, 14);
7125 gen_st32(tmp, addr, 0);
7126 tcg_gen_addi_i32(addr, addr, 4);
7127 tmp = new_tmp();
7128 gen_helper_cpsr_read(tmp);
7129 gen_st32(tmp, addr, 0);
7130 if (insn & (1 << 21)) {
7131 if ((insn & (1 << 24)) == 0) {
7132 tcg_gen_addi_i32(addr, addr, -4);
7133 } else {
7134 tcg_gen_addi_i32(addr, addr, 4);
7136 if (op == (env->uncached_cpsr & CPSR_M)) {
7137 store_reg(s, 13, addr);
7138 } else {
7139 gen_helper_set_r13_banked(cpu_env,
7140 tcg_const_i32(op), addr);
7142 } else {
7143 dead_tmp(addr);
7146 } else {
7147 int i;
7148 /* Load/store multiple. */
7149 addr = load_reg(s, rn);
7150 offset = 0;
7151 for (i = 0; i < 16; i++) {
7152 if (insn & (1 << i))
7153 offset += 4;
7155 if (insn & (1 << 24)) {
7156 tcg_gen_addi_i32(addr, addr, -offset);
7159 for (i = 0; i < 16; i++) {
7160 if ((insn & (1 << i)) == 0)
7161 continue;
7162 if (insn & (1 << 20)) {
7163 /* Load. */
7164 tmp = gen_ld32(addr, IS_USER(s));
7165 if (i == 15) {
7166 gen_bx(s, tmp);
7167 } else {
7168 store_reg(s, i, tmp);
7170 } else {
7171 /* Store. */
7172 tmp = load_reg(s, i);
7173 gen_st32(tmp, addr, IS_USER(s));
7175 tcg_gen_addi_i32(addr, addr, 4);
7177 if (insn & (1 << 21)) {
7178 /* Base register writeback. */
7179 if (insn & (1 << 24)) {
7180 tcg_gen_addi_i32(addr, addr, -offset);
7182 /* Fault if writeback register is in register list. */
7183 if (insn & (1 << rn))
7184 goto illegal_op;
7185 store_reg(s, rn, addr);
7186 } else {
7187 dead_tmp(addr);
7191 break;
7192 case 5: /* Data processing register constant shift. */
7193 if (rn == 15)
7194 gen_op_movl_T0_im(0);
7195 else
7196 gen_movl_T0_reg(s, rn);
7197 gen_movl_T1_reg(s, rm);
7198 op = (insn >> 21) & 0xf;
7199 shiftop = (insn >> 4) & 3;
7200 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7201 conds = (insn & (1 << 20)) != 0;
7202 logic_cc = (conds && thumb2_logic_op(op));
7203 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7204 if (gen_thumb2_data_op(s, op, conds, 0))
7205 goto illegal_op;
7206 if (rd != 15)
7207 gen_movl_reg_T0(s, rd);
7208 break;
7209 case 13: /* Misc data processing. */
7210 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7211 if (op < 4 && (insn & 0xf000) != 0xf000)
7212 goto illegal_op;
7213 switch (op) {
7214 case 0: /* Register controlled shift. */
7215 tmp = load_reg(s, rn);
7216 tmp2 = load_reg(s, rm);
7217 if ((insn & 0x70) != 0)
7218 goto illegal_op;
7219 op = (insn >> 21) & 3;
7220 logic_cc = (insn & (1 << 20)) != 0;
7221 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7222 if (logic_cc)
7223 gen_logic_CC(tmp);
7224 store_reg(s, rd, tmp);
7225 break;
7226 case 1: /* Sign/zero extend. */
7227 tmp = load_reg(s, rm);
7228 shift = (insn >> 4) & 3;
7229 /* ??? In many cases it's not neccessary to do a
7230 rotate, a shift is sufficient. */
7231 if (shift != 0)
7232 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7233 op = (insn >> 20) & 7;
7234 switch (op) {
7235 case 0: gen_sxth(tmp); break;
7236 case 1: gen_uxth(tmp); break;
7237 case 2: gen_sxtb16(tmp); break;
7238 case 3: gen_uxtb16(tmp); break;
7239 case 4: gen_sxtb(tmp); break;
7240 case 5: gen_uxtb(tmp); break;
7241 default: goto illegal_op;
7243 if (rn != 15) {
7244 tmp2 = load_reg(s, rn);
7245 if ((op >> 1) == 1) {
7246 gen_add16(tmp, tmp2);
7247 } else {
7248 tcg_gen_add_i32(tmp, tmp, tmp2);
7249 dead_tmp(tmp2);
7252 store_reg(s, rd, tmp);
7253 break;
7254 case 2: /* SIMD add/subtract. */
7255 op = (insn >> 20) & 7;
7256 shift = (insn >> 4) & 7;
7257 if ((op & 3) == 3 || (shift & 3) == 3)
7258 goto illegal_op;
7259 tmp = load_reg(s, rn);
7260 tmp2 = load_reg(s, rm);
7261 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7262 dead_tmp(tmp2);
7263 store_reg(s, rd, tmp);
7264 break;
7265 case 3: /* Other data processing. */
7266 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7267 if (op < 4) {
7268 /* Saturating add/subtract. */
7269 tmp = load_reg(s, rn);
7270 tmp2 = load_reg(s, rm);
7271 if (op & 2)
7272 gen_helper_double_saturate(tmp, tmp);
7273 if (op & 1)
7274 gen_helper_sub_saturate(tmp, tmp2, tmp);
7275 else
7276 gen_helper_add_saturate(tmp, tmp, tmp2);
7277 dead_tmp(tmp2);
7278 } else {
7279 tmp = load_reg(s, rn);
7280 switch (op) {
7281 case 0x0a: /* rbit */
7282 gen_helper_rbit(tmp, tmp);
7283 break;
7284 case 0x08: /* rev */
7285 tcg_gen_bswap_i32(tmp, tmp);
7286 break;
7287 case 0x09: /* rev16 */
7288 gen_rev16(tmp);
7289 break;
7290 case 0x0b: /* revsh */
7291 gen_revsh(tmp);
7292 break;
7293 case 0x10: /* sel */
7294 tmp2 = load_reg(s, rm);
7295 tmp3 = new_tmp();
7296 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7297 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7298 dead_tmp(tmp3);
7299 dead_tmp(tmp2);
7300 break;
7301 case 0x18: /* clz */
7302 gen_helper_clz(tmp, tmp);
7303 break;
7304 default:
7305 goto illegal_op;
7308 store_reg(s, rd, tmp);
7309 break;
7310 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7311 op = (insn >> 4) & 0xf;
7312 tmp = load_reg(s, rn);
7313 tmp2 = load_reg(s, rm);
7314 switch ((insn >> 20) & 7) {
7315 case 0: /* 32 x 32 -> 32 */
7316 tcg_gen_mul_i32(tmp, tmp, tmp2);
7317 dead_tmp(tmp2);
7318 if (rs != 15) {
7319 tmp2 = load_reg(s, rs);
7320 if (op)
7321 tcg_gen_sub_i32(tmp, tmp2, tmp);
7322 else
7323 tcg_gen_add_i32(tmp, tmp, tmp2);
7324 dead_tmp(tmp2);
7326 break;
7327 case 1: /* 16 x 16 -> 32 */
7328 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7329 dead_tmp(tmp2);
7330 if (rs != 15) {
7331 tmp2 = load_reg(s, rs);
7332 gen_helper_add_setq(tmp, tmp, tmp2);
7333 dead_tmp(tmp2);
7335 break;
7336 case 2: /* Dual multiply add. */
7337 case 4: /* Dual multiply subtract. */
7338 if (op)
7339 gen_swap_half(tmp2);
7340 gen_smul_dual(tmp, tmp2);
7341 /* This addition cannot overflow. */
7342 if (insn & (1 << 22)) {
7343 tcg_gen_sub_i32(tmp, tmp, tmp2);
7344 } else {
7345 tcg_gen_add_i32(tmp, tmp, tmp2);
7347 dead_tmp(tmp2);
7348 if (rs != 15)
7350 tmp2 = load_reg(s, rs);
7351 gen_helper_add_setq(tmp, tmp, tmp2);
7352 dead_tmp(tmp2);
7354 break;
7355 case 3: /* 32 * 16 -> 32msb */
7356 if (op)
7357 tcg_gen_sari_i32(tmp2, tmp2, 16);
7358 else
7359 gen_sxth(tmp2);
7360 tmp2 = gen_muls_i64_i32(tmp, tmp2);
7361 tcg_gen_shri_i64(tmp2, tmp2, 16);
7362 tmp = new_tmp();
7363 tcg_gen_trunc_i64_i32(tmp, tmp2);
7364 if (rs != 15)
7366 tmp2 = load_reg(s, rs);
7367 gen_helper_add_setq(tmp, tmp, tmp2);
7368 dead_tmp(tmp2);
7370 break;
7371 case 5: case 6: /* 32 * 32 -> 32msb */
7372 gen_imull(tmp, tmp2);
7373 if (insn & (1 << 5)) {
7374 gen_roundqd(tmp, tmp2);
7375 dead_tmp(tmp2);
7376 } else {
7377 dead_tmp(tmp);
7378 tmp = tmp2;
7380 if (rs != 15) {
7381 tmp2 = load_reg(s, rs);
7382 if (insn & (1 << 21)) {
7383 tcg_gen_add_i32(tmp, tmp, tmp2);
7384 } else {
7385 tcg_gen_sub_i32(tmp, tmp2, tmp);
7387 dead_tmp(tmp2);
7389 break;
7390 case 7: /* Unsigned sum of absolute differences. */
7391 gen_helper_usad8(tmp, tmp, tmp2);
7392 dead_tmp(tmp2);
7393 if (rs != 15) {
7394 tmp2 = load_reg(s, rs);
7395 tcg_gen_add_i32(tmp, tmp, tmp2);
7396 dead_tmp(tmp2);
7398 break;
7400 store_reg(s, rd, tmp);
7401 break;
7402 case 6: case 7: /* 64-bit multiply, Divide. */
7403 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7404 tmp = load_reg(s, rn);
7405 tmp2 = load_reg(s, rm);
7406 if ((op & 0x50) == 0x10) {
7407 /* sdiv, udiv */
7408 if (!arm_feature(env, ARM_FEATURE_DIV))
7409 goto illegal_op;
7410 if (op & 0x20)
7411 gen_helper_udiv(tmp, tmp, tmp2);
7412 else
7413 gen_helper_sdiv(tmp, tmp, tmp2);
7414 dead_tmp(tmp2);
7415 store_reg(s, rd, tmp);
7416 } else if ((op & 0xe) == 0xc) {
7417 /* Dual multiply accumulate long. */
7418 if (op & 1)
7419 gen_swap_half(tmp2);
7420 gen_smul_dual(tmp, tmp2);
7421 if (op & 0x10) {
7422 tcg_gen_sub_i32(tmp, tmp, tmp2);
7423 } else {
7424 tcg_gen_add_i32(tmp, tmp, tmp2);
7426 dead_tmp(tmp2);
7427 tmp2 = tcg_temp_new(TCG_TYPE_I64);
7428 gen_addq(s, tmp, rs, rd);
7429 gen_storeq_reg(s, rs, rd, tmp);
7430 } else {
7431 if (op & 0x20) {
7432 /* Unsigned 64-bit multiply */
7433 tmp = gen_mulu_i64_i32(tmp, tmp2);
7434 } else {
7435 if (op & 8) {
7436 /* smlalxy */
7437 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7438 dead_tmp(tmp2);
7439 tmp2 = tcg_temp_new(TCG_TYPE_I64);
7440 tcg_gen_ext_i32_i64(tmp2, tmp);
7441 dead_tmp(tmp);
7442 tmp = tmp2;
7443 } else {
7444 /* Signed 64-bit multiply */
7445 tmp = gen_muls_i64_i32(tmp, tmp2);
7448 if (op & 4) {
7449 /* umaal */
7450 gen_addq_lo(s, tmp, rs);
7451 gen_addq_lo(s, tmp, rd);
7452 } else if (op & 0x40) {
7453 /* 64-bit accumulate. */
7454 gen_addq(s, tmp, rs, rd);
7456 gen_storeq_reg(s, rs, rd, tmp);
7458 break;
7460 break;
7461 case 6: case 7: case 14: case 15:
7462 /* Coprocessor. */
7463 if (((insn >> 24) & 3) == 3) {
7464 /* Translate into the equivalent ARM encoding. */
7465 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7466 if (disas_neon_data_insn(env, s, insn))
7467 goto illegal_op;
7468 } else {
7469 if (insn & (1 << 28))
7470 goto illegal_op;
7471 if (disas_coproc_insn (env, s, insn))
7472 goto illegal_op;
7474 break;
7475 case 8: case 9: case 10: case 11:
7476 if (insn & (1 << 15)) {
7477 /* Branches, misc control. */
7478 if (insn & 0x5000) {
7479 /* Unconditional branch. */
7480 /* signextend(hw1[10:0]) -> offset[:12]. */
7481 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7482 /* hw1[10:0] -> offset[11:1]. */
7483 offset |= (insn & 0x7ff) << 1;
7484 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7485 offset[24:22] already have the same value because of the
7486 sign extension above. */
7487 offset ^= ((~insn) & (1 << 13)) << 10;
7488 offset ^= ((~insn) & (1 << 11)) << 11;
7490 if (insn & (1 << 14)) {
7491 /* Branch and link. */
7492 gen_op_movl_T1_im(s->pc | 1);
7493 gen_movl_reg_T1(s, 14);
7496 offset += s->pc;
7497 if (insn & (1 << 12)) {
7498 /* b/bl */
7499 gen_jmp(s, offset);
7500 } else {
7501 /* blx */
7502 offset &= ~(uint32_t)2;
7503 gen_bx_im(s, offset);
7505 } else if (((insn >> 23) & 7) == 7) {
7506 /* Misc control */
7507 if (insn & (1 << 13))
7508 goto illegal_op;
7510 if (insn & (1 << 26)) {
7511 /* Secure monitor call (v6Z) */
7512 goto illegal_op; /* not implemented. */
7513 } else {
7514 op = (insn >> 20) & 7;
7515 switch (op) {
7516 case 0: /* msr cpsr. */
7517 if (IS_M(env)) {
7518 tmp = load_reg(s, rn);
7519 addr = tcg_const_i32(insn & 0xff);
7520 gen_helper_v7m_msr(cpu_env, addr, tmp);
7521 gen_lookup_tb(s);
7522 break;
7524 /* fall through */
7525 case 1: /* msr spsr. */
7526 if (IS_M(env))
7527 goto illegal_op;
7528 gen_movl_T0_reg(s, rn);
7529 if (gen_set_psr_T0(s,
7530 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7531 op == 1))
7532 goto illegal_op;
7533 break;
7534 case 2: /* cps, nop-hint. */
7535 if (((insn >> 8) & 7) == 0) {
7536 gen_nop_hint(s, insn & 0xff);
7538 /* Implemented as NOP in user mode. */
7539 if (IS_USER(s))
7540 break;
7541 offset = 0;
7542 imm = 0;
7543 if (insn & (1 << 10)) {
7544 if (insn & (1 << 7))
7545 offset |= CPSR_A;
7546 if (insn & (1 << 6))
7547 offset |= CPSR_I;
7548 if (insn & (1 << 5))
7549 offset |= CPSR_F;
7550 if (insn & (1 << 9))
7551 imm = CPSR_A | CPSR_I | CPSR_F;
7553 if (insn & (1 << 8)) {
7554 offset |= 0x1f;
7555 imm |= (insn & 0x1f);
7557 if (offset) {
7558 gen_op_movl_T0_im(imm);
7559 gen_set_psr_T0(s, offset, 0);
7561 break;
7562 case 3: /* Special control operations. */
7563 op = (insn >> 4) & 0xf;
7564 switch (op) {
7565 case 2: /* clrex */
7566 gen_helper_clrex(cpu_env);
7567 break;
7568 case 4: /* dsb */
7569 case 5: /* dmb */
7570 case 6: /* isb */
7571 /* These execute as NOPs. */
7572 ARCH(7);
7573 break;
7574 default:
7575 goto illegal_op;
7577 break;
7578 case 4: /* bxj */
7579 /* Trivial implementation equivalent to bx. */
7580 tmp = load_reg(s, rn);
7581 gen_bx(s, tmp);
7582 break;
7583 case 5: /* Exception return. */
7584 /* Unpredictable in user mode. */
7585 goto illegal_op;
7586 case 6: /* mrs cpsr. */
7587 tmp = new_tmp();
7588 if (IS_M(env)) {
7589 addr = tcg_const_i32(insn & 0xff);
7590 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7591 } else {
7592 gen_helper_cpsr_read(tmp);
7594 store_reg(s, rd, tmp);
7595 break;
7596 case 7: /* mrs spsr. */
7597 /* Not accessible in user mode. */
7598 if (IS_USER(s) || IS_M(env))
7599 goto illegal_op;
7600 tmp = load_cpu_field(spsr);
7601 store_reg(s, rd, tmp);
7602 break;
7605 } else {
7606 /* Conditional branch. */
7607 op = (insn >> 22) & 0xf;
7608 /* Generate a conditional jump to next instruction. */
7609 s->condlabel = gen_new_label();
7610 gen_test_cc(op ^ 1, s->condlabel);
7611 s->condjmp = 1;
7613 /* offset[11:1] = insn[10:0] */
7614 offset = (insn & 0x7ff) << 1;
7615 /* offset[17:12] = insn[21:16]. */
7616 offset |= (insn & 0x003f0000) >> 4;
7617 /* offset[31:20] = insn[26]. */
7618 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7619 /* offset[18] = insn[13]. */
7620 offset |= (insn & (1 << 13)) << 5;
7621 /* offset[19] = insn[11]. */
7622 offset |= (insn & (1 << 11)) << 8;
7624 /* jump to the offset */
7625 gen_jmp(s, s->pc + offset);
7627 } else {
7628 /* Data processing immediate. */
7629 if (insn & (1 << 25)) {
7630 if (insn & (1 << 24)) {
7631 if (insn & (1 << 20))
7632 goto illegal_op;
7633 /* Bitfield/Saturate. */
7634 op = (insn >> 21) & 7;
7635 imm = insn & 0x1f;
7636 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7637 if (rn == 15) {
7638 tmp = new_tmp();
7639 tcg_gen_movi_i32(tmp, 0);
7640 } else {
7641 tmp = load_reg(s, rn);
7643 switch (op) {
7644 case 2: /* Signed bitfield extract. */
7645 imm++;
7646 if (shift + imm > 32)
7647 goto illegal_op;
7648 if (imm < 32)
7649 gen_sbfx(tmp, shift, imm);
7650 break;
7651 case 6: /* Unsigned bitfield extract. */
7652 imm++;
7653 if (shift + imm > 32)
7654 goto illegal_op;
7655 if (imm < 32)
7656 gen_ubfx(tmp, shift, (1u << imm) - 1);
7657 break;
7658 case 3: /* Bitfield insert/clear. */
7659 if (imm < shift)
7660 goto illegal_op;
7661 imm = imm + 1 - shift;
7662 if (imm != 32) {
7663 tmp2 = load_reg(s, rd);
7664 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7665 dead_tmp(tmp2);
7667 break;
7668 case 7:
7669 goto illegal_op;
7670 default: /* Saturate. */
7671 if (shift) {
7672 if (op & 1)
7673 tcg_gen_sari_i32(tmp, tmp, shift);
7674 else
7675 tcg_gen_shli_i32(tmp, tmp, shift);
7677 tmp2 = tcg_const_i32(imm);
7678 if (op & 4) {
7679 /* Unsigned. */
7680 if ((op & 1) && shift == 0)
7681 gen_helper_usat16(tmp, tmp, tmp2);
7682 else
7683 gen_helper_usat(tmp, tmp, tmp2);
7684 } else {
7685 /* Signed. */
7686 if ((op & 1) && shift == 0)
7687 gen_helper_ssat16(tmp, tmp, tmp2);
7688 else
7689 gen_helper_ssat(tmp, tmp, tmp2);
7691 break;
7693 store_reg(s, rd, tmp);
7694 } else {
7695 imm = ((insn & 0x04000000) >> 15)
7696 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7697 if (insn & (1 << 22)) {
7698 /* 16-bit immediate. */
7699 imm |= (insn >> 4) & 0xf000;
7700 if (insn & (1 << 23)) {
7701 /* movt */
7702 tmp = load_reg(s, rd);
7703 tcg_gen_andi_i32(tmp, tmp, 0xffff);
7704 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7705 } else {
7706 /* movw */
7707 tmp = new_tmp();
7708 tcg_gen_movi_i32(tmp, imm);
7710 } else {
7711 /* Add/sub 12-bit immediate. */
7712 if (rn == 15) {
7713 offset = s->pc & ~(uint32_t)3;
7714 if (insn & (1 << 23))
7715 offset -= imm;
7716 else
7717 offset += imm;
7718 tmp = new_tmp();
7719 tcg_gen_movi_i32(tmp, offset);
7720 } else {
7721 tmp = load_reg(s, rn);
7722 if (insn & (1 << 23))
7723 tcg_gen_subi_i32(tmp, tmp, imm);
7724 else
7725 tcg_gen_addi_i32(tmp, tmp, imm);
7728 store_reg(s, rd, tmp);
7730 } else {
7731 int shifter_out = 0;
7732 /* modified 12-bit immediate. */
7733 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7734 imm = (insn & 0xff);
7735 switch (shift) {
7736 case 0: /* XY */
7737 /* Nothing to do. */
7738 break;
7739 case 1: /* 00XY00XY */
7740 imm |= imm << 16;
7741 break;
7742 case 2: /* XY00XY00 */
7743 imm |= imm << 16;
7744 imm <<= 8;
7745 break;
7746 case 3: /* XYXYXYXY */
7747 imm |= imm << 16;
7748 imm |= imm << 8;
7749 break;
7750 default: /* Rotated constant. */
7751 shift = (shift << 1) | (imm >> 7);
7752 imm |= 0x80;
7753 imm = imm << (32 - shift);
7754 shifter_out = 1;
7755 break;
7757 gen_op_movl_T1_im(imm);
7758 rn = (insn >> 16) & 0xf;
7759 if (rn == 15)
7760 gen_op_movl_T0_im(0);
7761 else
7762 gen_movl_T0_reg(s, rn);
7763 op = (insn >> 21) & 0xf;
7764 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7765 shifter_out))
7766 goto illegal_op;
7767 rd = (insn >> 8) & 0xf;
7768 if (rd != 15) {
7769 gen_movl_reg_T0(s, rd);
7773 break;
7774 case 12: /* Load/store single data item. */
7776 int postinc = 0;
7777 int writeback = 0;
7778 int user;
7779 if ((insn & 0x01100000) == 0x01000000) {
7780 if (disas_neon_ls_insn(env, s, insn))
7781 goto illegal_op;
7782 break;
7784 user = IS_USER(s);
7785 if (rn == 15) {
7786 addr = new_tmp();
7787 /* PC relative. */
7788 /* s->pc has already been incremented by 4. */
7789 imm = s->pc & 0xfffffffc;
7790 if (insn & (1 << 23))
7791 imm += insn & 0xfff;
7792 else
7793 imm -= insn & 0xfff;
7794 tcg_gen_movi_i32(addr, imm);
7795 } else {
7796 addr = load_reg(s, rn);
7797 if (insn & (1 << 23)) {
7798 /* Positive offset. */
7799 imm = insn & 0xfff;
7800 tcg_gen_addi_i32(addr, addr, imm);
7801 } else {
7802 op = (insn >> 8) & 7;
7803 imm = insn & 0xff;
7804 switch (op) {
7805 case 0: case 8: /* Shifted Register. */
7806 shift = (insn >> 4) & 0xf;
7807 if (shift > 3)
7808 goto illegal_op;
7809 tmp = load_reg(s, rm);
7810 if (shift)
7811 tcg_gen_shli_i32(tmp, tmp, shift);
7812 tcg_gen_add_i32(addr, addr, tmp);
7813 dead_tmp(tmp);
7814 break;
7815 case 4: /* Negative offset. */
7816 tcg_gen_addi_i32(addr, addr, -imm);
7817 break;
7818 case 6: /* User privilege. */
7819 tcg_gen_addi_i32(addr, addr, imm);
7820 user = 1;
7821 break;
7822 case 1: /* Post-decrement. */
7823 imm = -imm;
7824 /* Fall through. */
7825 case 3: /* Post-increment. */
7826 postinc = 1;
7827 writeback = 1;
7828 break;
7829 case 5: /* Pre-decrement. */
7830 imm = -imm;
7831 /* Fall through. */
7832 case 7: /* Pre-increment. */
7833 tcg_gen_addi_i32(addr, addr, imm);
7834 writeback = 1;
7835 break;
7836 default:
7837 goto illegal_op;
7841 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7842 if (insn & (1 << 20)) {
7843 /* Load. */
7844 if (rs == 15 && op != 2) {
7845 if (op & 2)
7846 goto illegal_op;
7847 /* Memory hint. Implemented as NOP. */
7848 } else {
7849 switch (op) {
7850 case 0: tmp = gen_ld8u(addr, user); break;
7851 case 4: tmp = gen_ld8s(addr, user); break;
7852 case 1: tmp = gen_ld16u(addr, user); break;
7853 case 5: tmp = gen_ld16s(addr, user); break;
7854 case 2: tmp = gen_ld32(addr, user); break;
7855 default: goto illegal_op;
7857 if (rs == 15) {
7858 gen_bx(s, tmp);
7859 } else {
7860 store_reg(s, rs, tmp);
7863 } else {
7864 /* Store. */
7865 if (rs == 15)
7866 goto illegal_op;
7867 tmp = load_reg(s, rs);
7868 switch (op) {
7869 case 0: gen_st8(tmp, addr, user); break;
7870 case 1: gen_st16(tmp, addr, user); break;
7871 case 2: gen_st32(tmp, addr, user); break;
7872 default: goto illegal_op;
7875 if (postinc)
7876 tcg_gen_addi_i32(addr, addr, imm);
7877 if (writeback) {
7878 store_reg(s, rn, addr);
7879 } else {
7880 dead_tmp(addr);
7883 break;
7884 default:
7885 goto illegal_op;
7887 return 0;
7888 illegal_op:
7889 return 1;
7892 static void disas_thumb_insn(CPUState *env, DisasContext *s)
7894 uint32_t val, insn, op, rm, rn, rd, shift, cond;
7895 int32_t offset;
7896 int i;
7897 TCGv tmp;
7898 TCGv tmp2;
7899 TCGv addr;
7901 if (s->condexec_mask) {
7902 cond = s->condexec_cond;
7903 s->condlabel = gen_new_label();
7904 gen_test_cc(cond ^ 1, s->condlabel);
7905 s->condjmp = 1;
7908 insn = lduw_code(s->pc);
7909 s->pc += 2;
7911 switch (insn >> 12) {
7912 case 0: case 1:
7913 rd = insn & 7;
7914 op = (insn >> 11) & 3;
7915 if (op == 3) {
7916 /* add/subtract */
7917 rn = (insn >> 3) & 7;
7918 gen_movl_T0_reg(s, rn);
7919 if (insn & (1 << 10)) {
7920 /* immediate */
7921 gen_op_movl_T1_im((insn >> 6) & 7);
7922 } else {
7923 /* reg */
7924 rm = (insn >> 6) & 7;
7925 gen_movl_T1_reg(s, rm);
7927 if (insn & (1 << 9)) {
7928 if (s->condexec_mask)
7929 gen_op_subl_T0_T1();
7930 else
7931 gen_op_subl_T0_T1_cc();
7932 } else {
7933 if (s->condexec_mask)
7934 gen_op_addl_T0_T1();
7935 else
7936 gen_op_addl_T0_T1_cc();
7938 gen_movl_reg_T0(s, rd);
7939 } else {
7940 /* shift immediate */
7941 rm = (insn >> 3) & 7;
7942 shift = (insn >> 6) & 0x1f;
7943 tmp = load_reg(s, rm);
7944 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
7945 if (!s->condexec_mask)
7946 gen_logic_CC(tmp);
7947 store_reg(s, rd, tmp);
7949 break;
7950 case 2: case 3:
7951 /* arithmetic large immediate */
7952 op = (insn >> 11) & 3;
7953 rd = (insn >> 8) & 0x7;
7954 if (op == 0) {
7955 gen_op_movl_T0_im(insn & 0xff);
7956 } else {
7957 gen_movl_T0_reg(s, rd);
7958 gen_op_movl_T1_im(insn & 0xff);
7960 switch (op) {
7961 case 0: /* mov */
7962 if (!s->condexec_mask)
7963 gen_op_logic_T0_cc();
7964 break;
7965 case 1: /* cmp */
7966 gen_op_subl_T0_T1_cc();
7967 break;
7968 case 2: /* add */
7969 if (s->condexec_mask)
7970 gen_op_addl_T0_T1();
7971 else
7972 gen_op_addl_T0_T1_cc();
7973 break;
7974 case 3: /* sub */
7975 if (s->condexec_mask)
7976 gen_op_subl_T0_T1();
7977 else
7978 gen_op_subl_T0_T1_cc();
7979 break;
7981 if (op != 1)
7982 gen_movl_reg_T0(s, rd);
7983 break;
7984 case 4:
7985 if (insn & (1 << 11)) {
7986 rd = (insn >> 8) & 7;
7987 /* load pc-relative. Bit 1 of PC is ignored. */
7988 val = s->pc + 2 + ((insn & 0xff) * 4);
7989 val &= ~(uint32_t)2;
7990 addr = new_tmp();
7991 tcg_gen_movi_i32(addr, val);
7992 tmp = gen_ld32(addr, IS_USER(s));
7993 dead_tmp(addr);
7994 store_reg(s, rd, tmp);
7995 break;
7997 if (insn & (1 << 10)) {
7998 /* data processing extended or blx */
7999 rd = (insn & 7) | ((insn >> 4) & 8);
8000 rm = (insn >> 3) & 0xf;
8001 op = (insn >> 8) & 3;
8002 switch (op) {
8003 case 0: /* add */
8004 gen_movl_T0_reg(s, rd);
8005 gen_movl_T1_reg(s, rm);
8006 gen_op_addl_T0_T1();
8007 gen_movl_reg_T0(s, rd);
8008 break;
8009 case 1: /* cmp */
8010 gen_movl_T0_reg(s, rd);
8011 gen_movl_T1_reg(s, rm);
8012 gen_op_subl_T0_T1_cc();
8013 break;
8014 case 2: /* mov/cpy */
8015 gen_movl_T0_reg(s, rm);
8016 gen_movl_reg_T0(s, rd);
8017 break;
8018 case 3:/* branch [and link] exchange thumb register */
8019 tmp = load_reg(s, rm);
8020 if (insn & (1 << 7)) {
8021 val = (uint32_t)s->pc | 1;
8022 tmp2 = new_tmp();
8023 tcg_gen_movi_i32(tmp2, val);
8024 store_reg(s, 14, tmp2);
8026 gen_bx(s, tmp);
8027 break;
8029 break;
8032 /* data processing register */
8033 rd = insn & 7;
8034 rm = (insn >> 3) & 7;
8035 op = (insn >> 6) & 0xf;
8036 if (op == 2 || op == 3 || op == 4 || op == 7) {
8037 /* the shift/rotate ops want the operands backwards */
8038 val = rm;
8039 rm = rd;
8040 rd = val;
8041 val = 1;
8042 } else {
8043 val = 0;
8046 if (op == 9) /* neg */
8047 gen_op_movl_T0_im(0);
8048 else if (op != 0xf) /* mvn doesn't read its first operand */
8049 gen_movl_T0_reg(s, rd);
8051 gen_movl_T1_reg(s, rm);
8052 switch (op) {
8053 case 0x0: /* and */
8054 gen_op_andl_T0_T1();
8055 if (!s->condexec_mask)
8056 gen_op_logic_T0_cc();
8057 break;
8058 case 0x1: /* eor */
8059 gen_op_xorl_T0_T1();
8060 if (!s->condexec_mask)
8061 gen_op_logic_T0_cc();
8062 break;
8063 case 0x2: /* lsl */
8064 if (s->condexec_mask) {
8065 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8066 } else {
8067 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8068 gen_op_logic_T1_cc();
8070 break;
8071 case 0x3: /* lsr */
8072 if (s->condexec_mask) {
8073 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8074 } else {
8075 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8076 gen_op_logic_T1_cc();
8078 break;
8079 case 0x4: /* asr */
8080 if (s->condexec_mask) {
8081 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8082 } else {
8083 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8084 gen_op_logic_T1_cc();
8086 break;
8087 case 0x5: /* adc */
8088 if (s->condexec_mask)
8089 gen_adc_T0_T1();
8090 else
8091 gen_op_adcl_T0_T1_cc();
8092 break;
8093 case 0x6: /* sbc */
8094 if (s->condexec_mask)
8095 gen_sbc_T0_T1();
8096 else
8097 gen_op_sbcl_T0_T1_cc();
8098 break;
8099 case 0x7: /* ror */
8100 if (s->condexec_mask) {
8101 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8102 } else {
8103 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8104 gen_op_logic_T1_cc();
8106 break;
8107 case 0x8: /* tst */
8108 gen_op_andl_T0_T1();
8109 gen_op_logic_T0_cc();
8110 rd = 16;
8111 break;
8112 case 0x9: /* neg */
8113 if (s->condexec_mask)
8114 gen_op_subl_T0_T1();
8115 else
8116 gen_op_subl_T0_T1_cc();
8117 break;
8118 case 0xa: /* cmp */
8119 gen_op_subl_T0_T1_cc();
8120 rd = 16;
8121 break;
8122 case 0xb: /* cmn */
8123 gen_op_addl_T0_T1_cc();
8124 rd = 16;
8125 break;
8126 case 0xc: /* orr */
8127 gen_op_orl_T0_T1();
8128 if (!s->condexec_mask)
8129 gen_op_logic_T0_cc();
8130 break;
8131 case 0xd: /* mul */
8132 gen_op_mull_T0_T1();
8133 if (!s->condexec_mask)
8134 gen_op_logic_T0_cc();
8135 break;
8136 case 0xe: /* bic */
8137 gen_op_bicl_T0_T1();
8138 if (!s->condexec_mask)
8139 gen_op_logic_T0_cc();
8140 break;
8141 case 0xf: /* mvn */
8142 gen_op_notl_T1();
8143 if (!s->condexec_mask)
8144 gen_op_logic_T1_cc();
8145 val = 1;
8146 rm = rd;
8147 break;
8149 if (rd != 16) {
8150 if (val)
8151 gen_movl_reg_T1(s, rm);
8152 else
8153 gen_movl_reg_T0(s, rd);
8155 break;
8157 case 5:
8158 /* load/store register offset. */
8159 rd = insn & 7;
8160 rn = (insn >> 3) & 7;
8161 rm = (insn >> 6) & 7;
8162 op = (insn >> 9) & 7;
8163 addr = load_reg(s, rn);
8164 tmp = load_reg(s, rm);
8165 tcg_gen_add_i32(addr, addr, tmp);
8166 dead_tmp(tmp);
8168 if (op < 3) /* store */
8169 tmp = load_reg(s, rd);
8171 switch (op) {
8172 case 0: /* str */
8173 gen_st32(tmp, addr, IS_USER(s));
8174 break;
8175 case 1: /* strh */
8176 gen_st16(tmp, addr, IS_USER(s));
8177 break;
8178 case 2: /* strb */
8179 gen_st8(tmp, addr, IS_USER(s));
8180 break;
8181 case 3: /* ldrsb */
8182 tmp = gen_ld8s(addr, IS_USER(s));
8183 break;
8184 case 4: /* ldr */
8185 tmp = gen_ld32(addr, IS_USER(s));
8186 break;
8187 case 5: /* ldrh */
8188 tmp = gen_ld16u(addr, IS_USER(s));
8189 break;
8190 case 6: /* ldrb */
8191 tmp = gen_ld8u(addr, IS_USER(s));
8192 break;
8193 case 7: /* ldrsh */
8194 tmp = gen_ld16s(addr, IS_USER(s));
8195 break;
8197 if (op >= 3) /* load */
8198 store_reg(s, rd, tmp);
8199 dead_tmp(addr);
8200 break;
8202 case 6:
8203 /* load/store word immediate offset */
8204 rd = insn & 7;
8205 rn = (insn >> 3) & 7;
8206 addr = load_reg(s, rn);
8207 val = (insn >> 4) & 0x7c;
8208 tcg_gen_addi_i32(addr, addr, val);
8210 if (insn & (1 << 11)) {
8211 /* load */
8212 tmp = gen_ld32(addr, IS_USER(s));
8213 store_reg(s, rd, tmp);
8214 } else {
8215 /* store */
8216 tmp = load_reg(s, rd);
8217 gen_st32(tmp, addr, IS_USER(s));
8219 dead_tmp(addr);
8220 break;
8222 case 7:
8223 /* load/store byte immediate offset */
8224 rd = insn & 7;
8225 rn = (insn >> 3) & 7;
8226 addr = load_reg(s, rn);
8227 val = (insn >> 6) & 0x1f;
8228 tcg_gen_addi_i32(addr, addr, val);
8230 if (insn & (1 << 11)) {
8231 /* load */
8232 tmp = gen_ld8u(addr, IS_USER(s));
8233 store_reg(s, rd, tmp);
8234 } else {
8235 /* store */
8236 tmp = load_reg(s, rd);
8237 gen_st8(tmp, addr, IS_USER(s));
8239 dead_tmp(addr);
8240 break;
8242 case 8:
8243 /* load/store halfword immediate offset */
8244 rd = insn & 7;
8245 rn = (insn >> 3) & 7;
8246 addr = load_reg(s, rn);
8247 val = (insn >> 5) & 0x3e;
8248 tcg_gen_addi_i32(addr, addr, val);
8250 if (insn & (1 << 11)) {
8251 /* load */
8252 tmp = gen_ld16u(addr, IS_USER(s));
8253 store_reg(s, rd, tmp);
8254 } else {
8255 /* store */
8256 tmp = load_reg(s, rd);
8257 gen_st16(tmp, addr, IS_USER(s));
8259 dead_tmp(addr);
8260 break;
8262 case 9:
8263 /* load/store from stack */
8264 rd = (insn >> 8) & 7;
8265 addr = load_reg(s, 13);
8266 val = (insn & 0xff) * 4;
8267 tcg_gen_addi_i32(addr, addr, val);
8269 if (insn & (1 << 11)) {
8270 /* load */
8271 tmp = gen_ld32(addr, IS_USER(s));
8272 store_reg(s, rd, tmp);
8273 } else {
8274 /* store */
8275 tmp = load_reg(s, rd);
8276 gen_st32(tmp, addr, IS_USER(s));
8278 dead_tmp(addr);
8279 break;
8281 case 10:
8282 /* add to high reg */
8283 rd = (insn >> 8) & 7;
8284 if (insn & (1 << 11)) {
8285 /* SP */
8286 tmp = load_reg(s, 13);
8287 } else {
8288 /* PC. bit 1 is ignored. */
8289 tmp = new_tmp();
8290 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8292 val = (insn & 0xff) * 4;
8293 tcg_gen_addi_i32(tmp, tmp, val);
8294 store_reg(s, rd, tmp);
8295 break;
8297 case 11:
8298 /* misc */
8299 op = (insn >> 8) & 0xf;
8300 switch (op) {
8301 case 0:
8302 /* adjust stack pointer */
8303 tmp = load_reg(s, 13);
8304 val = (insn & 0x7f) * 4;
8305 if (insn & (1 << 7))
8306 val = -(int32_t)val;
8307 tcg_gen_addi_i32(tmp, tmp, val);
8308 store_reg(s, 13, tmp);
8309 break;
8311 case 2: /* sign/zero extend. */
8312 ARCH(6);
8313 rd = insn & 7;
8314 rm = (insn >> 3) & 7;
8315 tmp = load_reg(s, rm);
8316 switch ((insn >> 6) & 3) {
8317 case 0: gen_sxth(tmp); break;
8318 case 1: gen_sxtb(tmp); break;
8319 case 2: gen_uxth(tmp); break;
8320 case 3: gen_uxtb(tmp); break;
8322 store_reg(s, rd, tmp);
8323 break;
8324 case 4: case 5: case 0xc: case 0xd:
8325 /* push/pop */
8326 addr = load_reg(s, 13);
8327 if (insn & (1 << 8))
8328 offset = 4;
8329 else
8330 offset = 0;
8331 for (i = 0; i < 8; i++) {
8332 if (insn & (1 << i))
8333 offset += 4;
8335 if ((insn & (1 << 11)) == 0) {
8336 tcg_gen_addi_i32(addr, addr, -offset);
8338 for (i = 0; i < 8; i++) {
8339 if (insn & (1 << i)) {
8340 if (insn & (1 << 11)) {
8341 /* pop */
8342 tmp = gen_ld32(addr, IS_USER(s));
8343 store_reg(s, i, tmp);
8344 } else {
8345 /* push */
8346 tmp = load_reg(s, i);
8347 gen_st32(tmp, addr, IS_USER(s));
8349 /* advance to the next address. */
8350 tcg_gen_addi_i32(addr, addr, 4);
8353 if (insn & (1 << 8)) {
8354 if (insn & (1 << 11)) {
8355 /* pop pc */
8356 tmp = gen_ld32(addr, IS_USER(s));
8357 /* don't set the pc until the rest of the instruction
8358 has completed */
8359 } else {
8360 /* push lr */
8361 tmp = load_reg(s, 14);
8362 gen_st32(tmp, addr, IS_USER(s));
8364 tcg_gen_addi_i32(addr, addr, 4);
8366 if ((insn & (1 << 11)) == 0) {
8367 tcg_gen_addi_i32(addr, addr, -offset);
8369 /* write back the new stack pointer */
8370 store_reg(s, 13, addr);
8371 /* set the new PC value */
8372 if ((insn & 0x0900) == 0x0900)
8373 gen_bx(s, tmp);
8374 break;
8376 case 1: case 3: case 9: case 11: /* czb */
8377 rm = insn & 7;
8378 tmp = load_reg(s, rm);
8379 tmp2 = tcg_const_i32(0);
8380 s->condlabel = gen_new_label();
8381 s->condjmp = 1;
8382 if (insn & (1 << 11))
8383 tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, s->condlabel);
8384 else
8385 tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, s->condlabel);
8386 dead_tmp(tmp);
8387 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8388 val = (uint32_t)s->pc + 2;
8389 val += offset;
8390 gen_jmp(s, val);
8391 break;
8393 case 15: /* IT, nop-hint. */
8394 if ((insn & 0xf) == 0) {
8395 gen_nop_hint(s, (insn >> 4) & 0xf);
8396 break;
8398 /* If Then. */
8399 s->condexec_cond = (insn >> 4) & 0xe;
8400 s->condexec_mask = insn & 0x1f;
8401 /* No actual code generated for this insn, just setup state. */
8402 break;
8404 case 0xe: /* bkpt */
8405 gen_set_condexec(s);
8406 gen_set_pc_im(s->pc - 2);
8407 gen_exception(EXCP_BKPT);
8408 s->is_jmp = DISAS_JUMP;
8409 break;
8411 case 0xa: /* rev */
8412 ARCH(6);
8413 rn = (insn >> 3) & 0x7;
8414 rd = insn & 0x7;
8415 tmp = load_reg(s, rn);
8416 switch ((insn >> 6) & 3) {
8417 case 0: tcg_gen_bswap_i32(tmp, tmp); break;
8418 case 1: gen_rev16(tmp); break;
8419 case 3: gen_revsh(tmp); break;
8420 default: goto illegal_op;
8422 store_reg(s, rd, tmp);
8423 break;
8425 case 6: /* cps */
8426 ARCH(6);
8427 if (IS_USER(s))
8428 break;
8429 if (IS_M(env)) {
8430 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8431 /* PRIMASK */
8432 if (insn & 1) {
8433 addr = tcg_const_i32(16);
8434 gen_helper_v7m_msr(cpu_env, addr, tmp);
8436 /* FAULTMASK */
8437 if (insn & 2) {
8438 addr = tcg_const_i32(17);
8439 gen_helper_v7m_msr(cpu_env, addr, tmp);
8441 gen_lookup_tb(s);
8442 } else {
8443 if (insn & (1 << 4))
8444 shift = CPSR_A | CPSR_I | CPSR_F;
8445 else
8446 shift = 0;
8448 val = ((insn & 7) << 6) & shift;
8449 gen_op_movl_T0_im(val);
8450 gen_set_psr_T0(s, shift, 0);
8452 break;
8454 default:
8455 goto undef;
8457 break;
8459 case 12:
8460 /* load/store multiple */
8461 rn = (insn >> 8) & 0x7;
8462 addr = load_reg(s, rn);
8463 for (i = 0; i < 8; i++) {
8464 if (insn & (1 << i)) {
8465 if (insn & (1 << 11)) {
8466 /* load */
8467 tmp = gen_ld32(addr, IS_USER(s));
8468 store_reg(s, i, tmp);
8469 } else {
8470 /* store */
8471 tmp = load_reg(s, i);
8472 gen_st32(tmp, addr, IS_USER(s));
8474 /* advance to the next address */
8475 tcg_gen_addi_i32(addr, addr, 4);
8478 /* Base register writeback. */
8479 if ((insn & (1 << rn)) == 0) {
8480 store_reg(s, rn, addr);
8481 } else {
8482 dead_tmp(addr);
8484 break;
8486 case 13:
8487 /* conditional branch or swi */
8488 cond = (insn >> 8) & 0xf;
8489 if (cond == 0xe)
8490 goto undef;
8492 if (cond == 0xf) {
8493 /* swi */
8494 gen_set_condexec(s);
8495 gen_set_pc_im(s->pc);
8496 s->is_jmp = DISAS_SWI;
8497 break;
8499 /* generate a conditional jump to next instruction */
8500 s->condlabel = gen_new_label();
8501 gen_test_cc(cond ^ 1, s->condlabel);
8502 s->condjmp = 1;
8503 gen_movl_T1_reg(s, 15);
8505 /* jump to the offset */
8506 val = (uint32_t)s->pc + 2;
8507 offset = ((int32_t)insn << 24) >> 24;
8508 val += offset << 1;
8509 gen_jmp(s, val);
8510 break;
8512 case 14:
8513 if (insn & (1 << 11)) {
8514 if (disas_thumb2_insn(env, s, insn))
8515 goto undef32;
8516 break;
8518 /* unconditional branch */
8519 val = (uint32_t)s->pc;
8520 offset = ((int32_t)insn << 21) >> 21;
8521 val += (offset << 1) + 2;
8522 gen_jmp(s, val);
8523 break;
8525 case 15:
8526 if (disas_thumb2_insn(env, s, insn))
8527 goto undef32;
8528 break;
8530 return;
8531 undef32:
8532 gen_set_condexec(s);
8533 gen_set_pc_im(s->pc - 4);
8534 gen_exception(EXCP_UDEF);
8535 s->is_jmp = DISAS_JUMP;
8536 return;
8537 illegal_op:
8538 undef:
8539 gen_set_condexec(s);
8540 gen_set_pc_im(s->pc - 2);
8541 gen_exception(EXCP_UDEF);
8542 s->is_jmp = DISAS_JUMP;
8545 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8546 basic block 'tb'. If search_pc is TRUE, also generate PC
8547 information for each intermediate instruction. */
8548 static inline int gen_intermediate_code_internal(CPUState *env,
8549 TranslationBlock *tb,
8550 int search_pc)
8552 DisasContext dc1, *dc = &dc1;
8553 uint16_t *gen_opc_end;
8554 int j, lj;
8555 target_ulong pc_start;
8556 uint32_t next_page_start;
8558 /* generate intermediate code */
8559 num_temps = 0;
8560 memset(temps, 0, sizeof(temps));
8562 pc_start = tb->pc;
8564 dc->tb = tb;
8566 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8568 dc->is_jmp = DISAS_NEXT;
8569 dc->pc = pc_start;
8570 dc->singlestep_enabled = env->singlestep_enabled;
8571 dc->condjmp = 0;
8572 dc->thumb = env->thumb;
8573 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8574 dc->condexec_cond = env->condexec_bits >> 4;
8575 dc->is_mem = 0;
8576 #if !defined(CONFIG_USER_ONLY)
8577 if (IS_M(env)) {
8578 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8579 } else {
8580 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8582 #endif
8583 cpu_F0s = tcg_temp_new(TCG_TYPE_I32);
8584 cpu_F1s = tcg_temp_new(TCG_TYPE_I32);
8585 cpu_F0d = tcg_temp_new(TCG_TYPE_I64);
8586 cpu_F1d = tcg_temp_new(TCG_TYPE_I64);
8587 cpu_V0 = cpu_F0d;
8588 cpu_V1 = cpu_F1d;
8589 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8590 cpu_M0 = tcg_temp_new(TCG_TYPE_I64);
8591 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8592 lj = -1;
8593 /* Reset the conditional execution bits immediately. This avoids
8594 complications trying to do it at the end of the block. */
8595 if (env->condexec_bits)
8597 TCGv tmp = new_tmp();
8598 tcg_gen_movi_i32(tmp, 0);
8599 store_cpu_field(tmp, condexec_bits);
8601 do {
8602 #ifndef CONFIG_USER_ONLY
8603 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8604 /* We always get here via a jump, so know we are not in a
8605 conditional execution block. */
8606 gen_exception(EXCP_EXCEPTION_EXIT);
8608 #endif
8610 if (env->nb_breakpoints > 0) {
8611 for(j = 0; j < env->nb_breakpoints; j++) {
8612 if (env->breakpoints[j] == dc->pc) {
8613 gen_set_condexec(dc);
8614 gen_set_pc_im(dc->pc);
8615 gen_exception(EXCP_DEBUG);
8616 dc->is_jmp = DISAS_JUMP;
8617 /* Advance PC so that clearing the breakpoint will
8618 invalidate this TB. */
8619 dc->pc += 2;
8620 goto done_generating;
8621 break;
8625 if (search_pc) {
8626 j = gen_opc_ptr - gen_opc_buf;
8627 if (lj < j) {
8628 lj++;
8629 while (lj < j)
8630 gen_opc_instr_start[lj++] = 0;
8632 gen_opc_pc[lj] = dc->pc;
8633 gen_opc_instr_start[lj] = 1;
8636 if (env->thumb) {
8637 disas_thumb_insn(env, dc);
8638 if (dc->condexec_mask) {
8639 dc->condexec_cond = (dc->condexec_cond & 0xe)
8640 | ((dc->condexec_mask >> 4) & 1);
8641 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8642 if (dc->condexec_mask == 0) {
8643 dc->condexec_cond = 0;
8646 } else {
8647 disas_arm_insn(env, dc);
8649 if (num_temps) {
8650 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8651 num_temps = 0;
8654 if (dc->condjmp && !dc->is_jmp) {
8655 gen_set_label(dc->condlabel);
8656 dc->condjmp = 0;
8658 /* Terminate the TB on memory ops if watchpoints are present. */
8659 /* FIXME: This should be replacd by the deterministic execution
8660 * IRQ raising bits. */
8661 if (dc->is_mem && env->nb_watchpoints)
8662 break;
8664 /* Translation stops when a conditional branch is enoutered.
8665 * Otherwise the subsequent code could get translated several times.
8666 * Also stop translation when a page boundary is reached. This
8667 * ensures prefech aborts occur at the right place. */
8668 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8669 !env->singlestep_enabled &&
8670 dc->pc < next_page_start);
8672 /* At this stage dc->condjmp will only be set when the skipped
8673 instruction was a conditional branch or trap, and the PC has
8674 already been written. */
8675 if (__builtin_expect(env->singlestep_enabled, 0)) {
8676 /* Make sure the pc is updated, and raise a debug exception. */
8677 if (dc->condjmp) {
8678 gen_set_condexec(dc);
8679 if (dc->is_jmp == DISAS_SWI) {
8680 gen_exception(EXCP_SWI);
8681 } else {
8682 gen_exception(EXCP_DEBUG);
8684 gen_set_label(dc->condlabel);
8686 if (dc->condjmp || !dc->is_jmp) {
8687 gen_set_pc_im(dc->pc);
8688 dc->condjmp = 0;
8690 gen_set_condexec(dc);
8691 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8692 gen_exception(EXCP_SWI);
8693 } else {
8694 /* FIXME: Single stepping a WFI insn will not halt
8695 the CPU. */
8696 gen_exception(EXCP_DEBUG);
8698 } else {
8699 /* While branches must always occur at the end of an IT block,
8700 there are a few other things that can cause us to terminate
8701 the TB in the middel of an IT block:
8702 - Exception generating instructions (bkpt, swi, undefined).
8703 - Page boundaries.
8704 - Hardware watchpoints.
8705 Hardware breakpoints have already been handled and skip this code.
8707 gen_set_condexec(dc);
8708 switch(dc->is_jmp) {
8709 case DISAS_NEXT:
8710 gen_goto_tb(dc, 1, dc->pc);
8711 break;
8712 default:
8713 case DISAS_JUMP:
8714 case DISAS_UPDATE:
8715 /* indicate that the hash table must be used to find the next TB */
8716 tcg_gen_exit_tb(0);
8717 break;
8718 case DISAS_TB_JUMP:
8719 /* nothing more to generate */
8720 break;
8721 case DISAS_WFI:
8722 gen_helper_wfi();
8723 break;
8724 case DISAS_SWI:
8725 gen_exception(EXCP_SWI);
8726 break;
8728 if (dc->condjmp) {
8729 gen_set_label(dc->condlabel);
8730 gen_set_condexec(dc);
8731 gen_goto_tb(dc, 1, dc->pc);
8732 dc->condjmp = 0;
8735 done_generating:
8736 *gen_opc_ptr = INDEX_op_end;
8738 #ifdef DEBUG_DISAS
8739 if (loglevel & CPU_LOG_TB_IN_ASM) {
8740 fprintf(logfile, "----------------\n");
8741 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8742 target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
8743 fprintf(logfile, "\n");
8745 #endif
8746 if (search_pc) {
8747 j = gen_opc_ptr - gen_opc_buf;
8748 lj++;
8749 while (lj <= j)
8750 gen_opc_instr_start[lj++] = 0;
8751 } else {
8752 tb->size = dc->pc - pc_start;
8754 return 0;
8757 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8759 return gen_intermediate_code_internal(env, tb, 0);
8762 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8764 return gen_intermediate_code_internal(env, tb, 1);
8767 static const char *cpu_mode_names[16] = {
8768 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8769 "???", "???", "???", "und", "???", "???", "???", "sys"
8772 void cpu_dump_state(CPUState *env, FILE *f,
8773 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8774 int flags)
8776 int i;
8777 union {
8778 uint32_t i;
8779 float s;
8780 } s0, s1;
8781 CPU_DoubleU d;
8782 /* ??? This assumes float64 and double have the same layout.
8783 Oh well, it's only debug dumps. */
8784 union {
8785 float64 f64;
8786 double d;
8787 } d0;
8788 uint32_t psr;
8790 for(i=0;i<16;i++) {
8791 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8792 if ((i % 4) == 3)
8793 cpu_fprintf(f, "\n");
8794 else
8795 cpu_fprintf(f, " ");
8797 psr = cpsr_read(env);
8798 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8799 psr,
8800 psr & (1 << 31) ? 'N' : '-',
8801 psr & (1 << 30) ? 'Z' : '-',
8802 psr & (1 << 29) ? 'C' : '-',
8803 psr & (1 << 28) ? 'V' : '-',
8804 psr & CPSR_T ? 'T' : 'A',
8805 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8807 #if 0
8808 for (i = 0; i < 16; i++) {
8809 d.d = env->vfp.regs[i];
8810 s0.i = d.l.lower;
8811 s1.i = d.l.upper;
8812 d0.f64 = d.d;
8813 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8814 i * 2, (int)s0.i, s0.s,
8815 i * 2 + 1, (int)s1.i, s1.s,
8816 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
8817 d0.d);
8819 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
8820 #endif
8823 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8824 unsigned long searched_pc, int pc_pos, void *puc)
8826 env->regs[15] = gen_opc_pc[pc_pos];