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