4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext {
50 /* Nonzero if this instruction has been conditionally skipped. */
52 /* The label that will be jumped to when the instruction is skipped. */
54 /* Thumb-2 condtional execution bits. */
57 struct TranslationBlock *tb;
58 int singlestep_enabled;
60 #if !defined(CONFIG_USER_ONLY)
65 #if defined(CONFIG_USER_ONLY)
68 #define IS_USER(s) (s->user)
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
76 static TCGv_ptr cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
80 /* FIXME: These should be removed. */
82 static TCGv cpu_F0s, cpu_F1s;
83 static TCGv_i64 cpu_F0d, cpu_F1d;
85 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h"
88 /* initialize TCG globals. */
89 void arm_translate_init(void)
91 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
93 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
94 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
100 /* The code generator doesn't like lots of temporaries, so maintain our own
101 cache for reuse within a function. */
103 static int num_temps;
104 static TCGv temps[MAX_TEMPS];
106 /* Allocate a temporary variable. */
107 static TCGv_i32 new_tmp(void)
110 if (num_temps == MAX_TEMPS)
113 if (GET_TCGV_I32(temps[num_temps]))
114 return temps[num_temps++];
116 tmp = tcg_temp_new_i32();
117 temps[num_temps++] = tmp;
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp)
127 if (TCGV_EQUAL(temps[i], tmp))
130 /* Shuffle this temp to the last slot. */
131 while (!TCGV_EQUAL(temps[i], tmp))
133 while (i < num_temps) {
134 temps[i] = temps[i + 1];
140 static inline TCGv load_cpu_offset(int offset)
142 TCGv tmp = new_tmp();
143 tcg_gen_ld_i32(tmp, cpu_env, offset);
147 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
149 static inline void store_cpu_offset(TCGv var, int offset)
151 tcg_gen_st_i32(var, cpu_env, offset);
155 #define store_cpu_field(var, name) \
156 store_cpu_offset(var, offsetof(CPUState, name))
158 /* Set a variable to the value of a CPU register. */
159 static void load_reg_var(DisasContext *s, TCGv var, int reg)
163 /* normaly, since we updated PC, we need only to add one insn */
165 addr = (long)s->pc + 2;
167 addr = (long)s->pc + 4;
168 tcg_gen_movi_i32(var, addr);
170 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
174 /* Create a new temporary and set it to the value of a CPU register. */
175 static inline TCGv load_reg(DisasContext *s, int reg)
177 TCGv tmp = new_tmp();
178 load_reg_var(s, tmp, reg);
182 /* Set a CPU register. The source must be a temporary and will be
184 static void store_reg(DisasContext *s, int reg, TCGv var)
187 tcg_gen_andi_i32(var, var, ~1);
188 s->is_jmp = DISAS_JUMP;
190 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
194 /* Variant of store_reg which uses branch&exchange logic when storing
195 to r15 in ARM architecture v7 and above. The source must be a temporary
196 and will be marked as dead. */
197 #define store_reg_bx(dc, reg, var) \
198 if ((reg) == 15 && ENABLE_ARCH_7) \
199 gen_bx((dc), (var)); \
201 store_reg((dc), (reg), (var));
203 /* Basic operations. */
204 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
205 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
206 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
208 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
209 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
210 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
213 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
214 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
215 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
216 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
217 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
218 #define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
220 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
221 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
222 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
223 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
224 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
225 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
226 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
228 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
229 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
231 /* Value extensions. */
232 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
233 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
234 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
235 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
237 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
238 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
240 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
242 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
243 /* Set NZCV flags from the high 4 bits of var. */
244 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
246 static void gen_exception(int excp)
248 TCGv tmp = new_tmp();
249 tcg_gen_movi_i32(tmp, excp);
250 gen_helper_exception(tmp);
254 static void gen_smul_dual(TCGv a, TCGv b)
256 TCGv tmp1 = new_tmp();
257 TCGv tmp2 = new_tmp();
258 tcg_gen_ext16s_i32(tmp1, a);
259 tcg_gen_ext16s_i32(tmp2, b);
260 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
262 tcg_gen_sari_i32(a, a, 16);
263 tcg_gen_sari_i32(b, b, 16);
264 tcg_gen_mul_i32(b, b, a);
265 tcg_gen_mov_i32(a, tmp1);
269 /* Byteswap each halfword. */
270 static void gen_rev16(TCGv var)
272 TCGv tmp = new_tmp();
273 tcg_gen_shri_i32(tmp, var, 8);
274 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
275 tcg_gen_shli_i32(var, var, 8);
276 tcg_gen_andi_i32(var, var, 0xff00ff00);
277 tcg_gen_or_i32(var, var, tmp);
281 /* Byteswap low halfword and sign extend. */
282 static void gen_revsh(TCGv var)
284 TCGv tmp = new_tmp();
285 tcg_gen_shri_i32(tmp, var, 8);
286 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
287 tcg_gen_shli_i32(var, var, 8);
288 tcg_gen_ext8s_i32(var, var);
289 tcg_gen_or_i32(var, var, tmp);
293 /* Unsigned bitfield extract. */
294 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
297 tcg_gen_shri_i32(var, var, shift);
298 tcg_gen_andi_i32(var, var, mask);
301 /* Signed bitfield extract. */
302 static void gen_sbfx(TCGv var, int shift, int width)
307 tcg_gen_sari_i32(var, var, shift);
308 if (shift + width < 32) {
309 signbit = 1u << (width - 1);
310 tcg_gen_andi_i32(var, var, (1u << width) - 1);
311 tcg_gen_xori_i32(var, var, signbit);
312 tcg_gen_subi_i32(var, var, signbit);
316 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
317 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
319 tcg_gen_andi_i32(val, val, mask);
320 tcg_gen_shli_i32(val, val, shift);
321 tcg_gen_andi_i32(base, base, ~(mask << shift));
322 tcg_gen_or_i32(dest, base, val);
325 /* Round the top 32 bits of a 64-bit value. */
326 static void gen_roundqd(TCGv a, TCGv b)
328 tcg_gen_shri_i32(a, a, 31);
329 tcg_gen_add_i32(a, a, b);
332 /* FIXME: Most targets have native widening multiplication.
333 It would be good to use that instead of a full wide multiply. */
334 /* 32x32->64 multiply. Marks inputs as dead. */
335 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
337 TCGv_i64 tmp1 = tcg_temp_new_i64();
338 TCGv_i64 tmp2 = tcg_temp_new_i64();
340 tcg_gen_extu_i32_i64(tmp1, a);
342 tcg_gen_extu_i32_i64(tmp2, b);
344 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
348 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
350 TCGv_i64 tmp1 = tcg_temp_new_i64();
351 TCGv_i64 tmp2 = tcg_temp_new_i64();
353 tcg_gen_ext_i32_i64(tmp1, a);
355 tcg_gen_ext_i32_i64(tmp2, b);
357 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
361 /* Unsigned 32x32->64 multiply. */
362 static void gen_op_mull_T0_T1(void)
364 TCGv_i64 tmp1 = tcg_temp_new_i64();
365 TCGv_i64 tmp2 = tcg_temp_new_i64();
367 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
368 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
369 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
370 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
371 tcg_gen_shri_i64(tmp1, tmp1, 32);
372 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
375 /* Signed 32x32->64 multiply. */
376 static void gen_imull(TCGv a, TCGv b)
378 TCGv_i64 tmp1 = tcg_temp_new_i64();
379 TCGv_i64 tmp2 = tcg_temp_new_i64();
381 tcg_gen_ext_i32_i64(tmp1, a);
382 tcg_gen_ext_i32_i64(tmp2, b);
383 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
384 tcg_gen_trunc_i64_i32(a, tmp1);
385 tcg_gen_shri_i64(tmp1, tmp1, 32);
386 tcg_gen_trunc_i64_i32(b, tmp1);
389 /* Swap low and high halfwords. */
390 static void gen_swap_half(TCGv var)
392 TCGv tmp = new_tmp();
393 tcg_gen_shri_i32(tmp, var, 16);
394 tcg_gen_shli_i32(var, var, 16);
395 tcg_gen_or_i32(var, var, tmp);
399 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
400 tmp = (t0 ^ t1) & 0x8000;
403 t0 = (t0 + t1) ^ tmp;
406 static void gen_add16(TCGv t0, TCGv t1)
408 TCGv tmp = new_tmp();
409 tcg_gen_xor_i32(tmp, t0, t1);
410 tcg_gen_andi_i32(tmp, tmp, 0x8000);
411 tcg_gen_andi_i32(t0, t0, ~0x8000);
412 tcg_gen_andi_i32(t1, t1, ~0x8000);
413 tcg_gen_add_i32(t0, t0, t1);
414 tcg_gen_xor_i32(t0, t0, tmp);
419 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
421 /* Set CF to the top bit of var. */
422 static void gen_set_CF_bit31(TCGv var)
424 TCGv tmp = new_tmp();
425 tcg_gen_shri_i32(tmp, var, 31);
430 /* Set N and Z flags from var. */
431 static inline void gen_logic_CC(TCGv var)
433 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
434 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
438 static void gen_adc_T0_T1(void)
442 tmp = load_cpu_field(CF);
443 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
447 /* dest = T0 + T1 + CF. */
448 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
451 tcg_gen_add_i32(dest, t0, t1);
452 tmp = load_cpu_field(CF);
453 tcg_gen_add_i32(dest, dest, tmp);
457 /* dest = T0 - T1 + CF - 1. */
458 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
461 tcg_gen_sub_i32(dest, t0, t1);
462 tmp = load_cpu_field(CF);
463 tcg_gen_add_i32(dest, dest, tmp);
464 tcg_gen_subi_i32(dest, dest, 1);
468 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
469 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
471 /* T0 &= ~T1. Clobbers T1. */
472 /* FIXME: Implement bic natively. */
473 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
475 TCGv tmp = new_tmp();
476 tcg_gen_not_i32(tmp, t1);
477 tcg_gen_and_i32(dest, t0, tmp);
480 static inline void gen_op_bicl_T0_T1(void)
486 /* FIXME: Implement this natively. */
487 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
489 /* FIXME: Implement this natively. */
490 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
498 tcg_gen_shri_i32(tmp, t1, i);
499 tcg_gen_shli_i32(t1, t1, 32 - i);
500 tcg_gen_or_i32(t0, t1, tmp);
504 static void shifter_out_im(TCGv var, int shift)
506 TCGv tmp = new_tmp();
508 tcg_gen_andi_i32(tmp, var, 1);
510 tcg_gen_shri_i32(tmp, var, shift);
512 tcg_gen_andi_i32(tmp, tmp, 1);
518 /* Shift by immediate. Includes special handling for shift == 0. */
519 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
525 shifter_out_im(var, 32 - shift);
526 tcg_gen_shli_i32(var, var, shift);
532 tcg_gen_shri_i32(var, var, 31);
535 tcg_gen_movi_i32(var, 0);
538 shifter_out_im(var, shift - 1);
539 tcg_gen_shri_i32(var, var, shift);
546 shifter_out_im(var, shift - 1);
549 tcg_gen_sari_i32(var, var, shift);
551 case 3: /* ROR/RRX */
554 shifter_out_im(var, shift - 1);
555 tcg_gen_rori_i32(var, var, shift); break;
557 TCGv tmp = load_cpu_field(CF);
559 shifter_out_im(var, 0);
560 tcg_gen_shri_i32(var, var, 1);
561 tcg_gen_shli_i32(tmp, tmp, 31);
562 tcg_gen_or_i32(var, var, tmp);
568 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
569 TCGv shift, int flags)
573 case 0: gen_helper_shl_cc(var, var, shift); break;
574 case 1: gen_helper_shr_cc(var, var, shift); break;
575 case 2: gen_helper_sar_cc(var, var, shift); break;
576 case 3: gen_helper_ror_cc(var, var, shift); break;
580 case 0: gen_helper_shl(var, var, shift); break;
581 case 1: gen_helper_shr(var, var, shift); break;
582 case 2: gen_helper_sar(var, var, shift); break;
583 case 3: gen_helper_ror(var, var, shift); break;
589 #define PAS_OP(pfx) \
591 case 0: gen_pas_helper(glue(pfx,add16)); break; \
592 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
593 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
594 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
595 case 4: gen_pas_helper(glue(pfx,add8)); break; \
596 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
598 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
603 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
605 tmp = tcg_temp_new_ptr();
606 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
610 tmp = tcg_temp_new_ptr();
611 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
614 #undef gen_pas_helper
615 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
628 #undef gen_pas_helper
633 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
634 #define PAS_OP(pfx) \
636 case 0: gen_pas_helper(glue(pfx,add8)); break; \
637 case 1: gen_pas_helper(glue(pfx,add16)); break; \
638 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
639 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
640 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
641 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
643 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
648 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
650 tmp = tcg_temp_new_ptr();
651 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
655 tmp = tcg_temp_new_ptr();
656 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
659 #undef gen_pas_helper
660 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
673 #undef gen_pas_helper
678 static void gen_test_cc(int cc, int label)
686 tmp = load_cpu_field(ZF);
687 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
690 tmp = load_cpu_field(ZF);
691 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
694 tmp = load_cpu_field(CF);
695 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
698 tmp = load_cpu_field(CF);
699 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
702 tmp = load_cpu_field(NF);
703 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
706 tmp = load_cpu_field(NF);
707 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
710 tmp = load_cpu_field(VF);
711 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
714 tmp = load_cpu_field(VF);
715 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
717 case 8: /* hi: C && !Z */
718 inv = gen_new_label();
719 tmp = load_cpu_field(CF);
720 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
722 tmp = load_cpu_field(ZF);
723 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
726 case 9: /* ls: !C || Z */
727 tmp = load_cpu_field(CF);
728 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
730 tmp = load_cpu_field(ZF);
731 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
733 case 10: /* ge: N == V -> N ^ V == 0 */
734 tmp = load_cpu_field(VF);
735 tmp2 = load_cpu_field(NF);
736 tcg_gen_xor_i32(tmp, tmp, tmp2);
738 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
740 case 11: /* lt: N != V -> N ^ V != 0 */
741 tmp = load_cpu_field(VF);
742 tmp2 = load_cpu_field(NF);
743 tcg_gen_xor_i32(tmp, tmp, tmp2);
745 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
747 case 12: /* gt: !Z && N == V */
748 inv = gen_new_label();
749 tmp = load_cpu_field(ZF);
750 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
752 tmp = load_cpu_field(VF);
753 tmp2 = load_cpu_field(NF);
754 tcg_gen_xor_i32(tmp, tmp, tmp2);
756 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
759 case 13: /* le: Z || N != V */
760 tmp = load_cpu_field(ZF);
761 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
763 tmp = load_cpu_field(VF);
764 tmp2 = load_cpu_field(NF);
765 tcg_gen_xor_i32(tmp, tmp, tmp2);
767 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
770 fprintf(stderr, "Bad condition code 0x%x\n", cc);
776 static const uint8_t table_logic_cc[16] = {
795 /* Set PC and Thumb state from an immediate address. */
796 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
800 s->is_jmp = DISAS_UPDATE;
802 if (s->thumb != (addr & 1)) {
803 tcg_gen_movi_i32(tmp, addr & 1);
804 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
806 tcg_gen_movi_i32(tmp, addr & ~1);
807 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
811 /* Set PC and Thumb state from var. var is marked as dead. */
812 static inline void gen_bx(DisasContext *s, TCGv var)
816 s->is_jmp = DISAS_UPDATE;
818 tcg_gen_andi_i32(tmp, var, 1);
819 store_cpu_field(tmp, thumb);
820 tcg_gen_andi_i32(var, var, ~1);
821 store_cpu_field(var, regs[15]);
824 /* TODO: This should be removed. Use gen_bx instead. */
825 static inline void gen_bx_T0(DisasContext *s)
827 TCGv tmp = new_tmp();
828 tcg_gen_mov_i32(tmp, cpu_T[0]);
832 static inline TCGv gen_ld8s(TCGv addr, int index)
834 TCGv tmp = new_tmp();
835 tcg_gen_qemu_ld8s(tmp, addr, index);
838 static inline TCGv gen_ld8u(TCGv addr, int index)
840 TCGv tmp = new_tmp();
841 tcg_gen_qemu_ld8u(tmp, addr, index);
844 static inline TCGv gen_ld16s(TCGv addr, int index)
846 TCGv tmp = new_tmp();
847 tcg_gen_qemu_ld16s(tmp, addr, index);
850 static inline TCGv gen_ld16u(TCGv addr, int index)
852 TCGv tmp = new_tmp();
853 tcg_gen_qemu_ld16u(tmp, addr, index);
856 static inline TCGv gen_ld32(TCGv addr, int index)
858 TCGv tmp = new_tmp();
859 tcg_gen_qemu_ld32u(tmp, addr, index);
862 static inline void gen_st8(TCGv val, TCGv addr, int index)
864 tcg_gen_qemu_st8(val, addr, index);
867 static inline void gen_st16(TCGv val, TCGv addr, int index)
869 tcg_gen_qemu_st16(val, addr, index);
872 static inline void gen_st32(TCGv val, TCGv addr, int index)
874 tcg_gen_qemu_st32(val, addr, index);
878 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
880 load_reg_var(s, cpu_T[0], reg);
883 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
885 load_reg_var(s, cpu_T[1], reg);
888 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
890 load_reg_var(s, cpu_T[2], reg);
893 static inline void gen_set_pc_im(uint32_t val)
895 TCGv tmp = new_tmp();
896 tcg_gen_movi_i32(tmp, val);
897 store_cpu_field(tmp, regs[15]);
900 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
905 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
909 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
912 s->is_jmp = DISAS_JUMP;
916 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
918 gen_movl_reg_TN(s, reg, 0);
921 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
923 gen_movl_reg_TN(s, reg, 1);
926 /* Force a TB lookup after an instruction that changes the CPU state. */
927 static inline void gen_lookup_tb(DisasContext *s)
929 gen_op_movl_T0_im(s->pc);
930 gen_movl_reg_T0(s, 15);
931 s->is_jmp = DISAS_UPDATE;
934 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
937 int val, rm, shift, shiftop;
940 if (!(insn & (1 << 25))) {
943 if (!(insn & (1 << 23)))
946 tcg_gen_addi_i32(var, var, val);
950 shift = (insn >> 7) & 0x1f;
951 shiftop = (insn >> 5) & 3;
952 offset = load_reg(s, rm);
953 gen_arm_shift_im(offset, shiftop, shift, 0);
954 if (!(insn & (1 << 23)))
955 tcg_gen_sub_i32(var, var, offset);
957 tcg_gen_add_i32(var, var, offset);
962 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
968 if (insn & (1 << 22)) {
970 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
971 if (!(insn & (1 << 23)))
975 tcg_gen_addi_i32(var, var, val);
979 tcg_gen_addi_i32(var, var, extra);
981 offset = load_reg(s, rm);
982 if (!(insn & (1 << 23)))
983 tcg_gen_sub_i32(var, var, offset);
985 tcg_gen_add_i32(var, var, offset);
990 #define VFP_OP2(name) \
991 static inline void gen_vfp_##name(int dp) \
994 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
996 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1006 static inline void gen_vfp_abs(int dp)
1009 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1011 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1014 static inline void gen_vfp_neg(int dp)
1017 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1019 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1022 static inline void gen_vfp_sqrt(int dp)
1025 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1027 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1030 static inline void gen_vfp_cmp(int dp)
1033 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1035 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1038 static inline void gen_vfp_cmpe(int dp)
1041 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1043 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1046 static inline void gen_vfp_F1_ld0(int dp)
1049 tcg_gen_movi_i64(cpu_F1d, 0);
1051 tcg_gen_movi_i32(cpu_F1s, 0);
1054 static inline void gen_vfp_uito(int dp)
1057 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1059 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1062 static inline void gen_vfp_sito(int dp)
1065 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1067 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1070 static inline void gen_vfp_toui(int dp)
1073 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1075 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1078 static inline void gen_vfp_touiz(int dp)
1081 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1083 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1086 static inline void gen_vfp_tosi(int dp)
1089 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1091 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1094 static inline void gen_vfp_tosiz(int dp)
1097 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1099 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1102 #define VFP_GEN_FIX(name) \
1103 static inline void gen_vfp_##name(int dp, int shift) \
1106 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1108 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1120 static inline void gen_vfp_ld(DisasContext *s, int dp)
1123 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1125 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1128 static inline void gen_vfp_st(DisasContext *s, int dp)
1131 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1133 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1137 vfp_reg_offset (int dp, int reg)
1140 return offsetof(CPUARMState, vfp.regs[reg]);
1142 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1143 + offsetof(CPU_DoubleU, l.upper);
1145 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1146 + offsetof(CPU_DoubleU, l.lower);
1150 /* Return the offset of a 32-bit piece of a NEON register.
1151 zero is the least significant end of the register. */
1153 neon_reg_offset (int reg, int n)
1157 return vfp_reg_offset(0, sreg);
1160 /* FIXME: Remove these. */
1161 #define neon_T0 cpu_T[0]
1162 #define neon_T1 cpu_T[1]
1163 #define NEON_GET_REG(T, reg, n) \
1164 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1165 #define NEON_SET_REG(T, reg, n) \
1166 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1168 static TCGv neon_load_reg(int reg, int pass)
1170 TCGv tmp = new_tmp();
1171 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1175 static void neon_store_reg(int reg, int pass, TCGv var)
1177 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1181 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1183 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1186 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1188 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1191 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1192 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1193 #define tcg_gen_st_f32 tcg_gen_st_i32
1194 #define tcg_gen_st_f64 tcg_gen_st_i64
1196 static inline void gen_mov_F0_vreg(int dp, int reg)
1199 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1201 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1204 static inline void gen_mov_F1_vreg(int dp, int reg)
1207 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1209 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1212 static inline void gen_mov_vreg_F0(int dp, int reg)
1215 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1217 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1220 #define ARM_CP_RW_BIT (1 << 20)
1222 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1224 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1227 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1229 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1232 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1234 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1237 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1239 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1242 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1244 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1247 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1249 iwmmxt_store_reg(cpu_M0, rn);
1252 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1254 iwmmxt_load_reg(cpu_M0, rn);
1257 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1259 iwmmxt_load_reg(cpu_V1, rn);
1260 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1263 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1265 iwmmxt_load_reg(cpu_V1, rn);
1266 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1269 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1271 iwmmxt_load_reg(cpu_V1, rn);
1272 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1275 #define IWMMXT_OP(name) \
1276 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1278 iwmmxt_load_reg(cpu_V1, rn); \
1279 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1282 #define IWMMXT_OP_ENV(name) \
1283 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1285 iwmmxt_load_reg(cpu_V1, rn); \
1286 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1289 #define IWMMXT_OP_ENV_SIZE(name) \
1290 IWMMXT_OP_ENV(name##b) \
1291 IWMMXT_OP_ENV(name##w) \
1292 IWMMXT_OP_ENV(name##l)
1294 #define IWMMXT_OP_ENV1(name) \
1295 static inline void gen_op_iwmmxt_##name##_M0(void) \
1297 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1311 IWMMXT_OP_ENV_SIZE(unpackl)
1312 IWMMXT_OP_ENV_SIZE(unpackh)
1314 IWMMXT_OP_ENV1(unpacklub)
1315 IWMMXT_OP_ENV1(unpackluw)
1316 IWMMXT_OP_ENV1(unpacklul)
1317 IWMMXT_OP_ENV1(unpackhub)
1318 IWMMXT_OP_ENV1(unpackhuw)
1319 IWMMXT_OP_ENV1(unpackhul)
1320 IWMMXT_OP_ENV1(unpacklsb)
1321 IWMMXT_OP_ENV1(unpacklsw)
1322 IWMMXT_OP_ENV1(unpacklsl)
1323 IWMMXT_OP_ENV1(unpackhsb)
1324 IWMMXT_OP_ENV1(unpackhsw)
1325 IWMMXT_OP_ENV1(unpackhsl)
1327 IWMMXT_OP_ENV_SIZE(cmpeq)
1328 IWMMXT_OP_ENV_SIZE(cmpgtu)
1329 IWMMXT_OP_ENV_SIZE(cmpgts)
1331 IWMMXT_OP_ENV_SIZE(mins)
1332 IWMMXT_OP_ENV_SIZE(minu)
1333 IWMMXT_OP_ENV_SIZE(maxs)
1334 IWMMXT_OP_ENV_SIZE(maxu)
1336 IWMMXT_OP_ENV_SIZE(subn)
1337 IWMMXT_OP_ENV_SIZE(addn)
1338 IWMMXT_OP_ENV_SIZE(subu)
1339 IWMMXT_OP_ENV_SIZE(addu)
1340 IWMMXT_OP_ENV_SIZE(subs)
1341 IWMMXT_OP_ENV_SIZE(adds)
1343 IWMMXT_OP_ENV(avgb0)
1344 IWMMXT_OP_ENV(avgb1)
1345 IWMMXT_OP_ENV(avgw0)
1346 IWMMXT_OP_ENV(avgw1)
1350 IWMMXT_OP_ENV(packuw)
1351 IWMMXT_OP_ENV(packul)
1352 IWMMXT_OP_ENV(packuq)
1353 IWMMXT_OP_ENV(packsw)
1354 IWMMXT_OP_ENV(packsl)
1355 IWMMXT_OP_ENV(packsq)
1357 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1359 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1362 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1364 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1367 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1369 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1372 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1374 iwmmxt_load_reg(cpu_V1, rn);
1375 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1378 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1380 TCGv tmp = tcg_const_i32(shift);
1381 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1384 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1386 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1387 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1388 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1391 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1393 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1394 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1395 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1398 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1400 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1401 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1403 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1406 static void gen_op_iwmmxt_set_mup(void)
1409 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1410 tcg_gen_ori_i32(tmp, tmp, 2);
1411 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1414 static void gen_op_iwmmxt_set_cup(void)
1417 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1418 tcg_gen_ori_i32(tmp, tmp, 1);
1419 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1422 static void gen_op_iwmmxt_setpsr_nz(void)
1424 TCGv tmp = new_tmp();
1425 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1426 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1429 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1431 iwmmxt_load_reg(cpu_V1, rn);
1432 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1433 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1437 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1439 iwmmxt_load_reg(cpu_V0, rn);
1440 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1441 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1442 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1445 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1447 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1448 iwmmxt_store_reg(cpu_V0, rn);
1451 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1456 rd = (insn >> 16) & 0xf;
1457 gen_movl_T1_reg(s, rd);
1459 offset = (insn & 0xff) << ((insn >> 7) & 2);
1460 if (insn & (1 << 24)) {
1462 if (insn & (1 << 23))
1463 gen_op_addl_T1_im(offset);
1465 gen_op_addl_T1_im(-offset);
1467 if (insn & (1 << 21))
1468 gen_movl_reg_T1(s, rd);
1469 } else if (insn & (1 << 21)) {
1471 if (insn & (1 << 23))
1472 gen_op_movl_T0_im(offset);
1474 gen_op_movl_T0_im(- offset);
1475 gen_op_addl_T0_T1();
1476 gen_movl_reg_T0(s, rd);
1477 } else if (!(insn & (1 << 23)))
1482 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1484 int rd = (insn >> 0) & 0xf;
1486 if (insn & (1 << 8))
1487 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1490 gen_op_iwmmxt_movl_T0_wCx(rd);
1492 gen_iwmmxt_movl_T0_T1_wRn(rd);
1494 gen_op_movl_T1_im(mask);
1495 gen_op_andl_T0_T1();
1499 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1500 (ie. an undefined instruction). */
1501 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1504 int rdhi, rdlo, rd0, rd1, i;
1507 if ((insn & 0x0e000e00) == 0x0c000000) {
1508 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1510 rdlo = (insn >> 12) & 0xf;
1511 rdhi = (insn >> 16) & 0xf;
1512 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1513 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1514 gen_movl_reg_T0(s, rdlo);
1515 gen_movl_reg_T1(s, rdhi);
1516 } else { /* TMCRR */
1517 gen_movl_T0_reg(s, rdlo);
1518 gen_movl_T1_reg(s, rdhi);
1519 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1520 gen_op_iwmmxt_set_mup();
1525 wrd = (insn >> 12) & 0xf;
1526 if (gen_iwmmxt_address(s, insn))
1528 if (insn & ARM_CP_RW_BIT) {
1529 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1530 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1531 tcg_gen_mov_i32(cpu_T[0], tmp);
1533 gen_op_iwmmxt_movl_wCx_T0(wrd);
1536 if (insn & (1 << 8)) {
1537 if (insn & (1 << 22)) { /* WLDRD */
1538 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1540 } else { /* WLDRW wRd */
1541 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1544 if (insn & (1 << 22)) { /* WLDRH */
1545 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1546 } else { /* WLDRB */
1547 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1551 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1554 gen_op_iwmmxt_movq_wRn_M0(wrd);
1557 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1558 gen_op_iwmmxt_movl_T0_wCx(wrd);
1560 tcg_gen_mov_i32(tmp, cpu_T[0]);
1561 gen_st32(tmp, cpu_T[1], IS_USER(s));
1563 gen_op_iwmmxt_movq_M0_wRn(wrd);
1565 if (insn & (1 << 8)) {
1566 if (insn & (1 << 22)) { /* WSTRD */
1568 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1569 } else { /* WSTRW wRd */
1570 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1571 gen_st32(tmp, cpu_T[1], IS_USER(s));
1574 if (insn & (1 << 22)) { /* WSTRH */
1575 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1576 gen_st16(tmp, cpu_T[1], IS_USER(s));
1577 } else { /* WSTRB */
1578 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1579 gen_st8(tmp, cpu_T[1], IS_USER(s));
1587 if ((insn & 0x0f000000) != 0x0e000000)
1590 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1591 case 0x000: /* WOR */
1592 wrd = (insn >> 12) & 0xf;
1593 rd0 = (insn >> 0) & 0xf;
1594 rd1 = (insn >> 16) & 0xf;
1595 gen_op_iwmmxt_movq_M0_wRn(rd0);
1596 gen_op_iwmmxt_orq_M0_wRn(rd1);
1597 gen_op_iwmmxt_setpsr_nz();
1598 gen_op_iwmmxt_movq_wRn_M0(wrd);
1599 gen_op_iwmmxt_set_mup();
1600 gen_op_iwmmxt_set_cup();
1602 case 0x011: /* TMCR */
1605 rd = (insn >> 12) & 0xf;
1606 wrd = (insn >> 16) & 0xf;
1608 case ARM_IWMMXT_wCID:
1609 case ARM_IWMMXT_wCASF:
1611 case ARM_IWMMXT_wCon:
1612 gen_op_iwmmxt_set_cup();
1614 case ARM_IWMMXT_wCSSF:
1615 gen_op_iwmmxt_movl_T0_wCx(wrd);
1616 gen_movl_T1_reg(s, rd);
1617 gen_op_bicl_T0_T1();
1618 gen_op_iwmmxt_movl_wCx_T0(wrd);
1620 case ARM_IWMMXT_wCGR0:
1621 case ARM_IWMMXT_wCGR1:
1622 case ARM_IWMMXT_wCGR2:
1623 case ARM_IWMMXT_wCGR3:
1624 gen_op_iwmmxt_set_cup();
1625 gen_movl_reg_T0(s, rd);
1626 gen_op_iwmmxt_movl_wCx_T0(wrd);
1632 case 0x100: /* WXOR */
1633 wrd = (insn >> 12) & 0xf;
1634 rd0 = (insn >> 0) & 0xf;
1635 rd1 = (insn >> 16) & 0xf;
1636 gen_op_iwmmxt_movq_M0_wRn(rd0);
1637 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1638 gen_op_iwmmxt_setpsr_nz();
1639 gen_op_iwmmxt_movq_wRn_M0(wrd);
1640 gen_op_iwmmxt_set_mup();
1641 gen_op_iwmmxt_set_cup();
1643 case 0x111: /* TMRC */
1646 rd = (insn >> 12) & 0xf;
1647 wrd = (insn >> 16) & 0xf;
1648 gen_op_iwmmxt_movl_T0_wCx(wrd);
1649 gen_movl_reg_T0(s, rd);
1651 case 0x300: /* WANDN */
1652 wrd = (insn >> 12) & 0xf;
1653 rd0 = (insn >> 0) & 0xf;
1654 rd1 = (insn >> 16) & 0xf;
1655 gen_op_iwmmxt_movq_M0_wRn(rd0);
1656 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1657 gen_op_iwmmxt_andq_M0_wRn(rd1);
1658 gen_op_iwmmxt_setpsr_nz();
1659 gen_op_iwmmxt_movq_wRn_M0(wrd);
1660 gen_op_iwmmxt_set_mup();
1661 gen_op_iwmmxt_set_cup();
1663 case 0x200: /* WAND */
1664 wrd = (insn >> 12) & 0xf;
1665 rd0 = (insn >> 0) & 0xf;
1666 rd1 = (insn >> 16) & 0xf;
1667 gen_op_iwmmxt_movq_M0_wRn(rd0);
1668 gen_op_iwmmxt_andq_M0_wRn(rd1);
1669 gen_op_iwmmxt_setpsr_nz();
1670 gen_op_iwmmxt_movq_wRn_M0(wrd);
1671 gen_op_iwmmxt_set_mup();
1672 gen_op_iwmmxt_set_cup();
1674 case 0x810: case 0xa10: /* WMADD */
1675 wrd = (insn >> 12) & 0xf;
1676 rd0 = (insn >> 0) & 0xf;
1677 rd1 = (insn >> 16) & 0xf;
1678 gen_op_iwmmxt_movq_M0_wRn(rd0);
1679 if (insn & (1 << 21))
1680 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1682 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1683 gen_op_iwmmxt_movq_wRn_M0(wrd);
1684 gen_op_iwmmxt_set_mup();
1686 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1687 wrd = (insn >> 12) & 0xf;
1688 rd0 = (insn >> 16) & 0xf;
1689 rd1 = (insn >> 0) & 0xf;
1690 gen_op_iwmmxt_movq_M0_wRn(rd0);
1691 switch ((insn >> 22) & 3) {
1693 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1696 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1699 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1704 gen_op_iwmmxt_movq_wRn_M0(wrd);
1705 gen_op_iwmmxt_set_mup();
1706 gen_op_iwmmxt_set_cup();
1708 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1709 wrd = (insn >> 12) & 0xf;
1710 rd0 = (insn >> 16) & 0xf;
1711 rd1 = (insn >> 0) & 0xf;
1712 gen_op_iwmmxt_movq_M0_wRn(rd0);
1713 switch ((insn >> 22) & 3) {
1715 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1718 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1721 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1726 gen_op_iwmmxt_movq_wRn_M0(wrd);
1727 gen_op_iwmmxt_set_mup();
1728 gen_op_iwmmxt_set_cup();
1730 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1731 wrd = (insn >> 12) & 0xf;
1732 rd0 = (insn >> 16) & 0xf;
1733 rd1 = (insn >> 0) & 0xf;
1734 gen_op_iwmmxt_movq_M0_wRn(rd0);
1735 if (insn & (1 << 22))
1736 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1738 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1739 if (!(insn & (1 << 20)))
1740 gen_op_iwmmxt_addl_M0_wRn(wrd);
1741 gen_op_iwmmxt_movq_wRn_M0(wrd);
1742 gen_op_iwmmxt_set_mup();
1744 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1745 wrd = (insn >> 12) & 0xf;
1746 rd0 = (insn >> 16) & 0xf;
1747 rd1 = (insn >> 0) & 0xf;
1748 gen_op_iwmmxt_movq_M0_wRn(rd0);
1749 if (insn & (1 << 21)) {
1750 if (insn & (1 << 20))
1751 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1753 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1755 if (insn & (1 << 20))
1756 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1758 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1760 gen_op_iwmmxt_movq_wRn_M0(wrd);
1761 gen_op_iwmmxt_set_mup();
1763 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1764 wrd = (insn >> 12) & 0xf;
1765 rd0 = (insn >> 16) & 0xf;
1766 rd1 = (insn >> 0) & 0xf;
1767 gen_op_iwmmxt_movq_M0_wRn(rd0);
1768 if (insn & (1 << 21))
1769 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1771 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1772 if (!(insn & (1 << 20))) {
1773 iwmmxt_load_reg(cpu_V1, wrd);
1774 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1776 gen_op_iwmmxt_movq_wRn_M0(wrd);
1777 gen_op_iwmmxt_set_mup();
1779 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1780 wrd = (insn >> 12) & 0xf;
1781 rd0 = (insn >> 16) & 0xf;
1782 rd1 = (insn >> 0) & 0xf;
1783 gen_op_iwmmxt_movq_M0_wRn(rd0);
1784 switch ((insn >> 22) & 3) {
1786 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1789 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1792 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1797 gen_op_iwmmxt_movq_wRn_M0(wrd);
1798 gen_op_iwmmxt_set_mup();
1799 gen_op_iwmmxt_set_cup();
1801 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1802 wrd = (insn >> 12) & 0xf;
1803 rd0 = (insn >> 16) & 0xf;
1804 rd1 = (insn >> 0) & 0xf;
1805 gen_op_iwmmxt_movq_M0_wRn(rd0);
1806 if (insn & (1 << 22)) {
1807 if (insn & (1 << 20))
1808 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1810 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1812 if (insn & (1 << 20))
1813 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1815 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1817 gen_op_iwmmxt_movq_wRn_M0(wrd);
1818 gen_op_iwmmxt_set_mup();
1819 gen_op_iwmmxt_set_cup();
1821 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1822 wrd = (insn >> 12) & 0xf;
1823 rd0 = (insn >> 16) & 0xf;
1824 rd1 = (insn >> 0) & 0xf;
1825 gen_op_iwmmxt_movq_M0_wRn(rd0);
1826 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1827 gen_op_movl_T1_im(7);
1828 gen_op_andl_T0_T1();
1829 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1830 gen_op_iwmmxt_movq_wRn_M0(wrd);
1831 gen_op_iwmmxt_set_mup();
1833 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1834 rd = (insn >> 12) & 0xf;
1835 wrd = (insn >> 16) & 0xf;
1836 gen_movl_T0_reg(s, rd);
1837 gen_op_iwmmxt_movq_M0_wRn(wrd);
1838 switch ((insn >> 6) & 3) {
1840 gen_op_movl_T1_im(0xff);
1841 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1844 gen_op_movl_T1_im(0xffff);
1845 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1848 gen_op_movl_T1_im(0xffffffff);
1849 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1854 gen_op_iwmmxt_movq_wRn_M0(wrd);
1855 gen_op_iwmmxt_set_mup();
1857 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1858 rd = (insn >> 12) & 0xf;
1859 wrd = (insn >> 16) & 0xf;
1862 gen_op_iwmmxt_movq_M0_wRn(wrd);
1863 switch ((insn >> 22) & 3) {
1866 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1868 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1873 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1875 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1879 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1884 gen_movl_reg_T0(s, rd);
1886 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1887 if ((insn & 0x000ff008) != 0x0003f000)
1889 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1890 switch ((insn >> 22) & 3) {
1892 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1895 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1898 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1903 gen_op_shll_T1_im(28);
1904 gen_set_nzcv(cpu_T[1]);
1906 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1907 rd = (insn >> 12) & 0xf;
1908 wrd = (insn >> 16) & 0xf;
1909 gen_movl_T0_reg(s, rd);
1910 switch ((insn >> 6) & 3) {
1912 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1915 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1918 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1923 gen_op_iwmmxt_movq_wRn_M0(wrd);
1924 gen_op_iwmmxt_set_mup();
1926 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1927 if ((insn & 0x000ff00f) != 0x0003f000)
1929 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1930 switch ((insn >> 22) & 3) {
1932 for (i = 0; i < 7; i ++) {
1933 gen_op_shll_T1_im(4);
1934 gen_op_andl_T0_T1();
1938 for (i = 0; i < 3; i ++) {
1939 gen_op_shll_T1_im(8);
1940 gen_op_andl_T0_T1();
1944 gen_op_shll_T1_im(16);
1945 gen_op_andl_T0_T1();
1950 gen_set_nzcv(cpu_T[0]);
1952 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1953 wrd = (insn >> 12) & 0xf;
1954 rd0 = (insn >> 16) & 0xf;
1955 gen_op_iwmmxt_movq_M0_wRn(rd0);
1956 switch ((insn >> 22) & 3) {
1958 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1961 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1964 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1969 gen_op_iwmmxt_movq_wRn_M0(wrd);
1970 gen_op_iwmmxt_set_mup();
1972 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1973 if ((insn & 0x000ff00f) != 0x0003f000)
1975 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1976 switch ((insn >> 22) & 3) {
1978 for (i = 0; i < 7; i ++) {
1979 gen_op_shll_T1_im(4);
1984 for (i = 0; i < 3; i ++) {
1985 gen_op_shll_T1_im(8);
1990 gen_op_shll_T1_im(16);
1996 gen_set_nzcv(cpu_T[0]);
1998 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1999 rd = (insn >> 12) & 0xf;
2000 rd0 = (insn >> 16) & 0xf;
2001 if ((insn & 0xf) != 0)
2003 gen_op_iwmmxt_movq_M0_wRn(rd0);
2004 switch ((insn >> 22) & 3) {
2006 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2009 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2012 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2017 gen_movl_reg_T0(s, rd);
2019 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2020 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2021 wrd = (insn >> 12) & 0xf;
2022 rd0 = (insn >> 16) & 0xf;
2023 rd1 = (insn >> 0) & 0xf;
2024 gen_op_iwmmxt_movq_M0_wRn(rd0);
2025 switch ((insn >> 22) & 3) {
2027 if (insn & (1 << 21))
2028 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2030 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2033 if (insn & (1 << 21))
2034 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2036 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2039 if (insn & (1 << 21))
2040 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2042 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2047 gen_op_iwmmxt_movq_wRn_M0(wrd);
2048 gen_op_iwmmxt_set_mup();
2049 gen_op_iwmmxt_set_cup();
2051 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2052 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2053 wrd = (insn >> 12) & 0xf;
2054 rd0 = (insn >> 16) & 0xf;
2055 gen_op_iwmmxt_movq_M0_wRn(rd0);
2056 switch ((insn >> 22) & 3) {
2058 if (insn & (1 << 21))
2059 gen_op_iwmmxt_unpacklsb_M0();
2061 gen_op_iwmmxt_unpacklub_M0();
2064 if (insn & (1 << 21))
2065 gen_op_iwmmxt_unpacklsw_M0();
2067 gen_op_iwmmxt_unpackluw_M0();
2070 if (insn & (1 << 21))
2071 gen_op_iwmmxt_unpacklsl_M0();
2073 gen_op_iwmmxt_unpacklul_M0();
2078 gen_op_iwmmxt_movq_wRn_M0(wrd);
2079 gen_op_iwmmxt_set_mup();
2080 gen_op_iwmmxt_set_cup();
2082 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2083 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2084 wrd = (insn >> 12) & 0xf;
2085 rd0 = (insn >> 16) & 0xf;
2086 gen_op_iwmmxt_movq_M0_wRn(rd0);
2087 switch ((insn >> 22) & 3) {
2089 if (insn & (1 << 21))
2090 gen_op_iwmmxt_unpackhsb_M0();
2092 gen_op_iwmmxt_unpackhub_M0();
2095 if (insn & (1 << 21))
2096 gen_op_iwmmxt_unpackhsw_M0();
2098 gen_op_iwmmxt_unpackhuw_M0();
2101 if (insn & (1 << 21))
2102 gen_op_iwmmxt_unpackhsl_M0();
2104 gen_op_iwmmxt_unpackhul_M0();
2109 gen_op_iwmmxt_movq_wRn_M0(wrd);
2110 gen_op_iwmmxt_set_mup();
2111 gen_op_iwmmxt_set_cup();
2113 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2114 case 0x214: case 0x614: case 0xa14: case 0xe14:
2115 wrd = (insn >> 12) & 0xf;
2116 rd0 = (insn >> 16) & 0xf;
2117 gen_op_iwmmxt_movq_M0_wRn(rd0);
2118 if (gen_iwmmxt_shift(insn, 0xff))
2120 switch ((insn >> 22) & 3) {
2124 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2127 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2130 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2133 gen_op_iwmmxt_movq_wRn_M0(wrd);
2134 gen_op_iwmmxt_set_mup();
2135 gen_op_iwmmxt_set_cup();
2137 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2138 case 0x014: case 0x414: case 0x814: case 0xc14:
2139 wrd = (insn >> 12) & 0xf;
2140 rd0 = (insn >> 16) & 0xf;
2141 gen_op_iwmmxt_movq_M0_wRn(rd0);
2142 if (gen_iwmmxt_shift(insn, 0xff))
2144 switch ((insn >> 22) & 3) {
2148 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2151 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2154 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd);
2158 gen_op_iwmmxt_set_mup();
2159 gen_op_iwmmxt_set_cup();
2161 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2162 case 0x114: case 0x514: case 0x914: case 0xd14:
2163 wrd = (insn >> 12) & 0xf;
2164 rd0 = (insn >> 16) & 0xf;
2165 gen_op_iwmmxt_movq_M0_wRn(rd0);
2166 if (gen_iwmmxt_shift(insn, 0xff))
2168 switch ((insn >> 22) & 3) {
2172 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2175 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2178 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2181 gen_op_iwmmxt_movq_wRn_M0(wrd);
2182 gen_op_iwmmxt_set_mup();
2183 gen_op_iwmmxt_set_cup();
2185 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2186 case 0x314: case 0x714: case 0xb14: case 0xf14:
2187 wrd = (insn >> 12) & 0xf;
2188 rd0 = (insn >> 16) & 0xf;
2189 gen_op_iwmmxt_movq_M0_wRn(rd0);
2190 switch ((insn >> 22) & 3) {
2194 if (gen_iwmmxt_shift(insn, 0xf))
2196 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2199 if (gen_iwmmxt_shift(insn, 0x1f))
2201 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2204 if (gen_iwmmxt_shift(insn, 0x3f))
2206 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2209 gen_op_iwmmxt_movq_wRn_M0(wrd);
2210 gen_op_iwmmxt_set_mup();
2211 gen_op_iwmmxt_set_cup();
2213 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2214 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2215 wrd = (insn >> 12) & 0xf;
2216 rd0 = (insn >> 16) & 0xf;
2217 rd1 = (insn >> 0) & 0xf;
2218 gen_op_iwmmxt_movq_M0_wRn(rd0);
2219 switch ((insn >> 22) & 3) {
2221 if (insn & (1 << 21))
2222 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2224 gen_op_iwmmxt_minub_M0_wRn(rd1);
2227 if (insn & (1 << 21))
2228 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2230 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2233 if (insn & (1 << 21))
2234 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2236 gen_op_iwmmxt_minul_M0_wRn(rd1);
2241 gen_op_iwmmxt_movq_wRn_M0(wrd);
2242 gen_op_iwmmxt_set_mup();
2244 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2245 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2246 wrd = (insn >> 12) & 0xf;
2247 rd0 = (insn >> 16) & 0xf;
2248 rd1 = (insn >> 0) & 0xf;
2249 gen_op_iwmmxt_movq_M0_wRn(rd0);
2250 switch ((insn >> 22) & 3) {
2252 if (insn & (1 << 21))
2253 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2255 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2258 if (insn & (1 << 21))
2259 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2261 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2264 if (insn & (1 << 21))
2265 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2267 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2272 gen_op_iwmmxt_movq_wRn_M0(wrd);
2273 gen_op_iwmmxt_set_mup();
2275 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2276 case 0x402: case 0x502: case 0x602: case 0x702:
2277 wrd = (insn >> 12) & 0xf;
2278 rd0 = (insn >> 16) & 0xf;
2279 rd1 = (insn >> 0) & 0xf;
2280 gen_op_iwmmxt_movq_M0_wRn(rd0);
2281 gen_op_movl_T0_im((insn >> 20) & 3);
2282 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2283 gen_op_iwmmxt_movq_wRn_M0(wrd);
2284 gen_op_iwmmxt_set_mup();
2286 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2287 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2288 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2289 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2290 wrd = (insn >> 12) & 0xf;
2291 rd0 = (insn >> 16) & 0xf;
2292 rd1 = (insn >> 0) & 0xf;
2293 gen_op_iwmmxt_movq_M0_wRn(rd0);
2294 switch ((insn >> 20) & 0xf) {
2296 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2299 gen_op_iwmmxt_subub_M0_wRn(rd1);
2302 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2305 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2308 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2311 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2314 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2317 gen_op_iwmmxt_subul_M0_wRn(rd1);
2320 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2325 gen_op_iwmmxt_movq_wRn_M0(wrd);
2326 gen_op_iwmmxt_set_mup();
2327 gen_op_iwmmxt_set_cup();
2329 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2330 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2331 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2332 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2333 wrd = (insn >> 12) & 0xf;
2334 rd0 = (insn >> 16) & 0xf;
2335 gen_op_iwmmxt_movq_M0_wRn(rd0);
2336 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2337 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2338 gen_op_iwmmxt_movq_wRn_M0(wrd);
2339 gen_op_iwmmxt_set_mup();
2340 gen_op_iwmmxt_set_cup();
2342 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2343 case 0x418: case 0x518: case 0x618: case 0x718:
2344 case 0x818: case 0x918: case 0xa18: case 0xb18:
2345 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2346 wrd = (insn >> 12) & 0xf;
2347 rd0 = (insn >> 16) & 0xf;
2348 rd1 = (insn >> 0) & 0xf;
2349 gen_op_iwmmxt_movq_M0_wRn(rd0);
2350 switch ((insn >> 20) & 0xf) {
2352 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2355 gen_op_iwmmxt_addub_M0_wRn(rd1);
2358 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2361 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2364 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2367 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2370 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2373 gen_op_iwmmxt_addul_M0_wRn(rd1);
2376 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2381 gen_op_iwmmxt_movq_wRn_M0(wrd);
2382 gen_op_iwmmxt_set_mup();
2383 gen_op_iwmmxt_set_cup();
2385 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2386 case 0x408: case 0x508: case 0x608: case 0x708:
2387 case 0x808: case 0x908: case 0xa08: case 0xb08:
2388 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2389 wrd = (insn >> 12) & 0xf;
2390 rd0 = (insn >> 16) & 0xf;
2391 rd1 = (insn >> 0) & 0xf;
2392 gen_op_iwmmxt_movq_M0_wRn(rd0);
2393 if (!(insn & (1 << 20)))
2395 switch ((insn >> 22) & 3) {
2399 if (insn & (1 << 21))
2400 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2402 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2405 if (insn & (1 << 21))
2406 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2408 gen_op_iwmmxt_packul_M0_wRn(rd1);
2411 if (insn & (1 << 21))
2412 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2414 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2417 gen_op_iwmmxt_movq_wRn_M0(wrd);
2418 gen_op_iwmmxt_set_mup();
2419 gen_op_iwmmxt_set_cup();
2421 case 0x201: case 0x203: case 0x205: case 0x207:
2422 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2423 case 0x211: case 0x213: case 0x215: case 0x217:
2424 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2425 wrd = (insn >> 5) & 0xf;
2426 rd0 = (insn >> 12) & 0xf;
2427 rd1 = (insn >> 0) & 0xf;
2428 if (rd0 == 0xf || rd1 == 0xf)
2430 gen_op_iwmmxt_movq_M0_wRn(wrd);
2431 switch ((insn >> 16) & 0xf) {
2432 case 0x0: /* TMIA */
2433 gen_movl_T0_reg(s, rd0);
2434 gen_movl_T1_reg(s, rd1);
2435 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2437 case 0x8: /* TMIAPH */
2438 gen_movl_T0_reg(s, rd0);
2439 gen_movl_T1_reg(s, rd1);
2440 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2442 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2443 gen_movl_T1_reg(s, rd0);
2444 if (insn & (1 << 16))
2445 gen_op_shrl_T1_im(16);
2446 gen_op_movl_T0_T1();
2447 gen_movl_T1_reg(s, rd1);
2448 if (insn & (1 << 17))
2449 gen_op_shrl_T1_im(16);
2450 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2455 gen_op_iwmmxt_movq_wRn_M0(wrd);
2456 gen_op_iwmmxt_set_mup();
2465 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2466 (ie. an undefined instruction). */
2467 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2469 int acc, rd0, rd1, rdhi, rdlo;
2471 if ((insn & 0x0ff00f10) == 0x0e200010) {
2472 /* Multiply with Internal Accumulate Format */
2473 rd0 = (insn >> 12) & 0xf;
2475 acc = (insn >> 5) & 7;
2480 switch ((insn >> 16) & 0xf) {
2482 gen_movl_T0_reg(s, rd0);
2483 gen_movl_T1_reg(s, rd1);
2484 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2486 case 0x8: /* MIAPH */
2487 gen_movl_T0_reg(s, rd0);
2488 gen_movl_T1_reg(s, rd1);
2489 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2491 case 0xc: /* MIABB */
2492 case 0xd: /* MIABT */
2493 case 0xe: /* MIATB */
2494 case 0xf: /* MIATT */
2495 gen_movl_T1_reg(s, rd0);
2496 if (insn & (1 << 16))
2497 gen_op_shrl_T1_im(16);
2498 gen_op_movl_T0_T1();
2499 gen_movl_T1_reg(s, rd1);
2500 if (insn & (1 << 17))
2501 gen_op_shrl_T1_im(16);
2502 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2508 gen_op_iwmmxt_movq_wRn_M0(acc);
2512 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2513 /* Internal Accumulator Access Format */
2514 rdhi = (insn >> 16) & 0xf;
2515 rdlo = (insn >> 12) & 0xf;
2521 if (insn & ARM_CP_RW_BIT) { /* MRA */
2522 gen_iwmmxt_movl_T0_T1_wRn(acc);
2523 gen_movl_reg_T0(s, rdlo);
2524 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2525 gen_op_andl_T0_T1();
2526 gen_movl_reg_T0(s, rdhi);
2528 gen_movl_T0_reg(s, rdlo);
2529 gen_movl_T1_reg(s, rdhi);
2530 gen_iwmmxt_movl_wRn_T0_T1(acc);
2538 /* Disassemble system coprocessor instruction. Return nonzero if
2539 instruction is not defined. */
2540 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2543 uint32_t rd = (insn >> 12) & 0xf;
2544 uint32_t cp = (insn >> 8) & 0xf;
2549 if (insn & ARM_CP_RW_BIT) {
2550 if (!env->cp[cp].cp_read)
2552 gen_set_pc_im(s->pc);
2554 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2555 store_reg(s, rd, tmp);
2557 if (!env->cp[cp].cp_write)
2559 gen_set_pc_im(s->pc);
2560 tmp = load_reg(s, rd);
2561 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2567 static int cp15_user_ok(uint32_t insn)
2569 int cpn = (insn >> 16) & 0xf;
2570 int cpm = insn & 0xf;
2571 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2573 if (cpn == 13 && cpm == 0) {
2575 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2579 /* ISB, DSB, DMB. */
2580 if ((cpm == 5 && op == 4)
2581 || (cpm == 10 && (op == 4 || op == 5)))
2587 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2588 instruction is not defined. */
2589 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2594 /* M profile cores use memory mapped registers instead of cp15. */
2595 if (arm_feature(env, ARM_FEATURE_M))
2598 if ((insn & (1 << 25)) == 0) {
2599 if (insn & (1 << 20)) {
2603 /* mcrr. Used for block cache operations, so implement as no-op. */
2606 if ((insn & (1 << 4)) == 0) {
2610 if (IS_USER(s) && !cp15_user_ok(insn)) {
2613 if ((insn & 0x0fff0fff) == 0x0e070f90
2614 || (insn & 0x0fff0fff) == 0x0e070f58) {
2615 /* Wait for interrupt. */
2616 gen_set_pc_im(s->pc);
2617 s->is_jmp = DISAS_WFI;
2620 rd = (insn >> 12) & 0xf;
2621 if (insn & ARM_CP_RW_BIT) {
2623 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2624 /* If the destination register is r15 then sets condition codes. */
2626 store_reg(s, rd, tmp);
2630 tmp = load_reg(s, rd);
2631 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2633 /* Normally we would always end the TB here, but Linux
2634 * arch/arm/mach-pxa/sleep.S expects two instructions following
2635 * an MMU enable to execute from cache. Imitate this behaviour. */
2636 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2637 (insn & 0x0fff0fff) != 0x0e010f10)
2643 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2644 #define VFP_SREG(insn, bigbit, smallbit) \
2645 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2646 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2647 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2648 reg = (((insn) >> (bigbit)) & 0x0f) \
2649 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2651 if (insn & (1 << (smallbit))) \
2653 reg = ((insn) >> (bigbit)) & 0x0f; \
2656 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2657 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2658 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2659 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2660 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2661 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2663 /* Move between integer and VFP cores. */
2664 static TCGv gen_vfp_mrs(void)
2666 TCGv tmp = new_tmp();
2667 tcg_gen_mov_i32(tmp, cpu_F0s);
2671 static void gen_vfp_msr(TCGv tmp)
2673 tcg_gen_mov_i32(cpu_F0s, tmp);
2678 vfp_enabled(CPUState * env)
2680 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2683 static void gen_neon_dup_u8(TCGv var, int shift)
2685 TCGv tmp = new_tmp();
2687 tcg_gen_shri_i32(var, var, shift);
2688 tcg_gen_ext8u_i32(var, var);
2689 tcg_gen_shli_i32(tmp, var, 8);
2690 tcg_gen_or_i32(var, var, tmp);
2691 tcg_gen_shli_i32(tmp, var, 16);
2692 tcg_gen_or_i32(var, var, tmp);
2696 static void gen_neon_dup_low16(TCGv var)
2698 TCGv tmp = new_tmp();
2699 tcg_gen_ext16u_i32(var, var);
2700 tcg_gen_shli_i32(tmp, var, 16);
2701 tcg_gen_or_i32(var, var, tmp);
2705 static void gen_neon_dup_high16(TCGv var)
2707 TCGv tmp = new_tmp();
2708 tcg_gen_andi_i32(var, var, 0xffff0000);
2709 tcg_gen_shri_i32(tmp, var, 16);
2710 tcg_gen_or_i32(var, var, tmp);
2714 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2715 (ie. an undefined instruction). */
2716 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2718 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2723 if (!arm_feature(env, ARM_FEATURE_VFP))
2726 if (!vfp_enabled(env)) {
2727 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2728 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2730 rn = (insn >> 16) & 0xf;
2731 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2732 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2735 dp = ((insn & 0xf00) == 0xb00);
2736 switch ((insn >> 24) & 0xf) {
2738 if (insn & (1 << 4)) {
2739 /* single register transfer */
2740 rd = (insn >> 12) & 0xf;
2745 VFP_DREG_N(rn, insn);
2748 if (insn & 0x00c00060
2749 && !arm_feature(env, ARM_FEATURE_NEON))
2752 pass = (insn >> 21) & 1;
2753 if (insn & (1 << 22)) {
2755 offset = ((insn >> 5) & 3) * 8;
2756 } else if (insn & (1 << 5)) {
2758 offset = (insn & (1 << 6)) ? 16 : 0;
2763 if (insn & ARM_CP_RW_BIT) {
2765 tmp = neon_load_reg(rn, pass);
2769 tcg_gen_shri_i32(tmp, tmp, offset);
2770 if (insn & (1 << 23))
2776 if (insn & (1 << 23)) {
2778 tcg_gen_shri_i32(tmp, tmp, 16);
2784 tcg_gen_sari_i32(tmp, tmp, 16);
2793 store_reg(s, rd, tmp);
2796 tmp = load_reg(s, rd);
2797 if (insn & (1 << 23)) {
2800 gen_neon_dup_u8(tmp, 0);
2801 } else if (size == 1) {
2802 gen_neon_dup_low16(tmp);
2804 for (n = 0; n <= pass * 2; n++) {
2806 tcg_gen_mov_i32(tmp2, tmp);
2807 neon_store_reg(rn, n, tmp2);
2809 neon_store_reg(rn, n, tmp);
2814 tmp2 = neon_load_reg(rn, pass);
2815 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2819 tmp2 = neon_load_reg(rn, pass);
2820 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2826 neon_store_reg(rn, pass, tmp);
2830 if ((insn & 0x6f) != 0x00)
2832 rn = VFP_SREG_N(insn);
2833 if (insn & ARM_CP_RW_BIT) {
2835 if (insn & (1 << 21)) {
2836 /* system register */
2841 /* VFP2 allows access to FSID from userspace.
2842 VFP3 restricts all id registers to privileged
2845 && arm_feature(env, ARM_FEATURE_VFP3))
2847 tmp = load_cpu_field(vfp.xregs[rn]);
2852 tmp = load_cpu_field(vfp.xregs[rn]);
2854 case ARM_VFP_FPINST:
2855 case ARM_VFP_FPINST2:
2856 /* Not present in VFP3. */
2858 || arm_feature(env, ARM_FEATURE_VFP3))
2860 tmp = load_cpu_field(vfp.xregs[rn]);
2864 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2865 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2868 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2874 || !arm_feature(env, ARM_FEATURE_VFP3))
2876 tmp = load_cpu_field(vfp.xregs[rn]);
2882 gen_mov_F0_vreg(0, rn);
2883 tmp = gen_vfp_mrs();
2886 /* Set the 4 flag bits in the CPSR. */
2890 store_reg(s, rd, tmp);
2894 tmp = load_reg(s, rd);
2895 if (insn & (1 << 21)) {
2897 /* system register */
2902 /* Writes are ignored. */
2905 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2912 store_cpu_field(tmp, vfp.xregs[rn]);
2915 case ARM_VFP_FPINST:
2916 case ARM_VFP_FPINST2:
2917 store_cpu_field(tmp, vfp.xregs[rn]);
2924 gen_mov_vreg_F0(0, rn);
2929 /* data processing */
2930 /* The opcode is in bits 23, 21, 20 and 6. */
2931 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2935 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2937 /* rn is register number */
2938 VFP_DREG_N(rn, insn);
2941 if (op == 15 && (rn == 15 || rn > 17)) {
2942 /* Integer or single precision destination. */
2943 rd = VFP_SREG_D(insn);
2945 VFP_DREG_D(rd, insn);
2948 if (op == 15 && (rn == 16 || rn == 17)) {
2949 /* Integer source. */
2950 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2952 VFP_DREG_M(rm, insn);
2955 rn = VFP_SREG_N(insn);
2956 if (op == 15 && rn == 15) {
2957 /* Double precision destination. */
2958 VFP_DREG_D(rd, insn);
2960 rd = VFP_SREG_D(insn);
2962 rm = VFP_SREG_M(insn);
2965 veclen = env->vfp.vec_len;
2966 if (op == 15 && rn > 3)
2969 /* Shut up compiler warnings. */
2980 /* Figure out what type of vector operation this is. */
2981 if ((rd & bank_mask) == 0) {
2986 delta_d = (env->vfp.vec_stride >> 1) + 1;
2988 delta_d = env->vfp.vec_stride + 1;
2990 if ((rm & bank_mask) == 0) {
2991 /* mixed scalar/vector */
3000 /* Load the initial operands. */
3005 /* Integer source */
3006 gen_mov_F0_vreg(0, rm);
3011 gen_mov_F0_vreg(dp, rd);
3012 gen_mov_F1_vreg(dp, rm);
3016 /* Compare with zero */
3017 gen_mov_F0_vreg(dp, rd);
3028 /* Source and destination the same. */
3029 gen_mov_F0_vreg(dp, rd);
3032 /* One source operand. */
3033 gen_mov_F0_vreg(dp, rm);
3037 /* Two source operands. */
3038 gen_mov_F0_vreg(dp, rn);
3039 gen_mov_F1_vreg(dp, rm);
3043 /* Perform the calculation. */
3045 case 0: /* mac: fd + (fn * fm) */
3047 gen_mov_F1_vreg(dp, rd);
3050 case 1: /* nmac: fd - (fn * fm) */
3053 gen_mov_F1_vreg(dp, rd);
3056 case 2: /* msc: -fd + (fn * fm) */
3058 gen_mov_F1_vreg(dp, rd);
3061 case 3: /* nmsc: -fd - (fn * fm) */
3064 gen_mov_F1_vreg(dp, rd);
3067 case 4: /* mul: fn * fm */
3070 case 5: /* nmul: -(fn * fm) */
3074 case 6: /* add: fn + fm */
3077 case 7: /* sub: fn - fm */
3080 case 8: /* div: fn / fm */
3083 case 14: /* fconst */
3084 if (!arm_feature(env, ARM_FEATURE_VFP3))
3087 n = (insn << 12) & 0x80000000;
3088 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3095 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3102 tcg_gen_movi_i32(cpu_F0s, n);
3105 case 15: /* extension space */
3128 case 11: /* cmpez */
3132 case 15: /* single<->double conversion */
3134 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3136 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3138 case 16: /* fuito */
3141 case 17: /* fsito */
3144 case 20: /* fshto */
3145 if (!arm_feature(env, ARM_FEATURE_VFP3))
3147 gen_vfp_shto(dp, 16 - rm);
3149 case 21: /* fslto */
3150 if (!arm_feature(env, ARM_FEATURE_VFP3))
3152 gen_vfp_slto(dp, 32 - rm);
3154 case 22: /* fuhto */
3155 if (!arm_feature(env, ARM_FEATURE_VFP3))
3157 gen_vfp_uhto(dp, 16 - rm);
3159 case 23: /* fulto */
3160 if (!arm_feature(env, ARM_FEATURE_VFP3))
3162 gen_vfp_ulto(dp, 32 - rm);
3164 case 24: /* ftoui */
3167 case 25: /* ftouiz */
3170 case 26: /* ftosi */
3173 case 27: /* ftosiz */
3176 case 28: /* ftosh */
3177 if (!arm_feature(env, ARM_FEATURE_VFP3))
3179 gen_vfp_tosh(dp, 16 - rm);
3181 case 29: /* ftosl */
3182 if (!arm_feature(env, ARM_FEATURE_VFP3))
3184 gen_vfp_tosl(dp, 32 - rm);
3186 case 30: /* ftouh */
3187 if (!arm_feature(env, ARM_FEATURE_VFP3))
3189 gen_vfp_touh(dp, 16 - rm);
3191 case 31: /* ftoul */
3192 if (!arm_feature(env, ARM_FEATURE_VFP3))
3194 gen_vfp_toul(dp, 32 - rm);
3196 default: /* undefined */
3197 printf ("rn:%d\n", rn);
3201 default: /* undefined */
3202 printf ("op:%d\n", op);
3206 /* Write back the result. */
3207 if (op == 15 && (rn >= 8 && rn <= 11))
3208 ; /* Comparison, do nothing. */
3209 else if (op == 15 && rn > 17)
3210 /* Integer result. */
3211 gen_mov_vreg_F0(0, rd);
3212 else if (op == 15 && rn == 15)
3214 gen_mov_vreg_F0(!dp, rd);
3216 gen_mov_vreg_F0(dp, rd);
3218 /* break out of the loop if we have finished */
3222 if (op == 15 && delta_m == 0) {
3223 /* single source one-many */
3225 rd = ((rd + delta_d) & (bank_mask - 1))
3227 gen_mov_vreg_F0(dp, rd);
3231 /* Setup the next operands. */
3233 rd = ((rd + delta_d) & (bank_mask - 1))
3237 /* One source operand. */
3238 rm = ((rm + delta_m) & (bank_mask - 1))
3240 gen_mov_F0_vreg(dp, rm);
3242 /* Two source operands. */
3243 rn = ((rn + delta_d) & (bank_mask - 1))
3245 gen_mov_F0_vreg(dp, rn);
3247 rm = ((rm + delta_m) & (bank_mask - 1))
3249 gen_mov_F1_vreg(dp, rm);
3257 if (dp && (insn & 0x03e00000) == 0x00400000) {
3258 /* two-register transfer */
3259 rn = (insn >> 16) & 0xf;
3260 rd = (insn >> 12) & 0xf;
3262 VFP_DREG_M(rm, insn);
3264 rm = VFP_SREG_M(insn);
3267 if (insn & ARM_CP_RW_BIT) {
3270 gen_mov_F0_vreg(0, rm * 2);
3271 tmp = gen_vfp_mrs();
3272 store_reg(s, rd, tmp);
3273 gen_mov_F0_vreg(0, rm * 2 + 1);
3274 tmp = gen_vfp_mrs();
3275 store_reg(s, rn, tmp);
3277 gen_mov_F0_vreg(0, rm);
3278 tmp = gen_vfp_mrs();
3279 store_reg(s, rn, tmp);
3280 gen_mov_F0_vreg(0, rm + 1);
3281 tmp = gen_vfp_mrs();
3282 store_reg(s, rd, tmp);
3287 tmp = load_reg(s, rd);
3289 gen_mov_vreg_F0(0, rm * 2);
3290 tmp = load_reg(s, rn);
3292 gen_mov_vreg_F0(0, rm * 2 + 1);
3294 tmp = load_reg(s, rn);
3296 gen_mov_vreg_F0(0, rm);
3297 tmp = load_reg(s, rd);
3299 gen_mov_vreg_F0(0, rm + 1);
3304 rn = (insn >> 16) & 0xf;
3306 VFP_DREG_D(rd, insn);
3308 rd = VFP_SREG_D(insn);
3309 if (s->thumb && rn == 15) {
3310 gen_op_movl_T1_im(s->pc & ~2);
3312 gen_movl_T1_reg(s, rn);
3314 if ((insn & 0x01200000) == 0x01000000) {
3315 /* Single load/store */
3316 offset = (insn & 0xff) << 2;
3317 if ((insn & (1 << 23)) == 0)
3319 gen_op_addl_T1_im(offset);
3320 if (insn & (1 << 20)) {
3322 gen_mov_vreg_F0(dp, rd);
3324 gen_mov_F0_vreg(dp, rd);
3328 /* load/store multiple */
3330 n = (insn >> 1) & 0x7f;
3334 if (insn & (1 << 24)) /* pre-decrement */
3335 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3341 for (i = 0; i < n; i++) {
3342 if (insn & ARM_CP_RW_BIT) {
3345 gen_mov_vreg_F0(dp, rd + i);
3348 gen_mov_F0_vreg(dp, rd + i);
3351 gen_op_addl_T1_im(offset);
3353 if (insn & (1 << 21)) {
3355 if (insn & (1 << 24))
3356 offset = -offset * n;
3357 else if (dp && (insn & 1))
3363 gen_op_addl_T1_im(offset);
3364 gen_movl_reg_T1(s, rn);
3370 /* Should never happen. */
3376 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3378 TranslationBlock *tb;
3381 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3383 gen_set_pc_im(dest);
3384 tcg_gen_exit_tb((long)tb + n);
3386 gen_set_pc_im(dest);
3391 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3393 if (unlikely(s->singlestep_enabled)) {
3394 /* An indirect jump so that we still trigger the debug exception. */
3399 gen_goto_tb(s, 0, dest);
3400 s->is_jmp = DISAS_TB_JUMP;
3404 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3407 tcg_gen_sari_i32(t0, t0, 16);
3411 tcg_gen_sari_i32(t1, t1, 16);
3414 tcg_gen_mul_i32(t0, t0, t1);
3417 /* Return the mask of PSR bits set by a MSR instruction. */
3418 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3422 if (flags & (1 << 0))
3424 if (flags & (1 << 1))
3426 if (flags & (1 << 2))
3428 if (flags & (1 << 3))
3431 /* Mask out undefined bits. */
3432 mask &= ~CPSR_RESERVED;
3433 if (!arm_feature(env, ARM_FEATURE_V6))
3434 mask &= ~(CPSR_E | CPSR_GE);
3435 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3437 /* Mask out execution state bits. */
3440 /* Mask out privileged bits. */
3446 /* Returns nonzero if access to the PSR is not permitted. */
3447 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3451 /* ??? This is also undefined in system mode. */
3455 tmp = load_cpu_field(spsr);
3456 tcg_gen_andi_i32(tmp, tmp, ~mask);
3457 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3458 tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3459 store_cpu_field(tmp, spsr);
3461 gen_set_cpsr(cpu_T[0], mask);
3467 /* Generate an old-style exception return. Marks pc as dead. */
3468 static void gen_exception_return(DisasContext *s, TCGv pc)
3471 store_reg(s, 15, pc);
3472 tmp = load_cpu_field(spsr);
3473 gen_set_cpsr(tmp, 0xffffffff);
3475 s->is_jmp = DISAS_UPDATE;
3478 /* Generate a v6 exception return. Marks both values as dead. */
3479 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3481 gen_set_cpsr(cpsr, 0xffffffff);
3483 store_reg(s, 15, pc);
3484 s->is_jmp = DISAS_UPDATE;
3488 gen_set_condexec (DisasContext *s)
3490 if (s->condexec_mask) {
3491 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3492 TCGv tmp = new_tmp();
3493 tcg_gen_movi_i32(tmp, val);
3494 store_cpu_field(tmp, condexec_bits);
3498 static void gen_nop_hint(DisasContext *s, int val)
3502 gen_set_pc_im(s->pc);
3503 s->is_jmp = DISAS_WFI;
3507 /* TODO: Implement SEV and WFE. May help SMP performance. */
3513 /* These macros help make the code more readable when migrating from the
3514 old dyngen helpers. They should probably be removed when
3515 T0/T1 are removed. */
3516 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3517 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3519 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3521 static inline int gen_neon_add(int size)
3524 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3525 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3526 case 2: gen_op_addl_T0_T1(); break;
3532 static inline void gen_neon_rsb(int size)
3535 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3536 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3537 case 2: gen_op_rsbl_T0_T1(); break;
3542 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3543 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3544 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3545 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3546 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3548 /* FIXME: This is wrong. They set the wrong overflow bit. */
3549 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3550 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3551 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3552 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3554 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3555 switch ((size << 1) | u) { \
3557 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3560 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3563 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3566 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3569 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3572 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3574 default: return 1; \
3577 #define GEN_NEON_INTEGER_OP(name) do { \
3578 switch ((size << 1) | u) { \
3580 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3583 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3586 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3589 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3592 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3595 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3597 default: return 1; \
3601 gen_neon_movl_scratch_T0(int scratch)
3605 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3606 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3610 gen_neon_movl_scratch_T1(int scratch)
3614 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3615 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3619 gen_neon_movl_T0_scratch(int scratch)
3623 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3624 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3628 gen_neon_movl_T1_scratch(int scratch)
3632 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3633 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3636 static inline void gen_neon_get_scalar(int size, int reg)
3639 NEON_GET_REG(T0, reg >> 1, reg & 1);
3641 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3643 gen_neon_dup_low16(cpu_T[0]);
3645 gen_neon_dup_high16(cpu_T[0]);
3649 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3653 for (n = 0; n < q + 1; n += 2) {
3654 NEON_GET_REG(T0, reg, n);
3655 NEON_GET_REG(T0, reg, n + n);
3657 case 0: gen_helper_neon_unzip_u8(); break;
3658 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3659 case 2: /* no-op */; break;
3662 gen_neon_movl_scratch_T0(tmp + n);
3663 gen_neon_movl_scratch_T1(tmp + n + 1);
3671 } neon_ls_element_type[11] = {
3685 /* Translate a NEON load/store element instruction. Return nonzero if the
3686 instruction is invalid. */
3687 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3703 if (!vfp_enabled(env))
3705 VFP_DREG_D(rd, insn);
3706 rn = (insn >> 16) & 0xf;
3708 load = (insn & (1 << 21)) != 0;
3709 if ((insn & (1 << 23)) == 0) {
3710 /* Load store all elements. */
3711 op = (insn >> 8) & 0xf;
3712 size = (insn >> 6) & 3;
3713 if (op > 10 || size == 3)
3715 nregs = neon_ls_element_type[op].nregs;
3716 interleave = neon_ls_element_type[op].interleave;
3717 gen_movl_T1_reg(s, rn);
3718 stride = (1 << size) * interleave;
3719 for (reg = 0; reg < nregs; reg++) {
3720 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3721 gen_movl_T1_reg(s, rn);
3722 gen_op_addl_T1_im((1 << size) * reg);
3723 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3724 gen_movl_T1_reg(s, rn);
3725 gen_op_addl_T1_im(1 << size);
3727 for (pass = 0; pass < 2; pass++) {
3730 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3731 neon_store_reg(rd, pass, tmp);
3733 tmp = neon_load_reg(rd, pass);
3734 gen_st32(tmp, cpu_T[1], IS_USER(s));
3736 gen_op_addl_T1_im(stride);
3737 } else if (size == 1) {
3739 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3740 gen_op_addl_T1_im(stride);
3741 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3742 gen_op_addl_T1_im(stride);
3743 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3745 neon_store_reg(rd, pass, tmp);
3747 tmp = neon_load_reg(rd, pass);
3749 tcg_gen_shri_i32(tmp2, tmp, 16);
3750 gen_st16(tmp, cpu_T[1], IS_USER(s));
3751 gen_op_addl_T1_im(stride);
3752 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3753 gen_op_addl_T1_im(stride);
3755 } else /* size == 0 */ {
3758 for (n = 0; n < 4; n++) {
3759 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3760 gen_op_addl_T1_im(stride);
3764 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3768 neon_store_reg(rd, pass, tmp2);
3770 tmp2 = neon_load_reg(rd, pass);
3771 for (n = 0; n < 4; n++) {
3774 tcg_gen_mov_i32(tmp, tmp2);
3776 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3778 gen_st8(tmp, cpu_T[1], IS_USER(s));
3779 gen_op_addl_T1_im(stride);
3785 rd += neon_ls_element_type[op].spacing;
3789 size = (insn >> 10) & 3;
3791 /* Load single element to all lanes. */
3794 size = (insn >> 6) & 3;
3795 nregs = ((insn >> 8) & 3) + 1;
3796 stride = (insn & (1 << 5)) ? 2 : 1;
3797 gen_movl_T1_reg(s, rn);
3798 for (reg = 0; reg < nregs; reg++) {
3801 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3802 gen_neon_dup_u8(tmp, 0);
3805 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3806 gen_neon_dup_low16(tmp);
3809 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3813 default: /* Avoid compiler warnings. */
3816 gen_op_addl_T1_im(1 << size);
3818 tcg_gen_mov_i32(tmp2, tmp);
3819 neon_store_reg(rd, 0, tmp2);
3820 neon_store_reg(rd, 1, tmp);
3823 stride = (1 << size) * nregs;
3825 /* Single element. */
3826 pass = (insn >> 7) & 1;
3829 shift = ((insn >> 5) & 3) * 8;
3833 shift = ((insn >> 6) & 1) * 16;
3834 stride = (insn & (1 << 5)) ? 2 : 1;
3838 stride = (insn & (1 << 6)) ? 2 : 1;
3843 nregs = ((insn >> 8) & 3) + 1;
3844 gen_movl_T1_reg(s, rn);
3845 for (reg = 0; reg < nregs; reg++) {
3849 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3852 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3855 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3857 default: /* Avoid compiler warnings. */
3861 tmp2 = neon_load_reg(rd, pass);
3862 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3865 neon_store_reg(rd, pass, tmp);
3866 } else { /* Store */
3867 tmp = neon_load_reg(rd, pass);
3869 tcg_gen_shri_i32(tmp, tmp, shift);
3872 gen_st8(tmp, cpu_T[1], IS_USER(s));
3875 gen_st16(tmp, cpu_T[1], IS_USER(s));
3878 gen_st32(tmp, cpu_T[1], IS_USER(s));
3883 gen_op_addl_T1_im(1 << size);
3885 stride = nregs * (1 << size);
3891 base = load_reg(s, rn);
3893 tcg_gen_addi_i32(base, base, stride);
3896 index = load_reg(s, rm);
3897 tcg_gen_add_i32(base, base, index);
3900 store_reg(s, rn, base);
3905 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3906 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3908 tcg_gen_and_i32(t, t, c);
3909 tcg_gen_bic_i32(f, f, c);
3910 tcg_gen_or_i32(dest, t, f);
3913 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3916 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3917 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3918 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3923 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3926 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3927 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3928 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3933 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3936 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3937 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3938 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3943 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3949 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3950 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3955 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3956 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3963 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3964 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3969 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3970 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3977 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3981 case 0: gen_helper_neon_widen_u8(dest, src); break;
3982 case 1: gen_helper_neon_widen_u16(dest, src); break;
3983 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3988 case 0: gen_helper_neon_widen_s8(dest, src); break;
3989 case 1: gen_helper_neon_widen_s16(dest, src); break;
3990 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3997 static inline void gen_neon_addl(int size)
4000 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4001 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4002 case 2: tcg_gen_add_i64(CPU_V001); break;
4007 static inline void gen_neon_subl(int size)
4010 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4011 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4012 case 2: tcg_gen_sub_i64(CPU_V001); break;
4017 static inline void gen_neon_negl(TCGv_i64 var, int size)
4020 case 0: gen_helper_neon_negl_u16(var, var); break;
4021 case 1: gen_helper_neon_negl_u32(var, var); break;
4022 case 2: gen_helper_neon_negl_u64(var, var); break;
4027 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4030 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4031 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4036 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4040 switch ((size << 1) | u) {
4041 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4042 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4043 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4044 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4046 tmp = gen_muls_i64_i32(a, b);
4047 tcg_gen_mov_i64(dest, tmp);
4050 tmp = gen_mulu_i64_i32(a, b);
4051 tcg_gen_mov_i64(dest, tmp);
4061 /* Translate a NEON data processing instruction. Return nonzero if the
4062 instruction is invalid.
4063 We process data in a mixture of 32-bit and 64-bit chunks.
4064 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4066 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4084 if (!vfp_enabled(env))
4086 q = (insn & (1 << 6)) != 0;
4087 u = (insn >> 24) & 1;
4088 VFP_DREG_D(rd, insn);
4089 VFP_DREG_N(rn, insn);
4090 VFP_DREG_M(rm, insn);
4091 size = (insn >> 20) & 3;
4092 if ((insn & (1 << 23)) == 0) {
4093 /* Three register same length. */
4094 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4095 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4096 || op == 10 || op == 11 || op == 16)) {
4097 /* 64-bit element instructions. */
4098 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4099 neon_load_reg64(cpu_V0, rn + pass);
4100 neon_load_reg64(cpu_V1, rm + pass);
4104 gen_helper_neon_add_saturate_u64(CPU_V001);
4106 gen_helper_neon_add_saturate_s64(CPU_V001);
4111 gen_helper_neon_sub_saturate_u64(CPU_V001);
4113 gen_helper_neon_sub_saturate_s64(CPU_V001);
4118 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4120 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4125 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4128 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4132 case 10: /* VRSHL */
4134 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4136 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4139 case 11: /* VQRSHL */
4141 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4144 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4150 tcg_gen_sub_i64(CPU_V001);
4152 tcg_gen_add_i64(CPU_V001);
4158 neon_store_reg64(cpu_V0, rd + pass);
4165 case 10: /* VRSHL */
4166 case 11: /* VQRSHL */
4169 /* Shift instruction operands are reversed. */
4176 case 20: /* VPMAX */
4177 case 21: /* VPMIN */
4178 case 23: /* VPADD */
4181 case 26: /* VPADD (float) */
4182 pairwise = (u && size < 2);
4184 case 30: /* VPMIN/VPMAX (float) */
4191 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4200 NEON_GET_REG(T0, rn, n);
4201 NEON_GET_REG(T1, rn, n + 1);
4203 NEON_GET_REG(T0, rm, n);
4204 NEON_GET_REG(T1, rm, n + 1);
4208 NEON_GET_REG(T0, rn, pass);
4209 NEON_GET_REG(T1, rm, pass);
4213 GEN_NEON_INTEGER_OP(hadd);
4216 GEN_NEON_INTEGER_OP_ENV(qadd);
4218 case 2: /* VRHADD */
4219 GEN_NEON_INTEGER_OP(rhadd);
4221 case 3: /* Logic ops. */
4222 switch ((u << 2) | size) {
4224 gen_op_andl_T0_T1();
4227 gen_op_bicl_T0_T1();
4237 gen_op_xorl_T0_T1();
4240 tmp = neon_load_reg(rd, pass);
4241 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4245 tmp = neon_load_reg(rd, pass);
4246 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4250 tmp = neon_load_reg(rd, pass);
4251 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4257 GEN_NEON_INTEGER_OP(hsub);
4260 GEN_NEON_INTEGER_OP_ENV(qsub);
4263 GEN_NEON_INTEGER_OP(cgt);
4266 GEN_NEON_INTEGER_OP(cge);
4269 GEN_NEON_INTEGER_OP(shl);
4272 GEN_NEON_INTEGER_OP_ENV(qshl);
4274 case 10: /* VRSHL */
4275 GEN_NEON_INTEGER_OP(rshl);
4277 case 11: /* VQRSHL */
4278 GEN_NEON_INTEGER_OP_ENV(qrshl);
4281 GEN_NEON_INTEGER_OP(max);
4284 GEN_NEON_INTEGER_OP(min);
4287 GEN_NEON_INTEGER_OP(abd);
4290 GEN_NEON_INTEGER_OP(abd);
4291 NEON_GET_REG(T1, rd, pass);
4295 if (!u) { /* VADD */
4296 if (gen_neon_add(size))
4300 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4301 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4302 case 2: gen_op_subl_T0_T1(); break;
4308 if (!u) { /* VTST */
4310 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4311 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4312 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4317 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4318 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4319 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4324 case 18: /* Multiply. */
4326 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4327 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4328 case 2: gen_op_mul_T0_T1(); break;
4331 NEON_GET_REG(T1, rd, pass);
4339 if (u) { /* polynomial */
4340 gen_helper_neon_mul_p8(CPU_T001);
4341 } else { /* Integer */
4343 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4344 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4345 case 2: gen_op_mul_T0_T1(); break;
4350 case 20: /* VPMAX */
4351 GEN_NEON_INTEGER_OP(pmax);
4353 case 21: /* VPMIN */
4354 GEN_NEON_INTEGER_OP(pmin);
4356 case 22: /* Hultiply high. */
4357 if (!u) { /* VQDMULH */
4359 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4360 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4363 } else { /* VQRDHMUL */
4365 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4366 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4371 case 23: /* VPADD */
4375 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4376 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4377 case 2: gen_op_addl_T0_T1(); break;
4381 case 26: /* Floating point arithnetic. */
4382 switch ((u << 2) | size) {
4384 gen_helper_neon_add_f32(CPU_T001);
4387 gen_helper_neon_sub_f32(CPU_T001);
4390 gen_helper_neon_add_f32(CPU_T001);
4393 gen_helper_neon_abd_f32(CPU_T001);
4399 case 27: /* Float multiply. */
4400 gen_helper_neon_mul_f32(CPU_T001);
4402 NEON_GET_REG(T1, rd, pass);
4404 gen_helper_neon_add_f32(CPU_T001);
4406 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4410 case 28: /* Float compare. */
4412 gen_helper_neon_ceq_f32(CPU_T001);
4415 gen_helper_neon_cge_f32(CPU_T001);
4417 gen_helper_neon_cgt_f32(CPU_T001);
4420 case 29: /* Float compare absolute. */
4424 gen_helper_neon_acge_f32(CPU_T001);
4426 gen_helper_neon_acgt_f32(CPU_T001);
4428 case 30: /* Float min/max. */
4430 gen_helper_neon_max_f32(CPU_T001);
4432 gen_helper_neon_min_f32(CPU_T001);
4436 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4438 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4443 /* Save the result. For elementwise operations we can put it
4444 straight into the destination register. For pairwise operations
4445 we have to be careful to avoid clobbering the source operands. */
4446 if (pairwise && rd == rm) {
4447 gen_neon_movl_scratch_T0(pass);
4449 NEON_SET_REG(T0, rd, pass);
4453 if (pairwise && rd == rm) {
4454 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4455 gen_neon_movl_T0_scratch(pass);
4456 NEON_SET_REG(T0, rd, pass);
4459 /* End of 3 register same size operations. */
4460 } else if (insn & (1 << 4)) {
4461 if ((insn & 0x00380080) != 0) {
4462 /* Two registers and shift. */
4463 op = (insn >> 8) & 0xf;
4464 if (insn & (1 << 7)) {
4469 while ((insn & (1 << (size + 19))) == 0)
4472 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4473 /* To avoid excessive dumplication of ops we implement shift
4474 by immediate using the variable shift operations. */
4476 /* Shift by immediate:
4477 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4478 /* Right shifts are encoded as N - shift, where N is the
4479 element size in bits. */
4481 shift = shift - (1 << (size + 3));
4489 imm = (uint8_t) shift;
4494 imm = (uint16_t) shift;
4505 for (pass = 0; pass < count; pass++) {
4507 neon_load_reg64(cpu_V0, rm + pass);
4508 tcg_gen_movi_i64(cpu_V1, imm);
4513 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4515 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4520 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4522 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4527 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4529 case 5: /* VSHL, VSLI */
4530 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4534 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4536 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4538 case 7: /* VQSHLU */
4539 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4542 if (op == 1 || op == 3) {
4544 neon_load_reg64(cpu_V0, rd + pass);
4545 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4546 } else if (op == 4 || (op == 5 && u)) {
4548 cpu_abort(env, "VS[LR]I.64 not implemented");
4550 neon_store_reg64(cpu_V0, rd + pass);
4551 } else { /* size < 3 */
4552 /* Operands in T0 and T1. */
4553 gen_op_movl_T1_im(imm);
4554 NEON_GET_REG(T0, rm, pass);
4558 GEN_NEON_INTEGER_OP(shl);
4562 GEN_NEON_INTEGER_OP(rshl);
4567 GEN_NEON_INTEGER_OP(shl);
4569 case 5: /* VSHL, VSLI */
4571 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4572 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4573 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4578 GEN_NEON_INTEGER_OP_ENV(qshl);
4580 case 7: /* VQSHLU */
4582 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4583 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4584 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4590 if (op == 1 || op == 3) {
4592 NEON_GET_REG(T1, rd, pass);
4594 } else if (op == 4 || (op == 5 && u)) {
4599 imm = 0xff >> -shift;
4601 imm = (uint8_t)(0xff << shift);
4607 imm = 0xffff >> -shift;
4609 imm = (uint16_t)(0xffff << shift);
4614 imm = 0xffffffffu >> -shift;
4616 imm = 0xffffffffu << shift;
4621 tmp = neon_load_reg(rd, pass);
4622 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4623 tcg_gen_andi_i32(tmp, tmp, ~imm);
4624 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4626 NEON_SET_REG(T0, rd, pass);
4629 } else if (op < 10) {
4630 /* Shift by immediate and narrow:
4631 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4632 shift = shift - (1 << (size + 3));
4636 imm = (uint16_t)shift;
4638 tmp2 = tcg_const_i32(imm);
4639 TCGV_UNUSED_I64(tmp64);
4642 imm = (uint32_t)shift;
4643 tmp2 = tcg_const_i32(imm);
4644 TCGV_UNUSED_I64(tmp64);
4647 tmp64 = tcg_const_i64(shift);
4654 for (pass = 0; pass < 2; pass++) {
4656 neon_load_reg64(cpu_V0, rm + pass);
4659 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4661 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4664 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4666 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4669 tmp = neon_load_reg(rm + pass, 0);
4670 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4671 tmp3 = neon_load_reg(rm + pass, 1);
4672 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4673 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4678 if (op == 8 && !u) {
4679 gen_neon_narrow(size - 1, tmp, cpu_V0);
4682 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4684 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4689 neon_store_reg(rd, 0, tmp2);
4690 neon_store_reg(rd, 1, tmp);
4693 } else if (op == 10) {
4697 tmp = neon_load_reg(rm, 0);
4698 tmp2 = neon_load_reg(rm, 1);
4699 for (pass = 0; pass < 2; pass++) {
4703 gen_neon_widen(cpu_V0, tmp, size, u);
4706 /* The shift is less than the width of the source
4707 type, so we can just shift the whole register. */
4708 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4709 if (size < 2 || !u) {
4712 imm = (0xffu >> (8 - shift));
4715 imm = 0xffff >> (16 - shift);
4717 imm64 = imm | (((uint64_t)imm) << 32);
4718 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4721 neon_store_reg64(cpu_V0, rd + pass);
4723 } else if (op == 15 || op == 16) {
4724 /* VCVT fixed-point. */
4725 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4726 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4729 gen_vfp_ulto(0, shift);
4731 gen_vfp_slto(0, shift);
4734 gen_vfp_toul(0, shift);
4736 gen_vfp_tosl(0, shift);
4738 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4743 } else { /* (insn & 0x00380080) == 0 */
4746 op = (insn >> 8) & 0xf;
4747 /* One register and immediate. */
4748 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4749 invert = (insn & (1 << 5)) != 0;
4767 imm = (imm << 8) | (imm << 24);
4770 imm = (imm < 8) | 0xff;
4773 imm = (imm << 16) | 0xffff;
4776 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4781 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4782 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4788 if (op != 14 || !invert)
4789 gen_op_movl_T1_im(imm);
4791 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4792 if (op & 1 && op < 12) {
4793 tmp = neon_load_reg(rd, pass);
4795 /* The immediate value has already been inverted, so
4797 tcg_gen_andi_i32(tmp, tmp, imm);
4799 tcg_gen_ori_i32(tmp, tmp, imm);
4804 if (op == 14 && invert) {
4807 for (n = 0; n < 4; n++) {
4808 if (imm & (1 << (n + (pass & 1) * 4)))
4809 val |= 0xff << (n * 8);
4811 tcg_gen_movi_i32(tmp, val);
4813 tcg_gen_movi_i32(tmp, imm);
4816 neon_store_reg(rd, pass, tmp);
4819 } else { /* (insn & 0x00800010 == 0x00800000) */
4821 op = (insn >> 8) & 0xf;
4822 if ((insn & (1 << 6)) == 0) {
4823 /* Three registers of different lengths. */
4827 /* prewiden, src1_wide, src2_wide */
4828 static const int neon_3reg_wide[16][3] = {
4829 {1, 0, 0}, /* VADDL */
4830 {1, 1, 0}, /* VADDW */
4831 {1, 0, 0}, /* VSUBL */
4832 {1, 1, 0}, /* VSUBW */
4833 {0, 1, 1}, /* VADDHN */
4834 {0, 0, 0}, /* VABAL */
4835 {0, 1, 1}, /* VSUBHN */
4836 {0, 0, 0}, /* VABDL */
4837 {0, 0, 0}, /* VMLAL */
4838 {0, 0, 0}, /* VQDMLAL */
4839 {0, 0, 0}, /* VMLSL */
4840 {0, 0, 0}, /* VQDMLSL */
4841 {0, 0, 0}, /* Integer VMULL */
4842 {0, 0, 0}, /* VQDMULL */
4843 {0, 0, 0} /* Polynomial VMULL */
4846 prewiden = neon_3reg_wide[op][0];
4847 src1_wide = neon_3reg_wide[op][1];
4848 src2_wide = neon_3reg_wide[op][2];
4850 if (size == 0 && (op == 9 || op == 11 || op == 13))
4853 /* Avoid overlapping operands. Wide source operands are
4854 always aligned so will never overlap with wide
4855 destinations in problematic ways. */
4856 if (rd == rm && !src2_wide) {
4857 NEON_GET_REG(T0, rm, 1);
4858 gen_neon_movl_scratch_T0(2);
4859 } else if (rd == rn && !src1_wide) {
4860 NEON_GET_REG(T0, rn, 1);
4861 gen_neon_movl_scratch_T0(2);
4864 for (pass = 0; pass < 2; pass++) {
4866 neon_load_reg64(cpu_V0, rn + pass);
4869 if (pass == 1 && rd == rn) {
4870 gen_neon_movl_T0_scratch(2);
4872 tcg_gen_mov_i32(tmp, cpu_T[0]);
4874 tmp = neon_load_reg(rn, pass);
4877 gen_neon_widen(cpu_V0, tmp, size, u);
4881 neon_load_reg64(cpu_V1, rm + pass);
4884 if (pass == 1 && rd == rm) {
4885 gen_neon_movl_T0_scratch(2);
4887 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4889 tmp2 = neon_load_reg(rm, pass);
4892 gen_neon_widen(cpu_V1, tmp2, size, u);
4896 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4897 gen_neon_addl(size);
4899 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4900 gen_neon_subl(size);
4902 case 5: case 7: /* VABAL, VABDL */
4903 switch ((size << 1) | u) {
4905 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4908 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4911 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4914 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4917 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4920 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4927 case 8: case 9: case 10: case 11: case 12: case 13:
4928 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4929 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4931 case 14: /* Polynomial VMULL */
4932 cpu_abort(env, "Polynomial VMULL not implemented");
4934 default: /* 15 is RESERVED. */
4937 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4939 if (op == 10 || op == 11) {
4940 gen_neon_negl(cpu_V0, size);
4944 neon_load_reg64(cpu_V1, rd + pass);
4948 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4949 gen_neon_addl(size);
4951 case 9: case 11: /* VQDMLAL, VQDMLSL */
4952 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4953 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4956 case 13: /* VQDMULL */
4957 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4962 neon_store_reg64(cpu_V0, rd + pass);
4963 } else if (op == 4 || op == 6) {
4964 /* Narrowing operation. */
4969 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4972 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4975 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4976 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4983 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4986 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4989 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4990 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4991 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4999 neon_store_reg(rd, 0, tmp3);
5000 neon_store_reg(rd, 1, tmp);
5003 /* Write back the result. */
5004 neon_store_reg64(cpu_V0, rd + pass);
5008 /* Two registers and a scalar. */
5010 case 0: /* Integer VMLA scalar */
5011 case 1: /* Float VMLA scalar */
5012 case 4: /* Integer VMLS scalar */
5013 case 5: /* Floating point VMLS scalar */
5014 case 8: /* Integer VMUL scalar */
5015 case 9: /* Floating point VMUL scalar */
5016 case 12: /* VQDMULH scalar */
5017 case 13: /* VQRDMULH scalar */
5018 gen_neon_get_scalar(size, rm);
5019 gen_neon_movl_scratch_T0(0);
5020 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5022 gen_neon_movl_T0_scratch(0);
5023 NEON_GET_REG(T1, rn, pass);
5026 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5028 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5030 } else if (op == 13) {
5032 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5034 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5036 } else if (op & 1) {
5037 gen_helper_neon_mul_f32(CPU_T001);
5040 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5041 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5042 case 2: gen_op_mul_T0_T1(); break;
5048 NEON_GET_REG(T1, rd, pass);
5054 gen_helper_neon_add_f32(CPU_T001);
5060 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5066 NEON_SET_REG(T0, rd, pass);
5069 case 2: /* VMLAL sclar */
5070 case 3: /* VQDMLAL scalar */
5071 case 6: /* VMLSL scalar */
5072 case 7: /* VQDMLSL scalar */
5073 case 10: /* VMULL scalar */
5074 case 11: /* VQDMULL scalar */
5075 if (size == 0 && (op == 3 || op == 7 || op == 11))
5078 gen_neon_get_scalar(size, rm);
5079 NEON_GET_REG(T1, rn, 1);
5081 for (pass = 0; pass < 2; pass++) {
5083 tmp = neon_load_reg(rn, 0);
5086 tcg_gen_mov_i32(tmp, cpu_T[1]);
5089 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5090 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5091 if (op == 6 || op == 7) {
5092 gen_neon_negl(cpu_V0, size);
5095 neon_load_reg64(cpu_V1, rd + pass);
5099 gen_neon_addl(size);
5102 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5103 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5109 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5114 neon_store_reg64(cpu_V0, rd + pass);
5117 default: /* 14 and 15 are RESERVED */
5121 } else { /* size == 3 */
5124 imm = (insn >> 8) & 0xf;
5131 neon_load_reg64(cpu_V0, rn);
5133 neon_load_reg64(cpu_V1, rn + 1);
5135 } else if (imm == 8) {
5136 neon_load_reg64(cpu_V0, rn + 1);
5138 neon_load_reg64(cpu_V1, rm);
5141 tmp64 = tcg_temp_new_i64();
5143 neon_load_reg64(cpu_V0, rn);
5144 neon_load_reg64(tmp64, rn + 1);
5146 neon_load_reg64(cpu_V0, rn + 1);
5147 neon_load_reg64(tmp64, rm);
5149 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5150 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5151 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5153 neon_load_reg64(cpu_V1, rm);
5155 neon_load_reg64(cpu_V1, rm + 1);
5158 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5159 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5160 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5163 neon_load_reg64(cpu_V0, rn);
5164 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5165 neon_load_reg64(cpu_V1, rm);
5166 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5167 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5169 neon_store_reg64(cpu_V0, rd);
5171 neon_store_reg64(cpu_V1, rd + 1);
5173 } else if ((insn & (1 << 11)) == 0) {
5174 /* Two register misc. */
5175 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5176 size = (insn >> 18) & 3;
5178 case 0: /* VREV64 */
5181 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5182 NEON_GET_REG(T0, rm, pass * 2);
5183 NEON_GET_REG(T1, rm, pass * 2 + 1);
5185 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5186 case 1: gen_swap_half(cpu_T[0]); break;
5187 case 2: /* no-op */ break;
5190 NEON_SET_REG(T0, rd, pass * 2 + 1);
5192 NEON_SET_REG(T1, rd, pass * 2);
5194 gen_op_movl_T0_T1();
5196 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5197 case 1: gen_swap_half(cpu_T[0]); break;
5200 NEON_SET_REG(T0, rd, pass * 2);
5204 case 4: case 5: /* VPADDL */
5205 case 12: case 13: /* VPADAL */
5208 for (pass = 0; pass < q + 1; pass++) {
5209 tmp = neon_load_reg(rm, pass * 2);
5210 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5211 tmp = neon_load_reg(rm, pass * 2 + 1);
5212 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5214 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5215 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5216 case 2: tcg_gen_add_i64(CPU_V001); break;
5221 neon_load_reg64(cpu_V1, rd + pass);
5222 gen_neon_addl(size);
5224 neon_store_reg64(cpu_V0, rd + pass);
5229 for (n = 0; n < (q ? 4 : 2); n += 2) {
5230 NEON_GET_REG(T0, rm, n);
5231 NEON_GET_REG(T1, rd, n + 1);
5232 NEON_SET_REG(T1, rm, n);
5233 NEON_SET_REG(T0, rd, n + 1);
5241 Rd A3 A2 A1 A0 B2 B0 A2 A0
5242 Rm B3 B2 B1 B0 B3 B1 A3 A1
5246 gen_neon_unzip(rd, q, 0, size);
5247 gen_neon_unzip(rm, q, 4, size);
5249 static int unzip_order_q[8] =
5250 {0, 2, 4, 6, 1, 3, 5, 7};
5251 for (n = 0; n < 8; n++) {
5252 int reg = (n < 4) ? rd : rm;
5253 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5254 NEON_SET_REG(T0, reg, n % 4);
5257 static int unzip_order[4] =
5259 for (n = 0; n < 4; n++) {
5260 int reg = (n < 2) ? rd : rm;
5261 gen_neon_movl_T0_scratch(unzip_order[n]);
5262 NEON_SET_REG(T0, reg, n % 2);
5268 Rd A3 A2 A1 A0 B1 A1 B0 A0
5269 Rm B3 B2 B1 B0 B3 A3 B2 A2
5273 count = (q ? 4 : 2);
5274 for (n = 0; n < count; n++) {
5275 NEON_GET_REG(T0, rd, n);
5276 NEON_GET_REG(T1, rd, n);
5278 case 0: gen_helper_neon_zip_u8(); break;
5279 case 1: gen_helper_neon_zip_u16(); break;
5280 case 2: /* no-op */; break;
5283 gen_neon_movl_scratch_T0(n * 2);
5284 gen_neon_movl_scratch_T1(n * 2 + 1);
5286 for (n = 0; n < count * 2; n++) {
5287 int reg = (n < count) ? rd : rm;
5288 gen_neon_movl_T0_scratch(n);
5289 NEON_SET_REG(T0, reg, n % count);
5292 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5296 for (pass = 0; pass < 2; pass++) {
5297 neon_load_reg64(cpu_V0, rm + pass);
5299 if (op == 36 && q == 0) {
5300 gen_neon_narrow(size, tmp, cpu_V0);
5302 gen_neon_narrow_satu(size, tmp, cpu_V0);
5304 gen_neon_narrow_sats(size, tmp, cpu_V0);
5309 neon_store_reg(rd, 0, tmp2);
5310 neon_store_reg(rd, 1, tmp);
5314 case 38: /* VSHLL */
5317 tmp = neon_load_reg(rm, 0);
5318 tmp2 = neon_load_reg(rm, 1);
5319 for (pass = 0; pass < 2; pass++) {
5322 gen_neon_widen(cpu_V0, tmp, size, 1);
5323 neon_store_reg64(cpu_V0, rd + pass);
5328 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5329 if (op == 30 || op == 31 || op >= 58) {
5330 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5331 neon_reg_offset(rm, pass));
5333 NEON_GET_REG(T0, rm, pass);
5336 case 1: /* VREV32 */
5338 case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
5339 case 1: gen_swap_half(cpu_T[0]); break;
5343 case 2: /* VREV16 */
5346 gen_rev16(cpu_T[0]);
5350 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5351 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5352 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5358 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5359 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5360 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5367 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5374 case 14: /* VQABS */
5376 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5377 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5378 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5382 case 15: /* VQNEG */
5384 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5385 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5386 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5390 case 16: case 19: /* VCGT #0, VCLE #0 */
5391 gen_op_movl_T1_im(0);
5393 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5394 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5395 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5401 case 17: case 20: /* VCGE #0, VCLT #0 */
5402 gen_op_movl_T1_im(0);
5404 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5405 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5406 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5412 case 18: /* VCEQ #0 */
5413 gen_op_movl_T1_im(0);
5415 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5416 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5417 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5423 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5424 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5425 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5430 gen_op_movl_T1_im(0);
5435 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5436 gen_op_movl_T1_im(0);
5437 gen_helper_neon_cgt_f32(CPU_T001);
5441 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5442 gen_op_movl_T1_im(0);
5443 gen_helper_neon_cge_f32(CPU_T001);
5447 case 26: /* Float VCEQ #0 */
5448 gen_op_movl_T1_im(0);
5449 gen_helper_neon_ceq_f32(CPU_T001);
5451 case 30: /* Float VABS */
5454 case 31: /* Float VNEG */
5458 NEON_GET_REG(T1, rd, pass);
5459 NEON_SET_REG(T1, rm, pass);
5462 NEON_GET_REG(T1, rd, pass);
5464 case 0: gen_helper_neon_trn_u8(); break;
5465 case 1: gen_helper_neon_trn_u16(); break;
5469 NEON_SET_REG(T1, rm, pass);
5471 case 56: /* Integer VRECPE */
5472 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5474 case 57: /* Integer VRSQRTE */
5475 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5477 case 58: /* Float VRECPE */
5478 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5480 case 59: /* Float VRSQRTE */
5481 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5483 case 60: /* VCVT.F32.S32 */
5486 case 61: /* VCVT.F32.U32 */
5489 case 62: /* VCVT.S32.F32 */
5492 case 63: /* VCVT.U32.F32 */
5496 /* Reserved: 21, 29, 39-56 */
5499 if (op == 30 || op == 31 || op >= 58) {
5500 tcg_gen_st_f32(cpu_F0s, cpu_env,
5501 neon_reg_offset(rd, pass));
5503 NEON_SET_REG(T0, rd, pass);
5508 } else if ((insn & (1 << 10)) == 0) {
5510 n = ((insn >> 5) & 0x18) + 8;
5511 if (insn & (1 << 6)) {
5512 tmp = neon_load_reg(rd, 0);
5515 tcg_gen_movi_i32(tmp, 0);
5517 tmp2 = neon_load_reg(rm, 0);
5518 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5521 if (insn & (1 << 6)) {
5522 tmp = neon_load_reg(rd, 1);
5525 tcg_gen_movi_i32(tmp, 0);
5527 tmp3 = neon_load_reg(rm, 1);
5528 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5530 neon_store_reg(rd, 0, tmp2);
5531 neon_store_reg(rd, 1, tmp3);
5533 } else if ((insn & 0x380) == 0) {
5535 if (insn & (1 << 19)) {
5536 NEON_SET_REG(T0, rm, 1);
5538 NEON_SET_REG(T0, rm, 0);
5540 if (insn & (1 << 16)) {
5541 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5542 } else if (insn & (1 << 17)) {
5543 if ((insn >> 18) & 1)
5544 gen_neon_dup_high16(cpu_T[0]);
5546 gen_neon_dup_low16(cpu_T[0]);
5548 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5549 NEON_SET_REG(T0, rd, pass);
5559 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5561 int crn = (insn >> 16) & 0xf;
5562 int crm = insn & 0xf;
5563 int op1 = (insn >> 21) & 7;
5564 int op2 = (insn >> 5) & 7;
5565 int rt = (insn >> 12) & 0xf;
5568 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5569 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5573 tmp = load_cpu_field(teecr);
5574 store_reg(s, rt, tmp);
5577 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5579 if (IS_USER(s) && (env->teecr & 1))
5581 tmp = load_cpu_field(teehbr);
5582 store_reg(s, rt, tmp);
5586 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5587 op1, crn, crm, op2);
5591 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5593 int crn = (insn >> 16) & 0xf;
5594 int crm = insn & 0xf;
5595 int op1 = (insn >> 21) & 7;
5596 int op2 = (insn >> 5) & 7;
5597 int rt = (insn >> 12) & 0xf;
5600 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5601 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5605 tmp = load_reg(s, rt);
5606 gen_helper_set_teecr(cpu_env, tmp);
5610 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5612 if (IS_USER(s) && (env->teecr & 1))
5614 tmp = load_reg(s, rt);
5615 store_cpu_field(tmp, teehbr);
5619 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5620 op1, crn, crm, op2);
5624 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5628 cpnum = (insn >> 8) & 0xf;
5629 if (arm_feature(env, ARM_FEATURE_XSCALE)
5630 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5636 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5637 return disas_iwmmxt_insn(env, s, insn);
5638 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5639 return disas_dsp_insn(env, s, insn);
5644 return disas_vfp_insn (env, s, insn);
5646 /* Coprocessors 7-15 are architecturally reserved by ARM.
5647 Unfortunately Intel decided to ignore this. */
5648 if (arm_feature(env, ARM_FEATURE_XSCALE))
5650 if (insn & (1 << 20))
5651 return disas_cp14_read(env, s, insn);
5653 return disas_cp14_write(env, s, insn);
5655 return disas_cp15_insn (env, s, insn);
5658 /* Unknown coprocessor. See if the board has hooked it. */
5659 return disas_cp_insn (env, s, insn);
5664 /* Store a 64-bit value to a register pair. Clobbers val. */
5665 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5669 tcg_gen_trunc_i64_i32(tmp, val);
5670 store_reg(s, rlow, tmp);
5672 tcg_gen_shri_i64(val, val, 32);
5673 tcg_gen_trunc_i64_i32(tmp, val);
5674 store_reg(s, rhigh, tmp);
5677 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5678 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5683 /* Load value and extend to 64 bits. */
5684 tmp = tcg_temp_new_i64();
5685 tmp2 = load_reg(s, rlow);
5686 tcg_gen_extu_i32_i64(tmp, tmp2);
5688 tcg_gen_add_i64(val, val, tmp);
5691 /* load and add a 64-bit value from a register pair. */
5692 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5698 /* Load 64-bit value rd:rn. */
5699 tmpl = load_reg(s, rlow);
5700 tmph = load_reg(s, rhigh);
5701 tmp = tcg_temp_new_i64();
5702 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5705 tcg_gen_add_i64(val, val, tmp);
5708 /* Set N and Z flags from a 64-bit value. */
5709 static void gen_logicq_cc(TCGv_i64 val)
5711 TCGv tmp = new_tmp();
5712 gen_helper_logicq_cc(tmp, val);
5717 static void disas_arm_insn(CPUState * env, DisasContext *s)
5719 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5726 insn = ldl_code(s->pc);
5729 /* M variants do not implement ARM mode. */
5734 /* Unconditional instructions. */
5735 if (((insn >> 25) & 7) == 1) {
5736 /* NEON Data processing. */
5737 if (!arm_feature(env, ARM_FEATURE_NEON))
5740 if (disas_neon_data_insn(env, s, insn))
5744 if ((insn & 0x0f100000) == 0x04000000) {
5745 /* NEON load/store. */
5746 if (!arm_feature(env, ARM_FEATURE_NEON))
5749 if (disas_neon_ls_insn(env, s, insn))
5753 if ((insn & 0x0d70f000) == 0x0550f000)
5755 else if ((insn & 0x0ffffdff) == 0x01010000) {
5758 if (insn & (1 << 9)) {
5759 /* BE8 mode not implemented. */
5763 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5764 switch ((insn >> 4) & 0xf) {
5767 gen_helper_clrex(cpu_env);
5773 /* We don't emulate caches so these are a no-op. */
5778 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5784 op1 = (insn & 0x1f);
5785 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5786 addr = load_reg(s, 13);
5789 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5791 i = (insn >> 23) & 3;
5793 case 0: offset = -4; break; /* DA */
5794 case 1: offset = -8; break; /* DB */
5795 case 2: offset = 0; break; /* IA */
5796 case 3: offset = 4; break; /* IB */
5800 tcg_gen_addi_i32(addr, addr, offset);
5801 tmp = load_reg(s, 14);
5802 gen_st32(tmp, addr, 0);
5804 gen_helper_cpsr_read(tmp);
5805 tcg_gen_addi_i32(addr, addr, 4);
5806 gen_st32(tmp, addr, 0);
5807 if (insn & (1 << 21)) {
5808 /* Base writeback. */
5810 case 0: offset = -8; break;
5811 case 1: offset = -4; break;
5812 case 2: offset = 4; break;
5813 case 3: offset = 0; break;
5817 tcg_gen_addi_i32(addr, tmp, offset);
5818 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5819 gen_movl_reg_T1(s, 13);
5821 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5826 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5832 rn = (insn >> 16) & 0xf;
5833 addr = load_reg(s, rn);
5834 i = (insn >> 23) & 3;
5836 case 0: offset = -4; break; /* DA */
5837 case 1: offset = -8; break; /* DB */
5838 case 2: offset = 0; break; /* IA */
5839 case 3: offset = 4; break; /* IB */
5843 tcg_gen_addi_i32(addr, addr, offset);
5844 /* Load PC into tmp and CPSR into tmp2. */
5845 tmp = gen_ld32(addr, 0);
5846 tcg_gen_addi_i32(addr, addr, 4);
5847 tmp2 = gen_ld32(addr, 0);
5848 if (insn & (1 << 21)) {
5849 /* Base writeback. */
5851 case 0: offset = -8; break;
5852 case 1: offset = -4; break;
5853 case 2: offset = 4; break;
5854 case 3: offset = 0; break;
5858 tcg_gen_addi_i32(addr, addr, offset);
5859 store_reg(s, rn, addr);
5863 gen_rfe(s, tmp, tmp2);
5864 } else if ((insn & 0x0e000000) == 0x0a000000) {
5865 /* branch link and change to thumb (blx <offset>) */
5868 val = (uint32_t)s->pc;
5870 tcg_gen_movi_i32(tmp, val);
5871 store_reg(s, 14, tmp);
5872 /* Sign-extend the 24-bit offset */
5873 offset = (((int32_t)insn) << 8) >> 8;
5874 /* offset * 4 + bit24 * 2 + (thumb bit) */
5875 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5876 /* pipeline offset */
5880 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5881 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5882 /* iWMMXt register transfer. */
5883 if (env->cp15.c15_cpar & (1 << 1))
5884 if (!disas_iwmmxt_insn(env, s, insn))
5887 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5888 /* Coprocessor double register transfer. */
5889 } else if ((insn & 0x0f000010) == 0x0e000010) {
5890 /* Additional coprocessor register transfer. */
5891 } else if ((insn & 0x0ff10020) == 0x01000000) {
5894 /* cps (privileged) */
5898 if (insn & (1 << 19)) {
5899 if (insn & (1 << 8))
5901 if (insn & (1 << 7))
5903 if (insn & (1 << 6))
5905 if (insn & (1 << 18))
5908 if (insn & (1 << 17)) {
5910 val |= (insn & 0x1f);
5913 gen_op_movl_T0_im(val);
5914 gen_set_psr_T0(s, mask, 0);
5921 /* if not always execute, we generate a conditional jump to
5923 s->condlabel = gen_new_label();
5924 gen_test_cc(cond ^ 1, s->condlabel);
5927 if ((insn & 0x0f900000) == 0x03000000) {
5928 if ((insn & (1 << 21)) == 0) {
5930 rd = (insn >> 12) & 0xf;
5931 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5932 if ((insn & (1 << 22)) == 0) {
5935 tcg_gen_movi_i32(tmp, val);
5938 tmp = load_reg(s, rd);
5939 tcg_gen_ext16u_i32(tmp, tmp);
5940 tcg_gen_ori_i32(tmp, tmp, val << 16);
5942 store_reg(s, rd, tmp);
5944 if (((insn >> 12) & 0xf) != 0xf)
5946 if (((insn >> 16) & 0xf) == 0) {
5947 gen_nop_hint(s, insn & 0xff);
5949 /* CPSR = immediate */
5951 shift = ((insn >> 8) & 0xf) * 2;
5953 val = (val >> shift) | (val << (32 - shift));
5954 gen_op_movl_T0_im(val);
5955 i = ((insn & (1 << 22)) != 0);
5956 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5960 } else if ((insn & 0x0f900000) == 0x01000000
5961 && (insn & 0x00000090) != 0x00000090) {
5962 /* miscellaneous instructions */
5963 op1 = (insn >> 21) & 3;
5964 sh = (insn >> 4) & 0xf;
5967 case 0x0: /* move program status register */
5970 gen_movl_T0_reg(s, rm);
5971 i = ((op1 & 2) != 0);
5972 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5976 rd = (insn >> 12) & 0xf;
5980 tmp = load_cpu_field(spsr);
5983 gen_helper_cpsr_read(tmp);
5985 store_reg(s, rd, tmp);
5990 /* branch/exchange thumb (bx). */
5991 tmp = load_reg(s, rm);
5993 } else if (op1 == 3) {
5995 rd = (insn >> 12) & 0xf;
5996 tmp = load_reg(s, rm);
5997 gen_helper_clz(tmp, tmp);
5998 store_reg(s, rd, tmp);
6006 /* Trivial implementation equivalent to bx. */
6007 tmp = load_reg(s, rm);
6017 /* branch link/exchange thumb (blx) */
6018 tmp = load_reg(s, rm);
6020 tcg_gen_movi_i32(tmp2, s->pc);
6021 store_reg(s, 14, tmp2);
6024 case 0x5: /* saturating add/subtract */
6025 rd = (insn >> 12) & 0xf;
6026 rn = (insn >> 16) & 0xf;
6027 tmp = load_reg(s, rm);
6028 tmp2 = load_reg(s, rn);
6030 gen_helper_double_saturate(tmp2, tmp2);
6032 gen_helper_sub_saturate(tmp, tmp, tmp2);
6034 gen_helper_add_saturate(tmp, tmp, tmp2);
6036 store_reg(s, rd, tmp);
6041 gen_set_condexec(s);
6042 gen_set_pc_im(s->pc - 4);
6043 gen_exception(EXCP_BKPT);
6044 s->is_jmp = DISAS_JUMP;
6045 } else if (op1 == 3) {
6047 if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s))
6049 /* TODO: real implementation; execute as NOP for now */
6050 /*fprintf(stderr, "smc [0x%08x] pc=0x%08x\n", insn, s->pc);*/
6055 case 0x8: /* signed multiply */
6059 rs = (insn >> 8) & 0xf;
6060 rn = (insn >> 12) & 0xf;
6061 rd = (insn >> 16) & 0xf;
6063 /* (32 * 16) >> 16 */
6064 tmp = load_reg(s, rm);
6065 tmp2 = load_reg(s, rs);
6067 tcg_gen_sari_i32(tmp2, tmp2, 16);
6070 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6071 tcg_gen_shri_i64(tmp64, tmp64, 16);
6073 tcg_gen_trunc_i64_i32(tmp, tmp64);
6074 if ((sh & 2) == 0) {
6075 tmp2 = load_reg(s, rn);
6076 gen_helper_add_setq(tmp, tmp, tmp2);
6079 store_reg(s, rd, tmp);
6082 tmp = load_reg(s, rm);
6083 tmp2 = load_reg(s, rs);
6084 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6087 tmp64 = tcg_temp_new_i64();
6088 tcg_gen_ext_i32_i64(tmp64, tmp);
6090 gen_addq(s, tmp64, rn, rd);
6091 gen_storeq_reg(s, rn, rd, tmp64);
6094 tmp2 = load_reg(s, rn);
6095 gen_helper_add_setq(tmp, tmp, tmp2);
6098 store_reg(s, rd, tmp);
6105 } else if (((insn & 0x0e000000) == 0 &&
6106 (insn & 0x00000090) != 0x90) ||
6107 ((insn & 0x0e000000) == (1 << 25))) {
6108 int set_cc, logic_cc, shiftop;
6110 op1 = (insn >> 21) & 0xf;
6111 set_cc = (insn >> 20) & 1;
6112 logic_cc = table_logic_cc[op1] & set_cc;
6114 /* data processing instruction */
6115 if (insn & (1 << 25)) {
6116 /* immediate operand */
6118 shift = ((insn >> 8) & 0xf) * 2;
6120 val = (val >> shift) | (val << (32 - shift));
6122 tcg_gen_movi_i32(tmp2, val);
6123 if (logic_cc && shift)
6124 gen_set_CF_bit31(tmp2);
6128 tmp2 = load_reg(s, rm);
6129 shiftop = (insn >> 5) & 3;
6130 if (!(insn & (1 << 4))) {
6131 shift = (insn >> 7) & 0x1f;
6132 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6134 rs = (insn >> 8) & 0xf;
6135 tmp = load_reg(s, rs);
6136 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6139 if (op1 != 0x0f && op1 != 0x0d) {
6140 rn = (insn >> 16) & 0xf;
6141 gen_movl_T0_reg(s, rn); tmp = load_reg(s, rn);
6144 rd = (insn >> 12) & 0xf;
6147 tcg_gen_and_i32(tmp, tmp, tmp2);
6150 store_reg_bx(s, rd, tmp);
6153 tcg_gen_xor_i32(tmp, tmp, tmp2);
6156 store_reg_bx(s, rd, tmp);
6159 if (set_cc && rd == 15) {
6160 /* SUBS r15, ... is used for exception return. */
6163 gen_helper_sub_cc(tmp, tmp, tmp2);
6164 gen_exception_return(s, tmp);
6167 gen_helper_sub_cc(tmp, tmp, tmp2);
6169 tcg_gen_sub_i32(tmp, tmp, tmp2);
6170 store_reg_bx(s, rd, tmp);
6175 gen_helper_sub_cc(tmp, tmp2, tmp);
6177 tcg_gen_sub_i32(tmp, tmp2, tmp);
6178 store_reg_bx(s, rd, tmp);
6182 gen_helper_add_cc(tmp, tmp, tmp2);
6184 tcg_gen_add_i32(tmp, tmp, tmp2);
6185 store_reg_bx(s, rd, tmp);
6189 gen_helper_adc_cc(tmp, tmp, tmp2);
6191 gen_add_carry(tmp, tmp, tmp2);
6192 store_reg_bx(s, rd, tmp);
6196 gen_helper_sbc_cc(tmp, tmp, tmp2);
6198 gen_sub_carry(tmp, tmp, tmp2);
6199 store_reg_bx(s, rd, tmp);
6203 gen_helper_sbc_cc(tmp, tmp2, tmp);
6205 gen_sub_carry(tmp, tmp2, tmp);
6206 store_reg_bx(s, rd, tmp);
6210 tcg_gen_and_i32(tmp, tmp, tmp2);
6217 tcg_gen_xor_i32(tmp, tmp, tmp2);
6224 gen_helper_sub_cc(tmp, tmp, tmp2);
6229 gen_helper_add_cc(tmp, tmp, tmp2);
6233 tcg_gen_or_i32(tmp, tmp, tmp2);
6236 store_reg_bx(s, rd, tmp);
6239 tcg_gen_mov_i32(tmp, tmp2);
6240 if (logic_cc && rd == 15) {
6241 /* MOVS r15, ... is used for exception return. */
6244 gen_exception_return(s, tmp);
6246 store_reg_bx(s, rd, tmp);
6252 tcg_gen_bic_i32(tmp, tmp, tmp2);
6255 store_reg_bx(s, rd, tmp);
6259 tcg_gen_not_i32(tmp, tmp2);
6262 store_reg_bx(s, rd, tmp);
6267 /* other instructions */
6268 op1 = (insn >> 24) & 0xf;
6272 /* multiplies, extra load/stores */
6273 sh = (insn >> 5) & 3;
6276 rd = (insn >> 16) & 0xf;
6277 rn = (insn >> 12) & 0xf;
6278 rs = (insn >> 8) & 0xf;
6280 op1 = (insn >> 20) & 0xf;
6282 case 0: case 1: case 2: case 3: case 6:
6284 tmp = load_reg(s, rs);
6285 tmp2 = load_reg(s, rm);
6286 tcg_gen_mul_i32(tmp, tmp, tmp2);
6288 if (insn & (1 << 22)) {
6289 /* Subtract (mls) */
6291 tmp2 = load_reg(s, rn);
6292 tcg_gen_sub_i32(tmp, tmp2, tmp);
6294 } else if (insn & (1 << 21)) {
6296 tmp2 = load_reg(s, rn);
6297 tcg_gen_add_i32(tmp, tmp, tmp2);
6300 if (insn & (1 << 20))
6302 store_reg(s, rd, tmp);
6306 tmp = load_reg(s, rs);
6307 tmp2 = load_reg(s, rm);
6308 if (insn & (1 << 22))
6309 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6311 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6312 if (insn & (1 << 21)) /* mult accumulate */
6313 gen_addq(s, tmp64, rn, rd);
6314 if (!(insn & (1 << 23))) { /* double accumulate */
6316 gen_addq_lo(s, tmp64, rn);
6317 gen_addq_lo(s, tmp64, rd);
6319 if (insn & (1 << 20))
6320 gen_logicq_cc(tmp64);
6321 gen_storeq_reg(s, rn, rd, tmp64);
6325 rn = (insn >> 16) & 0xf;
6326 rd = (insn >> 12) & 0xf;
6327 if (insn & (1 << 23)) {
6328 /* load/store exclusive */
6329 op1 = (insn >> 21) & 0x3;
6334 gen_movl_T1_reg(s, rn);
6336 if (insn & (1 << 20)) {
6337 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6340 tmp = gen_ld32(addr, IS_USER(s));
6342 case 1: /* ldrexd */
6343 tmp = gen_ld32(addr, IS_USER(s));
6344 store_reg(s, rd, tmp);
6345 tcg_gen_addi_i32(addr, addr, 4);
6346 tmp = gen_ld32(addr, IS_USER(s));
6349 case 2: /* ldrexb */
6350 tmp = gen_ld8u(addr, IS_USER(s));
6352 case 3: /* ldrexh */
6353 tmp = gen_ld16u(addr, IS_USER(s));
6358 store_reg(s, rd, tmp);
6360 int label = gen_new_label();
6362 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6363 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6365 tmp = load_reg(s,rm);
6368 gen_st32(tmp, addr, IS_USER(s));
6370 case 1: /* strexd */
6371 gen_st32(tmp, addr, IS_USER(s));
6372 tcg_gen_addi_i32(addr, addr, 4);
6373 tmp = load_reg(s, rm + 1);
6374 gen_st32(tmp, addr, IS_USER(s));
6376 case 2: /* strexb */
6377 gen_st8(tmp, addr, IS_USER(s));
6379 case 3: /* strexh */
6380 gen_st16(tmp, addr, IS_USER(s));
6385 gen_set_label(label);
6386 gen_movl_reg_T0(s, rd);
6389 /* SWP instruction */
6392 /* ??? This is not really atomic. However we know
6393 we never have multiple CPUs running in parallel,
6394 so it is good enough. */
6395 addr = load_reg(s, rn);
6396 tmp = load_reg(s, rm);
6397 if (insn & (1 << 22)) {
6398 tmp2 = gen_ld8u(addr, IS_USER(s));
6399 gen_st8(tmp, addr, IS_USER(s));
6401 tmp2 = gen_ld32(addr, IS_USER(s));
6402 gen_st32(tmp, addr, IS_USER(s));
6405 store_reg(s, rd, tmp2);
6411 /* Misc load/store */
6412 rn = (insn >> 16) & 0xf;
6413 rd = (insn >> 12) & 0xf;
6414 addr = load_reg(s, rn);
6415 if (insn & (1 << 24))
6416 gen_add_datah_offset(s, insn, 0, addr);
6418 if (insn & (1 << 20)) {
6422 tmp = gen_ld16u(addr, IS_USER(s));
6425 tmp = gen_ld8s(addr, IS_USER(s));
6429 tmp = gen_ld16s(addr, IS_USER(s));
6433 } else if (sh & 2) {
6437 tmp = load_reg(s, rd);
6438 gen_st32(tmp, addr, IS_USER(s));
6439 tcg_gen_addi_i32(addr, addr, 4);
6440 tmp = load_reg(s, rd + 1);
6441 gen_st32(tmp, addr, IS_USER(s));
6445 tmp = gen_ld32(addr, IS_USER(s));
6446 store_reg(s, rd, tmp);
6447 tcg_gen_addi_i32(addr, addr, 4);
6448 tmp = gen_ld32(addr, IS_USER(s));
6452 address_offset = -4;
6455 tmp = load_reg(s, rd);
6456 gen_st16(tmp, addr, IS_USER(s));
6459 /* Perform base writeback before the loaded value to
6460 ensure correct behavior with overlapping index registers.
6461 ldrd with base writeback is is undefined if the
6462 destination and index registers overlap. */
6463 if (!(insn & (1 << 24))) {
6464 gen_add_datah_offset(s, insn, address_offset, addr);
6465 store_reg(s, rn, addr);
6466 } else if (insn & (1 << 21)) {
6468 tcg_gen_addi_i32(addr, addr, address_offset);
6469 store_reg(s, rn, addr);
6474 /* Complete the load. */
6475 store_reg(s, rd, tmp);
6484 if (insn & (1 << 4)) {
6486 /* Armv6 Media instructions. */
6488 rn = (insn >> 16) & 0xf;
6489 rd = (insn >> 12) & 0xf;
6490 rs = (insn >> 8) & 0xf;
6491 switch ((insn >> 23) & 3) {
6492 case 0: /* Parallel add/subtract. */
6493 op1 = (insn >> 20) & 7;
6494 tmp = load_reg(s, rn);
6495 tmp2 = load_reg(s, rm);
6496 sh = (insn >> 5) & 7;
6497 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6499 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6501 store_reg(s, rd, tmp);
6504 if ((insn & 0x00700020) == 0) {
6505 /* Halfword pack. */
6506 tmp = load_reg(s, rn);
6507 tmp2 = load_reg(s, rm);
6508 shift = (insn >> 7) & 0x1f;
6509 if (insn & (1 << 6)) {
6513 tcg_gen_sari_i32(tmp2, tmp2, shift);
6514 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6515 tcg_gen_ext16u_i32(tmp2, tmp2);
6519 tcg_gen_shli_i32(tmp2, tmp2, shift);
6520 tcg_gen_ext16u_i32(tmp, tmp);
6521 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6523 tcg_gen_or_i32(tmp, tmp, tmp2);
6525 store_reg(s, rd, tmp);
6526 } else if ((insn & 0x00200020) == 0x00200000) {
6528 tmp = load_reg(s, rm);
6529 shift = (insn >> 7) & 0x1f;
6530 if (insn & (1 << 6)) {
6533 tcg_gen_sari_i32(tmp, tmp, shift);
6535 tcg_gen_shli_i32(tmp, tmp, shift);
6537 sh = (insn >> 16) & 0x1f;
6539 if (insn & (1 << 22))
6540 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6542 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6544 store_reg(s, rd, tmp);
6545 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6547 tmp = load_reg(s, rm);
6548 sh = (insn >> 16) & 0x1f;
6550 if (insn & (1 << 22))
6551 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6553 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6555 store_reg(s, rd, tmp);
6556 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6558 tmp = load_reg(s, rn);
6559 tmp2 = load_reg(s, rm);
6561 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6562 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6565 store_reg(s, rd, tmp);
6566 } else if ((insn & 0x000003e0) == 0x00000060) {
6567 tmp = load_reg(s, rm);
6568 shift = (insn >> 10) & 3;
6569 /* ??? In many cases it's not neccessary to do a
6570 rotate, a shift is sufficient. */
6572 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6573 op1 = (insn >> 20) & 7;
6575 case 0: gen_sxtb16(tmp); break;
6576 case 2: gen_sxtb(tmp); break;
6577 case 3: gen_sxth(tmp); break;
6578 case 4: gen_uxtb16(tmp); break;
6579 case 6: gen_uxtb(tmp); break;
6580 case 7: gen_uxth(tmp); break;
6581 default: goto illegal_op;
6584 tmp2 = load_reg(s, rn);
6585 if ((op1 & 3) == 0) {
6586 gen_add16(tmp, tmp2);
6588 tcg_gen_add_i32(tmp, tmp, tmp2);
6592 store_reg(s, rd, tmp);
6593 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6595 tmp = load_reg(s, rm);
6596 if (insn & (1 << 22)) {
6597 if (insn & (1 << 7)) {
6601 gen_helper_rbit(tmp, tmp);
6604 if (insn & (1 << 7))
6607 tcg_gen_bswap_i32(tmp, tmp);
6609 store_reg(s, rd, tmp);
6614 case 2: /* Multiplies (Type 3). */
6615 tmp = load_reg(s, rm);
6616 tmp2 = load_reg(s, rs);
6617 if (insn & (1 << 20)) {
6618 /* Signed multiply most significant [accumulate]. */
6619 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6620 if (insn & (1 << 5))
6621 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6622 tcg_gen_shri_i64(tmp64, tmp64, 32);
6624 tcg_gen_trunc_i64_i32(tmp, tmp64);
6626 tmp2 = load_reg(s, rd);
6627 if (insn & (1 << 6)) {
6628 tcg_gen_sub_i32(tmp, tmp, tmp2);
6630 tcg_gen_add_i32(tmp, tmp, tmp2);
6634 store_reg(s, rn, tmp);
6636 if (insn & (1 << 5))
6637 gen_swap_half(tmp2);
6638 gen_smul_dual(tmp, tmp2);
6639 /* This addition cannot overflow. */
6640 if (insn & (1 << 6)) {
6641 tcg_gen_sub_i32(tmp, tmp, tmp2);
6643 tcg_gen_add_i32(tmp, tmp, tmp2);
6646 if (insn & (1 << 22)) {
6647 /* smlald, smlsld */
6648 tmp64 = tcg_temp_new_i64();
6649 tcg_gen_ext_i32_i64(tmp64, tmp);
6651 gen_addq(s, tmp64, rd, rn);
6652 gen_storeq_reg(s, rd, rn, tmp64);
6654 /* smuad, smusd, smlad, smlsd */
6657 tmp2 = load_reg(s, rd);
6658 gen_helper_add_setq(tmp, tmp, tmp2);
6661 store_reg(s, rn, tmp);
6666 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6668 case 0: /* Unsigned sum of absolute differences. */
6670 tmp = load_reg(s, rm);
6671 tmp2 = load_reg(s, rs);
6672 gen_helper_usad8(tmp, tmp, tmp2);
6675 tmp2 = load_reg(s, rd);
6676 tcg_gen_add_i32(tmp, tmp, tmp2);
6679 store_reg(s, rn, tmp);
6681 case 0x20: case 0x24: case 0x28: case 0x2c:
6682 /* Bitfield insert/clear. */
6684 shift = (insn >> 7) & 0x1f;
6685 i = (insn >> 16) & 0x1f;
6689 tcg_gen_movi_i32(tmp, 0);
6691 tmp = load_reg(s, rm);
6694 tmp2 = load_reg(s, rd);
6695 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6698 store_reg(s, rd, tmp);
6700 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6701 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6703 tmp = load_reg(s, rm);
6704 shift = (insn >> 7) & 0x1f;
6705 i = ((insn >> 16) & 0x1f) + 1;
6710 gen_ubfx(tmp, shift, (1u << i) - 1);
6712 gen_sbfx(tmp, shift, i);
6715 store_reg(s, rd, tmp);
6725 /* Check for undefined extension instructions
6726 * per the ARM Bible IE:
6727 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6729 sh = (0xf << 20) | (0xf << 4);
6730 if (op1 == 0x7 && ((insn & sh) == sh))
6734 /* load/store byte/word */
6735 rn = (insn >> 16) & 0xf;
6736 rd = (insn >> 12) & 0xf;
6737 tmp2 = load_reg(s, rn);
6738 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6739 if (insn & (1 << 24))
6740 gen_add_data_offset(s, insn, tmp2);
6741 if (insn & (1 << 20)) {
6743 if (insn & (1 << 22)) {
6744 tmp = gen_ld8u(tmp2, i);
6746 tmp = gen_ld32(tmp2, i);
6750 tmp = load_reg(s, rd);
6751 if (insn & (1 << 22))
6752 gen_st8(tmp, tmp2, i);
6754 gen_st32(tmp, tmp2, i);
6756 if (!(insn & (1 << 24))) {
6757 gen_add_data_offset(s, insn, tmp2);
6758 store_reg(s, rn, tmp2);
6759 } else if (insn & (1 << 21)) {
6760 store_reg(s, rn, tmp2);
6764 if (insn & (1 << 20)) {
6765 /* Complete the load. */
6769 store_reg(s, rd, tmp);
6775 int j, n, user, loaded_base;
6777 /* load/store multiple words */
6778 /* XXX: store correct base if write back */
6780 if (insn & (1 << 22)) {
6782 goto illegal_op; /* only usable in supervisor mode */
6784 if ((insn & (1 << 15)) == 0)
6787 rn = (insn >> 16) & 0xf;
6788 addr = load_reg(s, rn);
6790 /* compute total size */
6792 TCGV_UNUSED(loaded_var);
6795 if (insn & (1 << i))
6798 /* XXX: test invalid n == 0 case ? */
6799 if (insn & (1 << 23)) {
6800 if (insn & (1 << 24)) {
6802 tcg_gen_addi_i32(addr, addr, 4);
6804 /* post increment */
6807 if (insn & (1 << 24)) {
6809 tcg_gen_addi_i32(addr, addr, -(n * 4));
6811 /* post decrement */
6813 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6818 if (insn & (1 << i)) {
6819 if (insn & (1 << 20)) {
6821 tmp = gen_ld32(addr, IS_USER(s));
6825 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6827 } else if (i == rn) {
6831 store_reg(s, i, tmp);
6836 /* special case: r15 = PC + 8 */
6837 val = (long)s->pc + 4;
6839 tcg_gen_movi_i32(tmp, val);
6842 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6844 tmp = load_reg(s, i);
6846 gen_st32(tmp, addr, IS_USER(s));
6849 /* no need to add after the last transfer */
6851 tcg_gen_addi_i32(addr, addr, 4);
6854 if (insn & (1 << 21)) {
6856 if (insn & (1 << 23)) {
6857 if (insn & (1 << 24)) {
6860 /* post increment */
6861 tcg_gen_addi_i32(addr, addr, 4);
6864 if (insn & (1 << 24)) {
6867 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6869 /* post decrement */
6870 tcg_gen_addi_i32(addr, addr, -(n * 4));
6873 store_reg(s, rn, addr);
6878 store_reg(s, rn, loaded_var);
6880 if ((insn & (1 << 22)) && !user) {
6881 /* Restore CPSR from SPSR. */
6882 tmp = load_cpu_field(spsr);
6883 gen_set_cpsr(tmp, 0xffffffff);
6885 s->is_jmp = DISAS_UPDATE;
6894 /* branch (and link) */
6895 val = (int32_t)s->pc;
6896 if (insn & (1 << 24)) {
6898 tcg_gen_movi_i32(tmp, val);
6899 store_reg(s, 14, tmp);
6901 offset = (((int32_t)insn << 8) >> 8);
6902 val += (offset << 2) + 4;
6910 if (disas_coproc_insn(env, s, insn))
6915 gen_set_pc_im(s->pc);
6916 s->is_jmp = DISAS_SWI;
6920 gen_set_condexec(s);
6921 gen_set_pc_im(s->pc - 4);
6922 gen_exception(EXCP_UDEF);
6923 s->is_jmp = DISAS_JUMP;
6929 /* Return true if this is a Thumb-2 logical op. */
6931 thumb2_logic_op(int op)
6936 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6937 then set condition code flags based on the result of the operation.
6938 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6939 to the high bit of T1.
6940 Returns zero if the opcode is valid. */
6943 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6950 gen_op_andl_T0_T1();
6954 gen_op_bicl_T0_T1();
6967 gen_op_xorl_T0_T1();
6972 gen_op_addl_T0_T1_cc();
6974 gen_op_addl_T0_T1();
6978 gen_op_adcl_T0_T1_cc();
6984 gen_op_sbcl_T0_T1_cc();
6990 gen_op_subl_T0_T1_cc();
6992 gen_op_subl_T0_T1();
6996 gen_op_rsbl_T0_T1_cc();
6998 gen_op_rsbl_T0_T1();
7000 default: /* 5, 6, 7, 9, 12, 15. */
7004 gen_op_logic_T0_cc();
7006 gen_set_CF_bit31(cpu_T[1]);
7011 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7013 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7015 uint32_t insn, imm, shift, offset;
7016 uint32_t rd, rn, rm, rs;
7027 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7028 || arm_feature (env, ARM_FEATURE_M))) {
7029 /* Thumb-1 cores may need to treat bl and blx as a pair of
7030 16-bit instructions to get correct prefetch abort behavior. */
7032 if ((insn & (1 << 12)) == 0) {
7033 /* Second half of blx. */
7034 offset = ((insn & 0x7ff) << 1);
7035 tmp = load_reg(s, 14);
7036 tcg_gen_addi_i32(tmp, tmp, offset);
7037 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7040 tcg_gen_movi_i32(tmp2, s->pc | 1);
7041 store_reg(s, 14, tmp2);
7045 if (insn & (1 << 11)) {
7046 /* Second half of bl. */
7047 offset = ((insn & 0x7ff) << 1) | 1;
7048 tmp = load_reg(s, 14);
7049 tcg_gen_addi_i32(tmp, tmp, offset);
7052 tcg_gen_movi_i32(tmp2, s->pc | 1);
7053 store_reg(s, 14, tmp2);
7057 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7058 /* Instruction spans a page boundary. Implement it as two
7059 16-bit instructions in case the second half causes an
7061 offset = ((int32_t)insn << 21) >> 9;
7062 gen_op_movl_T0_im(s->pc + 2 + offset);
7063 gen_movl_reg_T0(s, 14);
7066 /* Fall through to 32-bit decode. */
7069 insn = lduw_code(s->pc);
7071 insn |= (uint32_t)insn_hw1 << 16;
7073 if ((insn & 0xf800e800) != 0xf000e800) {
7077 rn = (insn >> 16) & 0xf;
7078 rs = (insn >> 12) & 0xf;
7079 rd = (insn >> 8) & 0xf;
7081 switch ((insn >> 25) & 0xf) {
7082 case 0: case 1: case 2: case 3:
7083 /* 16-bit instructions. Should never happen. */
7086 if (insn & (1 << 22)) {
7087 /* Other load/store, table branch. */
7088 if (insn & 0x01200000) {
7089 /* Load/store doubleword. */
7092 tcg_gen_movi_i32(addr, s->pc & ~3);
7094 addr = load_reg(s, rn);
7096 offset = (insn & 0xff) * 4;
7097 if ((insn & (1 << 23)) == 0)
7099 if (insn & (1 << 24)) {
7100 tcg_gen_addi_i32(addr, addr, offset);
7103 if (insn & (1 << 20)) {
7105 tmp = gen_ld32(addr, IS_USER(s));
7106 store_reg(s, rs, tmp);
7107 tcg_gen_addi_i32(addr, addr, 4);
7108 tmp = gen_ld32(addr, IS_USER(s));
7109 store_reg(s, rd, tmp);
7112 tmp = load_reg(s, rs);
7113 gen_st32(tmp, addr, IS_USER(s));
7114 tcg_gen_addi_i32(addr, addr, 4);
7115 tmp = load_reg(s, rd);
7116 gen_st32(tmp, addr, IS_USER(s));
7118 if (insn & (1 << 21)) {
7119 /* Base writeback. */
7122 tcg_gen_addi_i32(addr, addr, offset - 4);
7123 store_reg(s, rn, addr);
7127 } else if ((insn & (1 << 23)) == 0) {
7128 /* Load/store exclusive word. */
7129 gen_movl_T1_reg(s, rn);
7131 if (insn & (1 << 20)) {
7132 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
7133 tmp = gen_ld32(addr, IS_USER(s));
7134 store_reg(s, rd, tmp);
7136 int label = gen_new_label();
7137 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7138 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7140 tmp = load_reg(s, rs);
7141 gen_st32(tmp, cpu_T[1], IS_USER(s));
7142 gen_set_label(label);
7143 gen_movl_reg_T0(s, rd);
7145 } else if ((insn & (1 << 6)) == 0) {
7149 tcg_gen_movi_i32(addr, s->pc);
7151 addr = load_reg(s, rn);
7153 tmp = load_reg(s, rm);
7154 tcg_gen_add_i32(addr, addr, tmp);
7155 if (insn & (1 << 4)) {
7157 tcg_gen_add_i32(addr, addr, tmp);
7159 tmp = gen_ld16u(addr, IS_USER(s));
7162 tmp = gen_ld8u(addr, IS_USER(s));
7165 tcg_gen_shli_i32(tmp, tmp, 1);
7166 tcg_gen_addi_i32(tmp, tmp, s->pc);
7167 store_reg(s, 15, tmp);
7169 /* Load/store exclusive byte/halfword/doubleword. */
7170 /* ??? These are not really atomic. However we know
7171 we never have multiple CPUs running in parallel,
7172 so it is good enough. */
7173 op = (insn >> 4) & 0x3;
7174 /* Must use a global reg for the address because we have
7175 a conditional branch in the store instruction. */
7176 gen_movl_T1_reg(s, rn);
7178 if (insn & (1 << 20)) {
7179 gen_helper_mark_exclusive(cpu_env, addr);
7182 tmp = gen_ld8u(addr, IS_USER(s));
7185 tmp = gen_ld16u(addr, IS_USER(s));
7188 tmp = gen_ld32(addr, IS_USER(s));
7189 tcg_gen_addi_i32(addr, addr, 4);
7190 tmp2 = gen_ld32(addr, IS_USER(s));
7191 store_reg(s, rd, tmp2);
7196 store_reg(s, rs, tmp);
7198 int label = gen_new_label();
7199 /* Must use a global that is not killed by the branch. */
7200 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7201 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
7202 tmp = load_reg(s, rs);
7205 gen_st8(tmp, addr, IS_USER(s));
7208 gen_st16(tmp, addr, IS_USER(s));
7211 gen_st32(tmp, addr, IS_USER(s));
7212 tcg_gen_addi_i32(addr, addr, 4);
7213 tmp = load_reg(s, rd);
7214 gen_st32(tmp, addr, IS_USER(s));
7219 gen_set_label(label);
7220 gen_movl_reg_T0(s, rm);
7224 /* Load/store multiple, RFE, SRS. */
7225 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7226 /* Not available in user mode. */
7229 if (insn & (1 << 20)) {
7231 addr = load_reg(s, rn);
7232 if ((insn & (1 << 24)) == 0)
7233 tcg_gen_addi_i32(addr, addr, -8);
7234 /* Load PC into tmp and CPSR into tmp2. */
7235 tmp = gen_ld32(addr, 0);
7236 tcg_gen_addi_i32(addr, addr, 4);
7237 tmp2 = gen_ld32(addr, 0);
7238 if (insn & (1 << 21)) {
7239 /* Base writeback. */
7240 if (insn & (1 << 24)) {
7241 tcg_gen_addi_i32(addr, addr, 4);
7243 tcg_gen_addi_i32(addr, addr, -4);
7245 store_reg(s, rn, addr);
7249 gen_rfe(s, tmp, tmp2);
7253 if (op == (env->uncached_cpsr & CPSR_M)) {
7254 addr = load_reg(s, 13);
7257 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7259 if ((insn & (1 << 24)) == 0) {
7260 tcg_gen_addi_i32(addr, addr, -8);
7262 tmp = load_reg(s, 14);
7263 gen_st32(tmp, addr, 0);
7264 tcg_gen_addi_i32(addr, addr, 4);
7266 gen_helper_cpsr_read(tmp);
7267 gen_st32(tmp, addr, 0);
7268 if (insn & (1 << 21)) {
7269 if ((insn & (1 << 24)) == 0) {
7270 tcg_gen_addi_i32(addr, addr, -4);
7272 tcg_gen_addi_i32(addr, addr, 4);
7274 if (op == (env->uncached_cpsr & CPSR_M)) {
7275 store_reg(s, 13, addr);
7277 gen_helper_set_r13_banked(cpu_env,
7278 tcg_const_i32(op), addr);
7286 /* Load/store multiple. */
7287 addr = load_reg(s, rn);
7289 for (i = 0; i < 16; i++) {
7290 if (insn & (1 << i))
7293 if (insn & (1 << 24)) {
7294 tcg_gen_addi_i32(addr, addr, -offset);
7297 for (i = 0; i < 16; i++) {
7298 if ((insn & (1 << i)) == 0)
7300 if (insn & (1 << 20)) {
7302 tmp = gen_ld32(addr, IS_USER(s));
7306 store_reg(s, i, tmp);
7310 tmp = load_reg(s, i);
7311 gen_st32(tmp, addr, IS_USER(s));
7313 tcg_gen_addi_i32(addr, addr, 4);
7315 if (insn & (1 << 21)) {
7316 /* Base register writeback. */
7317 if (insn & (1 << 24)) {
7318 tcg_gen_addi_i32(addr, addr, -offset);
7320 /* Fault if writeback register is in register list. */
7321 if (insn & (1 << rn))
7323 store_reg(s, rn, addr);
7330 case 5: /* Data processing register constant shift. */
7332 gen_op_movl_T0_im(0);
7334 gen_movl_T0_reg(s, rn);
7335 gen_movl_T1_reg(s, rm);
7336 op = (insn >> 21) & 0xf;
7337 shiftop = (insn >> 4) & 3;
7338 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7339 conds = (insn & (1 << 20)) != 0;
7340 logic_cc = (conds && thumb2_logic_op(op));
7341 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7342 if (gen_thumb2_data_op(s, op, conds, 0))
7345 gen_movl_reg_T0(s, rd);
7347 case 13: /* Misc data processing. */
7348 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7349 if (op < 4 && (insn & 0xf000) != 0xf000)
7352 case 0: /* Register controlled shift. */
7353 tmp = load_reg(s, rn);
7354 tmp2 = load_reg(s, rm);
7355 if ((insn & 0x70) != 0)
7357 op = (insn >> 21) & 3;
7358 logic_cc = (insn & (1 << 20)) != 0;
7359 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7362 store_reg(s, rd, tmp);
7364 case 1: /* Sign/zero extend. */
7365 tmp = load_reg(s, rm);
7366 shift = (insn >> 4) & 3;
7367 /* ??? In many cases it's not neccessary to do a
7368 rotate, a shift is sufficient. */
7370 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7371 op = (insn >> 20) & 7;
7373 case 0: gen_sxth(tmp); break;
7374 case 1: gen_uxth(tmp); break;
7375 case 2: gen_sxtb16(tmp); break;
7376 case 3: gen_uxtb16(tmp); break;
7377 case 4: gen_sxtb(tmp); break;
7378 case 5: gen_uxtb(tmp); break;
7379 default: goto illegal_op;
7382 tmp2 = load_reg(s, rn);
7383 if ((op >> 1) == 1) {
7384 gen_add16(tmp, tmp2);
7386 tcg_gen_add_i32(tmp, tmp, tmp2);
7390 store_reg(s, rd, tmp);
7392 case 2: /* SIMD add/subtract. */
7393 op = (insn >> 20) & 7;
7394 shift = (insn >> 4) & 7;
7395 if ((op & 3) == 3 || (shift & 3) == 3)
7397 tmp = load_reg(s, rn);
7398 tmp2 = load_reg(s, rm);
7399 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7401 store_reg(s, rd, tmp);
7403 case 3: /* Other data processing. */
7404 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7406 /* Saturating add/subtract. */
7407 tmp = load_reg(s, rn);
7408 tmp2 = load_reg(s, rm);
7410 gen_helper_double_saturate(tmp, tmp);
7412 gen_helper_sub_saturate(tmp, tmp2, tmp);
7414 gen_helper_add_saturate(tmp, tmp, tmp2);
7417 tmp = load_reg(s, rn);
7419 case 0x0a: /* rbit */
7420 gen_helper_rbit(tmp, tmp);
7422 case 0x08: /* rev */
7423 tcg_gen_bswap_i32(tmp, tmp);
7425 case 0x09: /* rev16 */
7428 case 0x0b: /* revsh */
7431 case 0x10: /* sel */
7432 tmp2 = load_reg(s, rm);
7434 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7435 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7439 case 0x18: /* clz */
7440 gen_helper_clz(tmp, tmp);
7446 store_reg(s, rd, tmp);
7448 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7449 op = (insn >> 4) & 0xf;
7450 tmp = load_reg(s, rn);
7451 tmp2 = load_reg(s, rm);
7452 switch ((insn >> 20) & 7) {
7453 case 0: /* 32 x 32 -> 32 */
7454 tcg_gen_mul_i32(tmp, tmp, tmp2);
7457 tmp2 = load_reg(s, rs);
7459 tcg_gen_sub_i32(tmp, tmp2, tmp);
7461 tcg_gen_add_i32(tmp, tmp, tmp2);
7465 case 1: /* 16 x 16 -> 32 */
7466 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7469 tmp2 = load_reg(s, rs);
7470 gen_helper_add_setq(tmp, tmp, tmp2);
7474 case 2: /* Dual multiply add. */
7475 case 4: /* Dual multiply subtract. */
7477 gen_swap_half(tmp2);
7478 gen_smul_dual(tmp, tmp2);
7479 /* This addition cannot overflow. */
7480 if (insn & (1 << 22)) {
7481 tcg_gen_sub_i32(tmp, tmp, tmp2);
7483 tcg_gen_add_i32(tmp, tmp, tmp2);
7488 tmp2 = load_reg(s, rs);
7489 gen_helper_add_setq(tmp, tmp, tmp2);
7493 case 3: /* 32 * 16 -> 32msb */
7495 tcg_gen_sari_i32(tmp2, tmp2, 16);
7498 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7499 tcg_gen_shri_i64(tmp64, tmp64, 16);
7501 tcg_gen_trunc_i64_i32(tmp, tmp64);
7504 tmp2 = load_reg(s, rs);
7505 gen_helper_add_setq(tmp, tmp, tmp2);
7509 case 5: case 6: /* 32 * 32 -> 32msb */
7510 gen_imull(tmp, tmp2);
7511 if (insn & (1 << 5)) {
7512 gen_roundqd(tmp, tmp2);
7519 tmp2 = load_reg(s, rs);
7520 if (insn & (1 << 21)) {
7521 tcg_gen_add_i32(tmp, tmp, tmp2);
7523 tcg_gen_sub_i32(tmp, tmp2, tmp);
7528 case 7: /* Unsigned sum of absolute differences. */
7529 gen_helper_usad8(tmp, tmp, tmp2);
7532 tmp2 = load_reg(s, rs);
7533 tcg_gen_add_i32(tmp, tmp, tmp2);
7538 store_reg(s, rd, tmp);
7540 case 6: case 7: /* 64-bit multiply, Divide. */
7541 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7542 tmp = load_reg(s, rn);
7543 tmp2 = load_reg(s, rm);
7544 if ((op & 0x50) == 0x10) {
7546 if (!arm_feature(env, ARM_FEATURE_DIV))
7549 gen_helper_udiv(tmp, tmp, tmp2);
7551 gen_helper_sdiv(tmp, tmp, tmp2);
7553 store_reg(s, rd, tmp);
7554 } else if ((op & 0xe) == 0xc) {
7555 /* Dual multiply accumulate long. */
7557 gen_swap_half(tmp2);
7558 gen_smul_dual(tmp, tmp2);
7560 tcg_gen_sub_i32(tmp, tmp, tmp2);
7562 tcg_gen_add_i32(tmp, tmp, tmp2);
7566 tmp64 = tcg_temp_new_i64();
7567 tcg_gen_ext_i32_i64(tmp64, tmp);
7569 gen_addq(s, tmp64, rs, rd);
7570 gen_storeq_reg(s, rs, rd, tmp64);
7573 /* Unsigned 64-bit multiply */
7574 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7578 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7580 tmp64 = tcg_temp_new_i64();
7581 tcg_gen_ext_i32_i64(tmp64, tmp);
7584 /* Signed 64-bit multiply */
7585 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7590 gen_addq_lo(s, tmp64, rs);
7591 gen_addq_lo(s, tmp64, rd);
7592 } else if (op & 0x40) {
7593 /* 64-bit accumulate. */
7594 gen_addq(s, tmp64, rs, rd);
7596 gen_storeq_reg(s, rs, rd, tmp64);
7601 case 6: case 7: case 14: case 15:
7603 if (((insn >> 24) & 3) == 3) {
7604 /* Translate into the equivalent ARM encoding. */
7605 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7606 if (disas_neon_data_insn(env, s, insn))
7609 if (insn & (1 << 28))
7611 if (disas_coproc_insn (env, s, insn))
7615 case 8: case 9: case 10: case 11:
7616 if (insn & (1 << 15)) {
7617 /* Branches, misc control. */
7618 if (insn & 0x5000) {
7619 /* Unconditional branch. */
7620 /* signextend(hw1[10:0]) -> offset[:12]. */
7621 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7622 /* hw1[10:0] -> offset[11:1]. */
7623 offset |= (insn & 0x7ff) << 1;
7624 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7625 offset[24:22] already have the same value because of the
7626 sign extension above. */
7627 offset ^= ((~insn) & (1 << 13)) << 10;
7628 offset ^= ((~insn) & (1 << 11)) << 11;
7630 if (insn & (1 << 14)) {
7631 /* Branch and link. */
7632 gen_op_movl_T1_im(s->pc | 1);
7633 gen_movl_reg_T1(s, 14);
7637 if (insn & (1 << 12)) {
7642 offset &= ~(uint32_t)2;
7643 gen_bx_im(s, offset);
7645 } else if (((insn >> 23) & 7) == 7) {
7647 if (insn & (1 << 13))
7650 if (insn & (1 << 26)) {
7651 /* Secure monitor call (v6Z) */
7652 goto illegal_op; /* not implemented. */
7654 op = (insn >> 20) & 7;
7656 case 0: /* msr cpsr. */
7658 tmp = load_reg(s, rn);
7659 addr = tcg_const_i32(insn & 0xff);
7660 gen_helper_v7m_msr(cpu_env, addr, tmp);
7665 case 1: /* msr spsr. */
7668 gen_movl_T0_reg(s, rn);
7669 if (gen_set_psr_T0(s,
7670 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7674 case 2: /* cps, nop-hint. */
7675 if (((insn >> 8) & 7) == 0) {
7676 gen_nop_hint(s, insn & 0xff);
7678 /* Implemented as NOP in user mode. */
7683 if (insn & (1 << 10)) {
7684 if (insn & (1 << 7))
7686 if (insn & (1 << 6))
7688 if (insn & (1 << 5))
7690 if (insn & (1 << 9))
7691 imm = CPSR_A | CPSR_I | CPSR_F;
7693 if (insn & (1 << 8)) {
7695 imm |= (insn & 0x1f);
7698 gen_op_movl_T0_im(imm);
7699 gen_set_psr_T0(s, offset, 0);
7702 case 3: /* Special control operations. */
7703 op = (insn >> 4) & 0xf;
7706 gen_helper_clrex(cpu_env);
7711 /* These execute as NOPs. */
7719 /* Trivial implementation equivalent to bx. */
7720 tmp = load_reg(s, rn);
7723 case 5: /* Exception return. */
7724 /* Unpredictable in user mode. */
7726 case 6: /* mrs cpsr. */
7729 addr = tcg_const_i32(insn & 0xff);
7730 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7732 gen_helper_cpsr_read(tmp);
7734 store_reg(s, rd, tmp);
7736 case 7: /* mrs spsr. */
7737 /* Not accessible in user mode. */
7738 if (IS_USER(s) || IS_M(env))
7740 tmp = load_cpu_field(spsr);
7741 store_reg(s, rd, tmp);
7746 /* Conditional branch. */
7747 op = (insn >> 22) & 0xf;
7748 /* Generate a conditional jump to next instruction. */
7749 s->condlabel = gen_new_label();
7750 gen_test_cc(op ^ 1, s->condlabel);
7753 /* offset[11:1] = insn[10:0] */
7754 offset = (insn & 0x7ff) << 1;
7755 /* offset[17:12] = insn[21:16]. */
7756 offset |= (insn & 0x003f0000) >> 4;
7757 /* offset[31:20] = insn[26]. */
7758 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7759 /* offset[18] = insn[13]. */
7760 offset |= (insn & (1 << 13)) << 5;
7761 /* offset[19] = insn[11]. */
7762 offset |= (insn & (1 << 11)) << 8;
7764 /* jump to the offset */
7765 gen_jmp(s, s->pc + offset);
7768 /* Data processing immediate. */
7769 if (insn & (1 << 25)) {
7770 if (insn & (1 << 24)) {
7771 if (insn & (1 << 20))
7773 /* Bitfield/Saturate. */
7774 op = (insn >> 21) & 7;
7776 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7779 tcg_gen_movi_i32(tmp, 0);
7781 tmp = load_reg(s, rn);
7784 case 2: /* Signed bitfield extract. */
7786 if (shift + imm > 32)
7789 gen_sbfx(tmp, shift, imm);
7791 case 6: /* Unsigned bitfield extract. */
7793 if (shift + imm > 32)
7796 gen_ubfx(tmp, shift, (1u << imm) - 1);
7798 case 3: /* Bitfield insert/clear. */
7801 imm = imm + 1 - shift;
7803 tmp2 = load_reg(s, rd);
7804 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7810 default: /* Saturate. */
7813 tcg_gen_sari_i32(tmp, tmp, shift);
7815 tcg_gen_shli_i32(tmp, tmp, shift);
7817 tmp2 = tcg_const_i32(imm);
7820 if ((op & 1) && shift == 0)
7821 gen_helper_usat16(tmp, tmp, tmp2);
7823 gen_helper_usat(tmp, tmp, tmp2);
7826 if ((op & 1) && shift == 0)
7827 gen_helper_ssat16(tmp, tmp, tmp2);
7829 gen_helper_ssat(tmp, tmp, tmp2);
7833 store_reg(s, rd, tmp);
7835 imm = ((insn & 0x04000000) >> 15)
7836 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7837 if (insn & (1 << 22)) {
7838 /* 16-bit immediate. */
7839 imm |= (insn >> 4) & 0xf000;
7840 if (insn & (1 << 23)) {
7842 tmp = load_reg(s, rd);
7843 tcg_gen_ext16u_i32(tmp, tmp);
7844 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7848 tcg_gen_movi_i32(tmp, imm);
7851 /* Add/sub 12-bit immediate. */
7853 offset = s->pc & ~(uint32_t)3;
7854 if (insn & (1 << 23))
7859 tcg_gen_movi_i32(tmp, offset);
7861 tmp = load_reg(s, rn);
7862 if (insn & (1 << 23))
7863 tcg_gen_subi_i32(tmp, tmp, imm);
7865 tcg_gen_addi_i32(tmp, tmp, imm);
7868 store_reg(s, rd, tmp);
7871 int shifter_out = 0;
7872 /* modified 12-bit immediate. */
7873 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7874 imm = (insn & 0xff);
7877 /* Nothing to do. */
7879 case 1: /* 00XY00XY */
7882 case 2: /* XY00XY00 */
7886 case 3: /* XYXYXYXY */
7890 default: /* Rotated constant. */
7891 shift = (shift << 1) | (imm >> 7);
7893 imm = imm << (32 - shift);
7897 gen_op_movl_T1_im(imm);
7898 rn = (insn >> 16) & 0xf;
7900 gen_op_movl_T0_im(0);
7902 gen_movl_T0_reg(s, rn);
7903 op = (insn >> 21) & 0xf;
7904 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7907 rd = (insn >> 8) & 0xf;
7909 gen_movl_reg_T0(s, rd);
7914 case 12: /* Load/store single data item. */
7919 if ((insn & 0x01100000) == 0x01000000) {
7920 if (disas_neon_ls_insn(env, s, insn))
7928 /* s->pc has already been incremented by 4. */
7929 imm = s->pc & 0xfffffffc;
7930 if (insn & (1 << 23))
7931 imm += insn & 0xfff;
7933 imm -= insn & 0xfff;
7934 tcg_gen_movi_i32(addr, imm);
7936 addr = load_reg(s, rn);
7937 if (insn & (1 << 23)) {
7938 /* Positive offset. */
7940 tcg_gen_addi_i32(addr, addr, imm);
7942 op = (insn >> 8) & 7;
7945 case 0: case 8: /* Shifted Register. */
7946 shift = (insn >> 4) & 0xf;
7949 tmp = load_reg(s, rm);
7951 tcg_gen_shli_i32(tmp, tmp, shift);
7952 tcg_gen_add_i32(addr, addr, tmp);
7955 case 4: /* Negative offset. */
7956 tcg_gen_addi_i32(addr, addr, -imm);
7958 case 6: /* User privilege. */
7959 tcg_gen_addi_i32(addr, addr, imm);
7962 case 1: /* Post-decrement. */
7965 case 3: /* Post-increment. */
7969 case 5: /* Pre-decrement. */
7972 case 7: /* Pre-increment. */
7973 tcg_gen_addi_i32(addr, addr, imm);
7981 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7982 if (insn & (1 << 20)) {
7984 if (rs == 15 && op != 2) {
7987 /* Memory hint. Implemented as NOP. */
7990 case 0: tmp = gen_ld8u(addr, user); break;
7991 case 4: tmp = gen_ld8s(addr, user); break;
7992 case 1: tmp = gen_ld16u(addr, user); break;
7993 case 5: tmp = gen_ld16s(addr, user); break;
7994 case 2: tmp = gen_ld32(addr, user); break;
7995 default: goto illegal_op;
8000 store_reg(s, rs, tmp);
8007 tmp = load_reg(s, rs);
8009 case 0: gen_st8(tmp, addr, user); break;
8010 case 1: gen_st16(tmp, addr, user); break;
8011 case 2: gen_st32(tmp, addr, user); break;
8012 default: goto illegal_op;
8016 tcg_gen_addi_i32(addr, addr, imm);
8018 store_reg(s, rn, addr);
8032 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8034 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8041 if (s->condexec_mask) {
8042 cond = s->condexec_cond;
8043 s->condlabel = gen_new_label();
8044 gen_test_cc(cond ^ 1, s->condlabel);
8048 insn = lduw_code(s->pc);
8051 switch (insn >> 12) {
8054 op = (insn >> 11) & 3;
8057 rn = (insn >> 3) & 7;
8058 gen_movl_T0_reg(s, rn);
8059 if (insn & (1 << 10)) {
8061 gen_op_movl_T1_im((insn >> 6) & 7);
8064 rm = (insn >> 6) & 7;
8065 gen_movl_T1_reg(s, rm);
8067 if (insn & (1 << 9)) {
8068 if (s->condexec_mask)
8069 gen_op_subl_T0_T1();
8071 gen_op_subl_T0_T1_cc();
8073 if (s->condexec_mask)
8074 gen_op_addl_T0_T1();
8076 gen_op_addl_T0_T1_cc();
8078 gen_movl_reg_T0(s, rd);
8080 /* shift immediate */
8081 rm = (insn >> 3) & 7;
8082 shift = (insn >> 6) & 0x1f;
8083 tmp = load_reg(s, rm);
8084 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8085 if (!s->condexec_mask)
8087 store_reg(s, rd, tmp);
8091 /* arithmetic large immediate */
8092 op = (insn >> 11) & 3;
8093 rd = (insn >> 8) & 0x7;
8095 gen_op_movl_T0_im(insn & 0xff);
8097 gen_movl_T0_reg(s, rd);
8098 gen_op_movl_T1_im(insn & 0xff);
8102 if (!s->condexec_mask)
8103 gen_op_logic_T0_cc();
8106 gen_op_subl_T0_T1_cc();
8109 if (s->condexec_mask)
8110 gen_op_addl_T0_T1();
8112 gen_op_addl_T0_T1_cc();
8115 if (s->condexec_mask)
8116 gen_op_subl_T0_T1();
8118 gen_op_subl_T0_T1_cc();
8122 gen_movl_reg_T0(s, rd);
8125 if (insn & (1 << 11)) {
8126 rd = (insn >> 8) & 7;
8127 /* load pc-relative. Bit 1 of PC is ignored. */
8128 val = s->pc + 2 + ((insn & 0xff) * 4);
8129 val &= ~(uint32_t)2;
8131 tcg_gen_movi_i32(addr, val);
8132 tmp = gen_ld32(addr, IS_USER(s));
8134 store_reg(s, rd, tmp);
8137 if (insn & (1 << 10)) {
8138 /* data processing extended or blx */
8139 rd = (insn & 7) | ((insn >> 4) & 8);
8140 rm = (insn >> 3) & 0xf;
8141 op = (insn >> 8) & 3;
8144 gen_movl_T0_reg(s, rd);
8145 gen_movl_T1_reg(s, rm);
8146 gen_op_addl_T0_T1();
8147 gen_movl_reg_T0(s, rd);
8150 gen_movl_T0_reg(s, rd);
8151 gen_movl_T1_reg(s, rm);
8152 gen_op_subl_T0_T1_cc();
8154 case 2: /* mov/cpy */
8155 gen_movl_T0_reg(s, rm);
8156 gen_movl_reg_T0(s, rd);
8158 case 3:/* branch [and link] exchange thumb register */
8159 tmp = load_reg(s, rm);
8160 if (insn & (1 << 7)) {
8161 val = (uint32_t)s->pc | 1;
8163 tcg_gen_movi_i32(tmp2, val);
8164 store_reg(s, 14, tmp2);
8172 /* data processing register */
8174 rm = (insn >> 3) & 7;
8175 op = (insn >> 6) & 0xf;
8176 if (op == 2 || op == 3 || op == 4 || op == 7) {
8177 /* the shift/rotate ops want the operands backwards */
8186 if (op == 9) /* neg */
8187 gen_op_movl_T0_im(0);
8188 else if (op != 0xf) /* mvn doesn't read its first operand */
8189 gen_movl_T0_reg(s, rd);
8191 gen_movl_T1_reg(s, rm);
8194 gen_op_andl_T0_T1();
8195 if (!s->condexec_mask)
8196 gen_op_logic_T0_cc();
8199 gen_op_xorl_T0_T1();
8200 if (!s->condexec_mask)
8201 gen_op_logic_T0_cc();
8204 if (s->condexec_mask) {
8205 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8207 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8208 gen_op_logic_T1_cc();
8212 if (s->condexec_mask) {
8213 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8215 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8216 gen_op_logic_T1_cc();
8220 if (s->condexec_mask) {
8221 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8223 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8224 gen_op_logic_T1_cc();
8228 if (s->condexec_mask)
8231 gen_op_adcl_T0_T1_cc();
8234 if (s->condexec_mask)
8237 gen_op_sbcl_T0_T1_cc();
8240 if (s->condexec_mask) {
8241 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8243 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8244 gen_op_logic_T1_cc();
8248 gen_op_andl_T0_T1();
8249 gen_op_logic_T0_cc();
8253 if (s->condexec_mask)
8254 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
8256 gen_op_subl_T0_T1_cc();
8259 gen_op_subl_T0_T1_cc();
8263 gen_op_addl_T0_T1_cc();
8268 if (!s->condexec_mask)
8269 gen_op_logic_T0_cc();
8272 gen_op_mull_T0_T1();
8273 if (!s->condexec_mask)
8274 gen_op_logic_T0_cc();
8277 gen_op_bicl_T0_T1();
8278 if (!s->condexec_mask)
8279 gen_op_logic_T0_cc();
8283 if (!s->condexec_mask)
8284 gen_op_logic_T1_cc();
8291 gen_movl_reg_T1(s, rm);
8293 gen_movl_reg_T0(s, rd);
8298 /* load/store register offset. */
8300 rn = (insn >> 3) & 7;
8301 rm = (insn >> 6) & 7;
8302 op = (insn >> 9) & 7;
8303 addr = load_reg(s, rn);
8304 tmp = load_reg(s, rm);
8305 tcg_gen_add_i32(addr, addr, tmp);
8308 if (op < 3) /* store */
8309 tmp = load_reg(s, rd);
8313 gen_st32(tmp, addr, IS_USER(s));
8316 gen_st16(tmp, addr, IS_USER(s));
8319 gen_st8(tmp, addr, IS_USER(s));
8322 tmp = gen_ld8s(addr, IS_USER(s));
8325 tmp = gen_ld32(addr, IS_USER(s));
8328 tmp = gen_ld16u(addr, IS_USER(s));
8331 tmp = gen_ld8u(addr, IS_USER(s));
8334 tmp = gen_ld16s(addr, IS_USER(s));
8337 if (op >= 3) /* load */
8338 store_reg(s, rd, tmp);
8343 /* load/store word immediate offset */
8345 rn = (insn >> 3) & 7;
8346 addr = load_reg(s, rn);
8347 val = (insn >> 4) & 0x7c;
8348 tcg_gen_addi_i32(addr, addr, val);
8350 if (insn & (1 << 11)) {
8352 tmp = gen_ld32(addr, IS_USER(s));
8353 store_reg(s, rd, tmp);
8356 tmp = load_reg(s, rd);
8357 gen_st32(tmp, addr, IS_USER(s));
8363 /* load/store byte immediate offset */
8365 rn = (insn >> 3) & 7;
8366 addr = load_reg(s, rn);
8367 val = (insn >> 6) & 0x1f;
8368 tcg_gen_addi_i32(addr, addr, val);
8370 if (insn & (1 << 11)) {
8372 tmp = gen_ld8u(addr, IS_USER(s));
8373 store_reg(s, rd, tmp);
8376 tmp = load_reg(s, rd);
8377 gen_st8(tmp, addr, IS_USER(s));
8383 /* load/store halfword immediate offset */
8385 rn = (insn >> 3) & 7;
8386 addr = load_reg(s, rn);
8387 val = (insn >> 5) & 0x3e;
8388 tcg_gen_addi_i32(addr, addr, val);
8390 if (insn & (1 << 11)) {
8392 tmp = gen_ld16u(addr, IS_USER(s));
8393 store_reg(s, rd, tmp);
8396 tmp = load_reg(s, rd);
8397 gen_st16(tmp, addr, IS_USER(s));
8403 /* load/store from stack */
8404 rd = (insn >> 8) & 7;
8405 addr = load_reg(s, 13);
8406 val = (insn & 0xff) * 4;
8407 tcg_gen_addi_i32(addr, addr, val);
8409 if (insn & (1 << 11)) {
8411 tmp = gen_ld32(addr, IS_USER(s));
8412 store_reg(s, rd, tmp);
8415 tmp = load_reg(s, rd);
8416 gen_st32(tmp, addr, IS_USER(s));
8422 /* add to high reg */
8423 rd = (insn >> 8) & 7;
8424 if (insn & (1 << 11)) {
8426 tmp = load_reg(s, 13);
8428 /* PC. bit 1 is ignored. */
8430 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8432 val = (insn & 0xff) * 4;
8433 tcg_gen_addi_i32(tmp, tmp, val);
8434 store_reg(s, rd, tmp);
8439 op = (insn >> 8) & 0xf;
8442 /* adjust stack pointer */
8443 tmp = load_reg(s, 13);
8444 val = (insn & 0x7f) * 4;
8445 if (insn & (1 << 7))
8446 val = -(int32_t)val;
8447 tcg_gen_addi_i32(tmp, tmp, val);
8448 store_reg(s, 13, tmp);
8451 case 2: /* sign/zero extend. */
8454 rm = (insn >> 3) & 7;
8455 tmp = load_reg(s, rm);
8456 switch ((insn >> 6) & 3) {
8457 case 0: gen_sxth(tmp); break;
8458 case 1: gen_sxtb(tmp); break;
8459 case 2: gen_uxth(tmp); break;
8460 case 3: gen_uxtb(tmp); break;
8462 store_reg(s, rd, tmp);
8464 case 4: case 5: case 0xc: case 0xd:
8466 addr = load_reg(s, 13);
8467 if (insn & (1 << 8))
8471 for (i = 0; i < 8; i++) {
8472 if (insn & (1 << i))
8475 if ((insn & (1 << 11)) == 0) {
8476 tcg_gen_addi_i32(addr, addr, -offset);
8478 for (i = 0; i < 8; i++) {
8479 if (insn & (1 << i)) {
8480 if (insn & (1 << 11)) {
8482 tmp = gen_ld32(addr, IS_USER(s));
8483 store_reg(s, i, tmp);
8486 tmp = load_reg(s, i);
8487 gen_st32(tmp, addr, IS_USER(s));
8489 /* advance to the next address. */
8490 tcg_gen_addi_i32(addr, addr, 4);
8494 if (insn & (1 << 8)) {
8495 if (insn & (1 << 11)) {
8497 tmp = gen_ld32(addr, IS_USER(s));
8498 /* don't set the pc until the rest of the instruction
8502 tmp = load_reg(s, 14);
8503 gen_st32(tmp, addr, IS_USER(s));
8505 tcg_gen_addi_i32(addr, addr, 4);
8507 if ((insn & (1 << 11)) == 0) {
8508 tcg_gen_addi_i32(addr, addr, -offset);
8510 /* write back the new stack pointer */
8511 store_reg(s, 13, addr);
8512 /* set the new PC value */
8513 if ((insn & 0x0900) == 0x0900)
8517 case 1: case 3: case 9: case 11: /* czb */
8519 tmp = load_reg(s, rm);
8520 s->condlabel = gen_new_label();
8522 if (insn & (1 << 11))
8523 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8525 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8527 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8528 val = (uint32_t)s->pc + 2;
8533 case 15: /* IT, nop-hint. */
8534 if ((insn & 0xf) == 0) {
8535 gen_nop_hint(s, (insn >> 4) & 0xf);
8539 s->condexec_cond = (insn >> 4) & 0xe;
8540 s->condexec_mask = insn & 0x1f;
8541 /* No actual code generated for this insn, just setup state. */
8544 case 0xe: /* bkpt */
8545 gen_set_condexec(s);
8546 gen_set_pc_im(s->pc - 2);
8547 gen_exception(EXCP_BKPT);
8548 s->is_jmp = DISAS_JUMP;
8553 rn = (insn >> 3) & 0x7;
8555 tmp = load_reg(s, rn);
8556 switch ((insn >> 6) & 3) {
8557 case 0: tcg_gen_bswap_i32(tmp, tmp); break;
8558 case 1: gen_rev16(tmp); break;
8559 case 3: gen_revsh(tmp); break;
8560 default: goto illegal_op;
8562 store_reg(s, rd, tmp);
8570 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8573 addr = tcg_const_i32(16);
8574 gen_helper_v7m_msr(cpu_env, addr, tmp);
8578 addr = tcg_const_i32(17);
8579 gen_helper_v7m_msr(cpu_env, addr, tmp);
8583 if (insn & (1 << 4))
8584 shift = CPSR_A | CPSR_I | CPSR_F;
8588 val = ((insn & 7) << 6) & shift;
8589 gen_op_movl_T0_im(val);
8590 gen_set_psr_T0(s, shift, 0);
8600 /* load/store multiple */
8601 rn = (insn >> 8) & 0x7;
8602 addr = load_reg(s, rn);
8603 for (i = 0; i < 8; i++) {
8604 if (insn & (1 << i)) {
8605 if (insn & (1 << 11)) {
8607 tmp = gen_ld32(addr, IS_USER(s));
8608 store_reg(s, i, tmp);
8611 tmp = load_reg(s, i);
8612 gen_st32(tmp, addr, IS_USER(s));
8614 /* advance to the next address */
8615 tcg_gen_addi_i32(addr, addr, 4);
8618 /* Base register writeback. */
8619 if ((insn & (1 << rn)) == 0) {
8620 store_reg(s, rn, addr);
8627 /* conditional branch or swi */
8628 cond = (insn >> 8) & 0xf;
8634 gen_set_condexec(s);
8635 gen_set_pc_im(s->pc);
8636 s->is_jmp = DISAS_SWI;
8639 /* generate a conditional jump to next instruction */
8640 s->condlabel = gen_new_label();
8641 gen_test_cc(cond ^ 1, s->condlabel);
8643 gen_movl_T1_reg(s, 15);
8645 /* jump to the offset */
8646 val = (uint32_t)s->pc + 2;
8647 offset = ((int32_t)insn << 24) >> 24;
8653 if (insn & (1 << 11)) {
8654 if (disas_thumb2_insn(env, s, insn))
8658 /* unconditional branch */
8659 val = (uint32_t)s->pc;
8660 offset = ((int32_t)insn << 21) >> 21;
8661 val += (offset << 1) + 2;
8666 if (disas_thumb2_insn(env, s, insn))
8672 gen_set_condexec(s);
8673 gen_set_pc_im(s->pc - 4);
8674 gen_exception(EXCP_UDEF);
8675 s->is_jmp = DISAS_JUMP;
8679 gen_set_condexec(s);
8680 gen_set_pc_im(s->pc - 2);
8681 gen_exception(EXCP_UDEF);
8682 s->is_jmp = DISAS_JUMP;
8685 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8686 basic block 'tb'. If search_pc is TRUE, also generate PC
8687 information for each intermediate instruction. */
8688 static inline void gen_intermediate_code_internal(CPUState *env,
8689 TranslationBlock *tb,
8692 DisasContext dc1, *dc = &dc1;
8694 uint16_t *gen_opc_end;
8696 target_ulong pc_start;
8697 uint32_t next_page_start;
8701 /* generate intermediate code */
8703 memset(temps, 0, sizeof(temps));
8709 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8711 dc->is_jmp = DISAS_NEXT;
8713 dc->singlestep_enabled = env->singlestep_enabled;
8715 dc->thumb = env->thumb;
8716 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8717 dc->condexec_cond = env->condexec_bits >> 4;
8718 #if !defined(CONFIG_USER_ONLY)
8720 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8722 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8725 cpu_F0s = tcg_temp_new_i32();
8726 cpu_F1s = tcg_temp_new_i32();
8727 cpu_F0d = tcg_temp_new_i64();
8728 cpu_F1d = tcg_temp_new_i64();
8731 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8732 cpu_M0 = tcg_temp_new_i64();
8733 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8736 max_insns = tb->cflags & CF_COUNT_MASK;
8738 max_insns = CF_COUNT_MASK;
8741 /* Reset the conditional execution bits immediately. This avoids
8742 complications trying to do it at the end of the block. */
8743 if (env->condexec_bits)
8745 TCGv tmp = new_tmp();
8746 tcg_gen_movi_i32(tmp, 0);
8747 store_cpu_field(tmp, condexec_bits);
8750 #ifdef CONFIG_USER_ONLY
8751 /* Intercept jump to the magic kernel page. */
8752 if (dc->pc >= 0xffff0000) {
8753 /* We always get here via a jump, so know we are not in a
8754 conditional execution block. */
8755 gen_exception(EXCP_KERNEL_TRAP);
8756 dc->is_jmp = DISAS_UPDATE;
8760 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8761 /* We always get here via a jump, so know we are not in a
8762 conditional execution block. */
8763 gen_exception(EXCP_EXCEPTION_EXIT);
8764 dc->is_jmp = DISAS_UPDATE;
8769 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8770 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8771 if (bp->pc == dc->pc) {
8772 gen_set_condexec(dc);
8773 gen_set_pc_im(dc->pc);
8774 gen_exception(EXCP_DEBUG);
8775 dc->is_jmp = DISAS_JUMP;
8776 /* Advance PC so that clearing the breakpoint will
8777 invalidate this TB. */
8779 goto done_generating;
8785 j = gen_opc_ptr - gen_opc_buf;
8789 gen_opc_instr_start[lj++] = 0;
8791 gen_opc_pc[lj] = dc->pc;
8792 gen_opc_instr_start[lj] = 1;
8793 gen_opc_icount[lj] = num_insns;
8796 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8800 disas_thumb_insn(env, dc);
8801 if (dc->condexec_mask) {
8802 dc->condexec_cond = (dc->condexec_cond & 0xe)
8803 | ((dc->condexec_mask >> 4) & 1);
8804 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8805 if (dc->condexec_mask == 0) {
8806 dc->condexec_cond = 0;
8810 disas_arm_insn(env, dc);
8813 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8817 if (dc->condjmp && !dc->is_jmp) {
8818 gen_set_label(dc->condlabel);
8821 /* Translation stops when a conditional branch is encountered.
8822 * Otherwise the subsequent code could get translated several times.
8823 * Also stop translation when a page boundary is reached. This
8824 * ensures prefetch aborts occur at the right place. */
8826 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8827 !env->singlestep_enabled &&
8828 dc->pc < next_page_start &&
8829 num_insns < max_insns);
8831 if (tb->cflags & CF_LAST_IO) {
8833 /* FIXME: This can theoretically happen with self-modifying
8835 cpu_abort(env, "IO on conditional branch instruction");
8840 /* At this stage dc->condjmp will only be set when the skipped
8841 instruction was a conditional branch or trap, and the PC has
8842 already been written. */
8843 if (unlikely(env->singlestep_enabled)) {
8844 /* Make sure the pc is updated, and raise a debug exception. */
8846 gen_set_condexec(dc);
8847 if (dc->is_jmp == DISAS_SWI) {
8848 gen_exception(EXCP_SWI);
8850 gen_exception(EXCP_DEBUG);
8852 gen_set_label(dc->condlabel);
8854 if (dc->condjmp || !dc->is_jmp) {
8855 gen_set_pc_im(dc->pc);
8858 gen_set_condexec(dc);
8859 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8860 gen_exception(EXCP_SWI);
8862 /* FIXME: Single stepping a WFI insn will not halt
8864 gen_exception(EXCP_DEBUG);
8867 /* While branches must always occur at the end of an IT block,
8868 there are a few other things that can cause us to terminate
8869 the TB in the middel of an IT block:
8870 - Exception generating instructions (bkpt, swi, undefined).
8872 - Hardware watchpoints.
8873 Hardware breakpoints have already been handled and skip this code.
8875 gen_set_condexec(dc);
8876 switch(dc->is_jmp) {
8878 gen_goto_tb(dc, 1, dc->pc);
8883 /* indicate that the hash table must be used to find the next TB */
8887 /* nothing more to generate */
8893 gen_exception(EXCP_SWI);
8897 gen_set_label(dc->condlabel);
8898 gen_set_condexec(dc);
8899 gen_goto_tb(dc, 1, dc->pc);
8905 gen_icount_end(tb, num_insns);
8906 *gen_opc_ptr = INDEX_op_end;
8909 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8910 qemu_log("----------------\n");
8911 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8912 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8917 j = gen_opc_ptr - gen_opc_buf;
8920 gen_opc_instr_start[lj++] = 0;
8922 tb->size = dc->pc - pc_start;
8923 tb->icount = num_insns;
8927 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8929 gen_intermediate_code_internal(env, tb, 0);
8932 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8934 gen_intermediate_code_internal(env, tb, 1);
8937 static const char *cpu_mode_names[16] = {
8938 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8939 "???", "???", "???", "und", "???", "???", "???", "sys"
8942 void cpu_dump_state(CPUState *env, FILE *f,
8943 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8953 /* ??? This assumes float64 and double have the same layout.
8954 Oh well, it's only debug dumps. */
8963 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8965 cpu_fprintf(f, "\n");
8967 cpu_fprintf(f, " ");
8969 psr = cpsr_read(env);
8970 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8972 psr & (1 << 31) ? 'N' : '-',
8973 psr & (1 << 30) ? 'Z' : '-',
8974 psr & (1 << 29) ? 'C' : '-',
8975 psr & (1 << 28) ? 'V' : '-',
8976 psr & CPSR_T ? 'T' : 'A',
8977 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8980 for (i = 0; i < 16; i++) {
8981 d.d = env->vfp.regs[i];
8985 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8986 i * 2, (int)s0.i, s0.s,
8987 i * 2 + 1, (int)s1.i, s1.s,
8988 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
8991 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
8995 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8996 unsigned long searched_pc, int pc_pos, void *puc)
8998 env->regs[15] = gen_opc_pc[pc_pos];