]>
git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
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, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
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 static const char *regnames
[] =
89 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
92 /* initialize TCG globals. */
93 void arm_translate_init(void)
97 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
99 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
100 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
102 for (i
= 0; i
< 16; i
++) {
103 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
104 offsetof(CPUState
, regs
[i
]),
112 static int num_temps
;
114 /* Allocate a temporary variable. */
115 static TCGv_i32
new_tmp(void)
118 return tcg_temp_new_i32();
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp
)
128 static inline TCGv
load_cpu_offset(int offset
)
130 TCGv tmp
= new_tmp();
131 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
135 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
137 static inline void store_cpu_offset(TCGv var
, int offset
)
139 tcg_gen_st_i32(var
, cpu_env
, offset
);
143 #define store_cpu_field(var, name) \
144 store_cpu_offset(var, offsetof(CPUState, name))
146 /* Set a variable to the value of a CPU register. */
147 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
151 /* normaly, since we updated PC, we need only to add one insn */
153 addr
= (long)s
->pc
+ 2;
155 addr
= (long)s
->pc
+ 4;
156 tcg_gen_movi_i32(var
, addr
);
158 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
162 /* Create a new temporary and set it to the value of a CPU register. */
163 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
165 TCGv tmp
= new_tmp();
166 load_reg_var(s
, tmp
, reg
);
170 /* Set a CPU register. The source must be a temporary and will be
172 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
175 tcg_gen_andi_i32(var
, var
, ~1);
176 s
->is_jmp
= DISAS_JUMP
;
178 tcg_gen_mov_i32(cpu_R
[reg
], var
);
183 /* Basic operations. */
184 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
185 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
188 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
191 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
192 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
193 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
195 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
196 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
198 /* Value extensions. */
199 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
200 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
201 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
202 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
204 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
205 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
208 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
209 /* Set NZCV flags from the high 4 bits of var. */
210 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
212 static void gen_exception(int excp
)
214 TCGv tmp
= new_tmp();
215 tcg_gen_movi_i32(tmp
, excp
);
216 gen_helper_exception(tmp
);
220 static void gen_smul_dual(TCGv a
, TCGv b
)
222 TCGv tmp1
= new_tmp();
223 TCGv tmp2
= new_tmp();
224 tcg_gen_ext16s_i32(tmp1
, a
);
225 tcg_gen_ext16s_i32(tmp2
, b
);
226 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
228 tcg_gen_sari_i32(a
, a
, 16);
229 tcg_gen_sari_i32(b
, b
, 16);
230 tcg_gen_mul_i32(b
, b
, a
);
231 tcg_gen_mov_i32(a
, tmp1
);
235 /* Byteswap each halfword. */
236 static void gen_rev16(TCGv var
)
238 TCGv tmp
= new_tmp();
239 tcg_gen_shri_i32(tmp
, var
, 8);
240 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
241 tcg_gen_shli_i32(var
, var
, 8);
242 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
243 tcg_gen_or_i32(var
, var
, tmp
);
247 /* Byteswap low halfword and sign extend. */
248 static void gen_revsh(TCGv var
)
250 TCGv tmp
= new_tmp();
251 tcg_gen_shri_i32(tmp
, var
, 8);
252 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
253 tcg_gen_shli_i32(var
, var
, 8);
254 tcg_gen_ext8s_i32(var
, var
);
255 tcg_gen_or_i32(var
, var
, tmp
);
259 /* Unsigned bitfield extract. */
260 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
263 tcg_gen_shri_i32(var
, var
, shift
);
264 tcg_gen_andi_i32(var
, var
, mask
);
267 /* Signed bitfield extract. */
268 static void gen_sbfx(TCGv var
, int shift
, int width
)
273 tcg_gen_sari_i32(var
, var
, shift
);
274 if (shift
+ width
< 32) {
275 signbit
= 1u << (width
- 1);
276 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
277 tcg_gen_xori_i32(var
, var
, signbit
);
278 tcg_gen_subi_i32(var
, var
, signbit
);
282 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
283 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
285 tcg_gen_andi_i32(val
, val
, mask
);
286 tcg_gen_shli_i32(val
, val
, shift
);
287 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
288 tcg_gen_or_i32(dest
, base
, val
);
291 /* Round the top 32 bits of a 64-bit value. */
292 static void gen_roundqd(TCGv a
, TCGv b
)
294 tcg_gen_shri_i32(a
, a
, 31);
295 tcg_gen_add_i32(a
, a
, b
);
298 /* FIXME: Most targets have native widening multiplication.
299 It would be good to use that instead of a full wide multiply. */
300 /* 32x32->64 multiply. Marks inputs as dead. */
301 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
303 TCGv_i64 tmp1
= tcg_temp_new_i64();
304 TCGv_i64 tmp2
= tcg_temp_new_i64();
306 tcg_gen_extu_i32_i64(tmp1
, a
);
308 tcg_gen_extu_i32_i64(tmp2
, b
);
310 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
314 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1
, a
);
321 tcg_gen_ext_i32_i64(tmp2
, b
);
323 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
327 /* Unsigned 32x32->64 multiply. */
328 static void gen_mull(TCGv a
, TCGv b
)
330 TCGv_i64 tmp1
= tcg_temp_new_i64();
331 TCGv_i64 tmp2
= tcg_temp_new_i64();
333 tcg_gen_extu_i32_i64(tmp1
, a
);
334 tcg_gen_extu_i32_i64(tmp2
, b
);
335 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
336 tcg_gen_trunc_i64_i32(a
, tmp1
);
337 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
338 tcg_gen_trunc_i64_i32(b
, tmp1
);
341 /* Signed 32x32->64 multiply. */
342 static void gen_imull(TCGv a
, TCGv b
)
344 TCGv_i64 tmp1
= tcg_temp_new_i64();
345 TCGv_i64 tmp2
= tcg_temp_new_i64();
347 tcg_gen_ext_i32_i64(tmp1
, a
);
348 tcg_gen_ext_i32_i64(tmp2
, b
);
349 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
350 tcg_gen_trunc_i64_i32(a
, tmp1
);
351 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
352 tcg_gen_trunc_i64_i32(b
, tmp1
);
355 /* Swap low and high halfwords. */
356 static void gen_swap_half(TCGv var
)
358 TCGv tmp
= new_tmp();
359 tcg_gen_shri_i32(tmp
, var
, 16);
360 tcg_gen_shli_i32(var
, var
, 16);
361 tcg_gen_or_i32(var
, var
, tmp
);
365 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
366 tmp = (t0 ^ t1) & 0x8000;
369 t0 = (t0 + t1) ^ tmp;
372 static void gen_add16(TCGv t0
, TCGv t1
)
374 TCGv tmp
= new_tmp();
375 tcg_gen_xor_i32(tmp
, t0
, t1
);
376 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
377 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
378 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
379 tcg_gen_add_i32(t0
, t0
, t1
);
380 tcg_gen_xor_i32(t0
, t0
, tmp
);
385 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
387 /* Set CF to the top bit of var. */
388 static void gen_set_CF_bit31(TCGv var
)
390 TCGv tmp
= new_tmp();
391 tcg_gen_shri_i32(tmp
, var
, 31);
396 /* Set N and Z flags from var. */
397 static inline void gen_logic_CC(TCGv var
)
399 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
400 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
404 static void gen_adc(TCGv t0
, TCGv t1
)
407 tcg_gen_add_i32(t0
, t0
, t1
);
408 tmp
= load_cpu_field(CF
);
409 tcg_gen_add_i32(t0
, t0
, tmp
);
413 /* dest = T0 + T1 + CF. */
414 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
417 tcg_gen_add_i32(dest
, t0
, t1
);
418 tmp
= load_cpu_field(CF
);
419 tcg_gen_add_i32(dest
, dest
, tmp
);
423 /* dest = T0 - T1 + CF - 1. */
424 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
427 tcg_gen_sub_i32(dest
, t0
, t1
);
428 tmp
= load_cpu_field(CF
);
429 tcg_gen_add_i32(dest
, dest
, tmp
);
430 tcg_gen_subi_i32(dest
, dest
, 1);
434 /* T0 &= ~T1. Clobbers T1. */
435 /* FIXME: Implement bic natively. */
436 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
438 TCGv tmp
= new_tmp();
439 tcg_gen_not_i32(tmp
, t1
);
440 tcg_gen_and_i32(dest
, t0
, tmp
);
443 static inline void gen_op_bicl_T0_T1(void)
449 /* FIXME: Implement this natively. */
450 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
452 /* FIXME: Implement this natively. */
453 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
461 tcg_gen_shri_i32(tmp
, t1
, i
);
462 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
463 tcg_gen_or_i32(t0
, t1
, tmp
);
467 static void shifter_out_im(TCGv var
, int shift
)
469 TCGv tmp
= new_tmp();
471 tcg_gen_andi_i32(tmp
, var
, 1);
473 tcg_gen_shri_i32(tmp
, var
, shift
);
475 tcg_gen_andi_i32(tmp
, tmp
, 1);
481 /* Shift by immediate. Includes special handling for shift == 0. */
482 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
488 shifter_out_im(var
, 32 - shift
);
489 tcg_gen_shli_i32(var
, var
, shift
);
495 tcg_gen_shri_i32(var
, var
, 31);
498 tcg_gen_movi_i32(var
, 0);
501 shifter_out_im(var
, shift
- 1);
502 tcg_gen_shri_i32(var
, var
, shift
);
509 shifter_out_im(var
, shift
- 1);
512 tcg_gen_sari_i32(var
, var
, shift
);
514 case 3: /* ROR/RRX */
517 shifter_out_im(var
, shift
- 1);
518 tcg_gen_rori_i32(var
, var
, shift
); break;
520 TCGv tmp
= load_cpu_field(CF
);
522 shifter_out_im(var
, 0);
523 tcg_gen_shri_i32(var
, var
, 1);
524 tcg_gen_shli_i32(tmp
, tmp
, 31);
525 tcg_gen_or_i32(var
, var
, tmp
);
531 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
532 TCGv shift
, int flags
)
536 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
537 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
538 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
539 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
543 case 0: gen_helper_shl(var
, var
, shift
); break;
544 case 1: gen_helper_shr(var
, var
, shift
); break;
545 case 2: gen_helper_sar(var
, var
, shift
); break;
546 case 3: gen_helper_ror(var
, var
, shift
); break;
552 #define PAS_OP(pfx) \
554 case 0: gen_pas_helper(glue(pfx,add16)); break; \
555 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
556 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
557 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
558 case 4: gen_pas_helper(glue(pfx,add8)); break; \
559 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
561 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
566 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
568 tmp
= tcg_temp_new_ptr();
569 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
573 tmp
= tcg_temp_new_ptr();
574 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
577 #undef gen_pas_helper
578 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
591 #undef gen_pas_helper
596 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
597 #define PAS_OP(pfx) \
599 case 0: gen_pas_helper(glue(pfx,add8)); break; \
600 case 1: gen_pas_helper(glue(pfx,add16)); break; \
601 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
602 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
603 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
604 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
606 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
611 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
613 tmp
= tcg_temp_new_ptr();
614 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
618 tmp
= tcg_temp_new_ptr();
619 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
622 #undef gen_pas_helper
623 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
636 #undef gen_pas_helper
641 static void gen_test_cc(int cc
, int label
)
649 tmp
= load_cpu_field(ZF
);
650 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
653 tmp
= load_cpu_field(ZF
);
654 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
657 tmp
= load_cpu_field(CF
);
658 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
661 tmp
= load_cpu_field(CF
);
662 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
665 tmp
= load_cpu_field(NF
);
666 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
669 tmp
= load_cpu_field(NF
);
670 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
673 tmp
= load_cpu_field(VF
);
674 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
677 tmp
= load_cpu_field(VF
);
678 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
680 case 8: /* hi: C && !Z */
681 inv
= gen_new_label();
682 tmp
= load_cpu_field(CF
);
683 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
685 tmp
= load_cpu_field(ZF
);
686 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
689 case 9: /* ls: !C || Z */
690 tmp
= load_cpu_field(CF
);
691 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
693 tmp
= load_cpu_field(ZF
);
694 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
696 case 10: /* ge: N == V -> N ^ V == 0 */
697 tmp
= load_cpu_field(VF
);
698 tmp2
= load_cpu_field(NF
);
699 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
701 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
703 case 11: /* lt: N != V -> N ^ V != 0 */
704 tmp
= load_cpu_field(VF
);
705 tmp2
= load_cpu_field(NF
);
706 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
708 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
710 case 12: /* gt: !Z && N == V */
711 inv
= gen_new_label();
712 tmp
= load_cpu_field(ZF
);
713 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
715 tmp
= load_cpu_field(VF
);
716 tmp2
= load_cpu_field(NF
);
717 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
719 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
722 case 13: /* le: Z || N != V */
723 tmp
= load_cpu_field(ZF
);
724 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
726 tmp
= load_cpu_field(VF
);
727 tmp2
= load_cpu_field(NF
);
728 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
730 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
733 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
739 static const uint8_t table_logic_cc
[16] = {
758 /* Set PC and Thumb state from an immediate address. */
759 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
763 s
->is_jmp
= DISAS_UPDATE
;
764 if (s
->thumb
!= (addr
& 1)) {
766 tcg_gen_movi_i32(tmp
, addr
& 1);
767 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
770 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
773 /* Set PC and Thumb state from var. var is marked as dead. */
774 static inline void gen_bx(DisasContext
*s
, TCGv var
)
776 s
->is_jmp
= DISAS_UPDATE
;
777 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
778 tcg_gen_andi_i32(var
, var
, 1);
779 store_cpu_field(var
, thumb
);
782 /* Variant of store_reg which uses branch&exchange logic when storing
783 to r15 in ARM architecture v7 and above. The source must be a temporary
784 and will be marked as dead. */
785 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
788 if (reg
== 15 && ENABLE_ARCH_7
) {
791 store_reg(s
, reg
, var
);
795 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
797 TCGv tmp
= new_tmp();
798 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
801 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
803 TCGv tmp
= new_tmp();
804 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
807 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
809 TCGv tmp
= new_tmp();
810 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
813 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
815 TCGv tmp
= new_tmp();
816 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
819 static inline TCGv
gen_ld32(TCGv addr
, int index
)
821 TCGv tmp
= new_tmp();
822 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
825 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
827 tcg_gen_qemu_st8(val
, addr
, index
);
830 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
832 tcg_gen_qemu_st16(val
, addr
, index
);
835 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
837 tcg_gen_qemu_st32(val
, addr
, index
);
841 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
843 load_reg_var(s
, cpu_T
[0], reg
);
846 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
848 load_reg_var(s
, cpu_T
[1], reg
);
851 static inline void gen_set_pc_im(uint32_t val
)
853 tcg_gen_movi_i32(cpu_R
[15], val
);
856 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
861 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
865 tcg_gen_mov_i32(cpu_R
[reg
], tmp
);
868 s
->is_jmp
= DISAS_JUMP
;
872 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
874 gen_movl_reg_TN(s
, reg
, 0);
877 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
879 gen_movl_reg_TN(s
, reg
, 1);
882 /* Force a TB lookup after an instruction that changes the CPU state. */
883 static inline void gen_lookup_tb(DisasContext
*s
)
885 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
886 s
->is_jmp
= DISAS_UPDATE
;
889 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
892 int val
, rm
, shift
, shiftop
;
895 if (!(insn
& (1 << 25))) {
898 if (!(insn
& (1 << 23)))
901 tcg_gen_addi_i32(var
, var
, val
);
905 shift
= (insn
>> 7) & 0x1f;
906 shiftop
= (insn
>> 5) & 3;
907 offset
= load_reg(s
, rm
);
908 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
909 if (!(insn
& (1 << 23)))
910 tcg_gen_sub_i32(var
, var
, offset
);
912 tcg_gen_add_i32(var
, var
, offset
);
917 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
923 if (insn
& (1 << 22)) {
925 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
926 if (!(insn
& (1 << 23)))
930 tcg_gen_addi_i32(var
, var
, val
);
934 tcg_gen_addi_i32(var
, var
, extra
);
936 offset
= load_reg(s
, rm
);
937 if (!(insn
& (1 << 23)))
938 tcg_gen_sub_i32(var
, var
, offset
);
940 tcg_gen_add_i32(var
, var
, offset
);
945 #define VFP_OP2(name) \
946 static inline void gen_vfp_##name(int dp) \
949 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
951 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
961 static inline void gen_vfp_abs(int dp
)
964 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
966 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
969 static inline void gen_vfp_neg(int dp
)
972 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
974 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
977 static inline void gen_vfp_sqrt(int dp
)
980 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
982 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
985 static inline void gen_vfp_cmp(int dp
)
988 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
990 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
993 static inline void gen_vfp_cmpe(int dp
)
996 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
998 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1001 static inline void gen_vfp_F1_ld0(int dp
)
1004 tcg_gen_movi_i64(cpu_F1d
, 0);
1006 tcg_gen_movi_i32(cpu_F1s
, 0);
1009 static inline void gen_vfp_uito(int dp
)
1012 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1014 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1017 static inline void gen_vfp_sito(int dp
)
1020 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1022 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1025 static inline void gen_vfp_toui(int dp
)
1028 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1030 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1033 static inline void gen_vfp_touiz(int dp
)
1036 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1038 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1041 static inline void gen_vfp_tosi(int dp
)
1044 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1046 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1049 static inline void gen_vfp_tosiz(int dp
)
1052 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1054 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1057 #define VFP_GEN_FIX(name) \
1058 static inline void gen_vfp_##name(int dp, int shift) \
1061 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1063 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1075 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1078 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1080 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1083 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1086 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1088 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1092 vfp_reg_offset (int dp
, int reg
)
1095 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1097 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1098 + offsetof(CPU_DoubleU
, l
.upper
);
1100 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1101 + offsetof(CPU_DoubleU
, l
.lower
);
1105 /* Return the offset of a 32-bit piece of a NEON register.
1106 zero is the least significant end of the register. */
1108 neon_reg_offset (int reg
, int n
)
1112 return vfp_reg_offset(0, sreg
);
1115 static TCGv
neon_load_reg(int reg
, int pass
)
1117 TCGv tmp
= new_tmp();
1118 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1122 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1124 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1128 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1130 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1133 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1135 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1138 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1139 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1140 #define tcg_gen_st_f32 tcg_gen_st_i32
1141 #define tcg_gen_st_f64 tcg_gen_st_i64
1143 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1146 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1148 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1151 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1154 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1156 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1159 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1162 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1164 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1167 #define ARM_CP_RW_BIT (1 << 20)
1169 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1171 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1174 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1176 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1179 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1181 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1184 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1186 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1189 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1191 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1194 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1196 iwmmxt_store_reg(cpu_M0
, rn
);
1199 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1201 iwmmxt_load_reg(cpu_M0
, rn
);
1204 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1206 iwmmxt_load_reg(cpu_V1
, rn
);
1207 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1210 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1212 iwmmxt_load_reg(cpu_V1
, rn
);
1213 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1216 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1218 iwmmxt_load_reg(cpu_V1
, rn
);
1219 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1222 #define IWMMXT_OP(name) \
1223 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1225 iwmmxt_load_reg(cpu_V1, rn); \
1226 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1229 #define IWMMXT_OP_ENV(name) \
1230 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1232 iwmmxt_load_reg(cpu_V1, rn); \
1233 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1236 #define IWMMXT_OP_ENV_SIZE(name) \
1237 IWMMXT_OP_ENV(name##b) \
1238 IWMMXT_OP_ENV(name##w) \
1239 IWMMXT_OP_ENV(name##l)
1241 #define IWMMXT_OP_ENV1(name) \
1242 static inline void gen_op_iwmmxt_##name##_M0(void) \
1244 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1258 IWMMXT_OP_ENV_SIZE(unpackl
)
1259 IWMMXT_OP_ENV_SIZE(unpackh
)
1261 IWMMXT_OP_ENV1(unpacklub
)
1262 IWMMXT_OP_ENV1(unpackluw
)
1263 IWMMXT_OP_ENV1(unpacklul
)
1264 IWMMXT_OP_ENV1(unpackhub
)
1265 IWMMXT_OP_ENV1(unpackhuw
)
1266 IWMMXT_OP_ENV1(unpackhul
)
1267 IWMMXT_OP_ENV1(unpacklsb
)
1268 IWMMXT_OP_ENV1(unpacklsw
)
1269 IWMMXT_OP_ENV1(unpacklsl
)
1270 IWMMXT_OP_ENV1(unpackhsb
)
1271 IWMMXT_OP_ENV1(unpackhsw
)
1272 IWMMXT_OP_ENV1(unpackhsl
)
1274 IWMMXT_OP_ENV_SIZE(cmpeq
)
1275 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1276 IWMMXT_OP_ENV_SIZE(cmpgts
)
1278 IWMMXT_OP_ENV_SIZE(mins
)
1279 IWMMXT_OP_ENV_SIZE(minu
)
1280 IWMMXT_OP_ENV_SIZE(maxs
)
1281 IWMMXT_OP_ENV_SIZE(maxu
)
1283 IWMMXT_OP_ENV_SIZE(subn
)
1284 IWMMXT_OP_ENV_SIZE(addn
)
1285 IWMMXT_OP_ENV_SIZE(subu
)
1286 IWMMXT_OP_ENV_SIZE(addu
)
1287 IWMMXT_OP_ENV_SIZE(subs
)
1288 IWMMXT_OP_ENV_SIZE(adds
)
1290 IWMMXT_OP_ENV(avgb0
)
1291 IWMMXT_OP_ENV(avgb1
)
1292 IWMMXT_OP_ENV(avgw0
)
1293 IWMMXT_OP_ENV(avgw1
)
1297 IWMMXT_OP_ENV(packuw
)
1298 IWMMXT_OP_ENV(packul
)
1299 IWMMXT_OP_ENV(packuq
)
1300 IWMMXT_OP_ENV(packsw
)
1301 IWMMXT_OP_ENV(packsl
)
1302 IWMMXT_OP_ENV(packsq
)
1304 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1306 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1309 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1311 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1314 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1316 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1319 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1321 iwmmxt_load_reg(cpu_V1
, rn
);
1322 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1325 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1327 TCGv tmp
= tcg_const_i32(shift
);
1328 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1331 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1333 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1334 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1335 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1338 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1340 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1341 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1342 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1345 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1347 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1348 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1350 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1353 static void gen_op_iwmmxt_set_mup(void)
1356 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1357 tcg_gen_ori_i32(tmp
, tmp
, 2);
1358 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1361 static void gen_op_iwmmxt_set_cup(void)
1364 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1365 tcg_gen_ori_i32(tmp
, tmp
, 1);
1366 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1369 static void gen_op_iwmmxt_setpsr_nz(void)
1371 TCGv tmp
= new_tmp();
1372 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1373 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1376 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1378 iwmmxt_load_reg(cpu_V1
, rn
);
1379 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1380 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1384 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1386 iwmmxt_load_reg(cpu_V0
, rn
);
1387 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1388 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1389 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1392 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1394 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1395 iwmmxt_store_reg(cpu_V0
, rn
);
1398 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1403 rd
= (insn
>> 16) & 0xf;
1404 gen_movl_T1_reg(s
, rd
);
1406 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1407 if (insn
& (1 << 24)) {
1409 if (insn
& (1 << 23))
1410 gen_op_addl_T1_im(offset
);
1412 gen_op_addl_T1_im(-offset
);
1414 if (insn
& (1 << 21))
1415 gen_movl_reg_T1(s
, rd
);
1416 } else if (insn
& (1 << 21)) {
1418 if (insn
& (1 << 23))
1419 gen_op_movl_T0_im(offset
);
1421 gen_op_movl_T0_im(- offset
);
1422 gen_op_addl_T0_T1();
1423 gen_movl_reg_T0(s
, rd
);
1424 } else if (!(insn
& (1 << 23)))
1429 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1431 int rd
= (insn
>> 0) & 0xf;
1433 if (insn
& (1 << 8))
1434 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1437 gen_op_iwmmxt_movl_T0_wCx(rd
);
1439 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1441 gen_op_movl_T1_im(mask
);
1442 gen_op_andl_T0_T1();
1446 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1447 (ie. an undefined instruction). */
1448 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1451 int rdhi
, rdlo
, rd0
, rd1
, i
;
1454 if ((insn
& 0x0e000e00) == 0x0c000000) {
1455 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1457 rdlo
= (insn
>> 12) & 0xf;
1458 rdhi
= (insn
>> 16) & 0xf;
1459 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1460 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1461 gen_movl_reg_T0(s
, rdlo
);
1462 gen_movl_reg_T1(s
, rdhi
);
1463 } else { /* TMCRR */
1464 gen_movl_T0_reg(s
, rdlo
);
1465 gen_movl_T1_reg(s
, rdhi
);
1466 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1467 gen_op_iwmmxt_set_mup();
1472 wrd
= (insn
>> 12) & 0xf;
1473 if (gen_iwmmxt_address(s
, insn
))
1475 if (insn
& ARM_CP_RW_BIT
) {
1476 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1477 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1478 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1480 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1483 if (insn
& (1 << 8)) {
1484 if (insn
& (1 << 22)) { /* WLDRD */
1485 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1487 } else { /* WLDRW wRd */
1488 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1491 if (insn
& (1 << 22)) { /* WLDRH */
1492 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1493 } else { /* WLDRB */
1494 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1498 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1501 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1504 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1505 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1507 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1508 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1510 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1512 if (insn
& (1 << 8)) {
1513 if (insn
& (1 << 22)) { /* WSTRD */
1515 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1516 } else { /* WSTRW wRd */
1517 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1518 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1521 if (insn
& (1 << 22)) { /* WSTRH */
1522 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1523 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1524 } else { /* WSTRB */
1525 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1526 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1534 if ((insn
& 0x0f000000) != 0x0e000000)
1537 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1538 case 0x000: /* WOR */
1539 wrd
= (insn
>> 12) & 0xf;
1540 rd0
= (insn
>> 0) & 0xf;
1541 rd1
= (insn
>> 16) & 0xf;
1542 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1543 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1544 gen_op_iwmmxt_setpsr_nz();
1545 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1546 gen_op_iwmmxt_set_mup();
1547 gen_op_iwmmxt_set_cup();
1549 case 0x011: /* TMCR */
1552 rd
= (insn
>> 12) & 0xf;
1553 wrd
= (insn
>> 16) & 0xf;
1555 case ARM_IWMMXT_wCID
:
1556 case ARM_IWMMXT_wCASF
:
1558 case ARM_IWMMXT_wCon
:
1559 gen_op_iwmmxt_set_cup();
1561 case ARM_IWMMXT_wCSSF
:
1562 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1563 gen_movl_T1_reg(s
, rd
);
1564 gen_op_bicl_T0_T1();
1565 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1567 case ARM_IWMMXT_wCGR0
:
1568 case ARM_IWMMXT_wCGR1
:
1569 case ARM_IWMMXT_wCGR2
:
1570 case ARM_IWMMXT_wCGR3
:
1571 gen_op_iwmmxt_set_cup();
1572 gen_movl_reg_T0(s
, rd
);
1573 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1579 case 0x100: /* WXOR */
1580 wrd
= (insn
>> 12) & 0xf;
1581 rd0
= (insn
>> 0) & 0xf;
1582 rd1
= (insn
>> 16) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1584 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1585 gen_op_iwmmxt_setpsr_nz();
1586 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1587 gen_op_iwmmxt_set_mup();
1588 gen_op_iwmmxt_set_cup();
1590 case 0x111: /* TMRC */
1593 rd
= (insn
>> 12) & 0xf;
1594 wrd
= (insn
>> 16) & 0xf;
1595 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1596 gen_movl_reg_T0(s
, rd
);
1598 case 0x300: /* WANDN */
1599 wrd
= (insn
>> 12) & 0xf;
1600 rd0
= (insn
>> 0) & 0xf;
1601 rd1
= (insn
>> 16) & 0xf;
1602 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1603 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1604 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1605 gen_op_iwmmxt_setpsr_nz();
1606 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1607 gen_op_iwmmxt_set_mup();
1608 gen_op_iwmmxt_set_cup();
1610 case 0x200: /* WAND */
1611 wrd
= (insn
>> 12) & 0xf;
1612 rd0
= (insn
>> 0) & 0xf;
1613 rd1
= (insn
>> 16) & 0xf;
1614 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1615 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1616 gen_op_iwmmxt_setpsr_nz();
1617 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1618 gen_op_iwmmxt_set_mup();
1619 gen_op_iwmmxt_set_cup();
1621 case 0x810: case 0xa10: /* WMADD */
1622 wrd
= (insn
>> 12) & 0xf;
1623 rd0
= (insn
>> 0) & 0xf;
1624 rd1
= (insn
>> 16) & 0xf;
1625 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1626 if (insn
& (1 << 21))
1627 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1629 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1630 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1631 gen_op_iwmmxt_set_mup();
1633 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1634 wrd
= (insn
>> 12) & 0xf;
1635 rd0
= (insn
>> 16) & 0xf;
1636 rd1
= (insn
>> 0) & 0xf;
1637 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1638 switch ((insn
>> 22) & 3) {
1640 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1643 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1646 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1651 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1652 gen_op_iwmmxt_set_mup();
1653 gen_op_iwmmxt_set_cup();
1655 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1656 wrd
= (insn
>> 12) & 0xf;
1657 rd0
= (insn
>> 16) & 0xf;
1658 rd1
= (insn
>> 0) & 0xf;
1659 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1660 switch ((insn
>> 22) & 3) {
1662 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1665 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1668 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1673 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1674 gen_op_iwmmxt_set_mup();
1675 gen_op_iwmmxt_set_cup();
1677 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1678 wrd
= (insn
>> 12) & 0xf;
1679 rd0
= (insn
>> 16) & 0xf;
1680 rd1
= (insn
>> 0) & 0xf;
1681 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1682 if (insn
& (1 << 22))
1683 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1685 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1686 if (!(insn
& (1 << 20)))
1687 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1688 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1689 gen_op_iwmmxt_set_mup();
1691 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1692 wrd
= (insn
>> 12) & 0xf;
1693 rd0
= (insn
>> 16) & 0xf;
1694 rd1
= (insn
>> 0) & 0xf;
1695 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1696 if (insn
& (1 << 21)) {
1697 if (insn
& (1 << 20))
1698 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1700 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1702 if (insn
& (1 << 20))
1703 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1705 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1707 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1708 gen_op_iwmmxt_set_mup();
1710 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1711 wrd
= (insn
>> 12) & 0xf;
1712 rd0
= (insn
>> 16) & 0xf;
1713 rd1
= (insn
>> 0) & 0xf;
1714 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1715 if (insn
& (1 << 21))
1716 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1718 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1719 if (!(insn
& (1 << 20))) {
1720 iwmmxt_load_reg(cpu_V1
, wrd
);
1721 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1723 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1724 gen_op_iwmmxt_set_mup();
1726 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1727 wrd
= (insn
>> 12) & 0xf;
1728 rd0
= (insn
>> 16) & 0xf;
1729 rd1
= (insn
>> 0) & 0xf;
1730 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1731 switch ((insn
>> 22) & 3) {
1733 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1736 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1739 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1744 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1745 gen_op_iwmmxt_set_mup();
1746 gen_op_iwmmxt_set_cup();
1748 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1749 wrd
= (insn
>> 12) & 0xf;
1750 rd0
= (insn
>> 16) & 0xf;
1751 rd1
= (insn
>> 0) & 0xf;
1752 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1753 if (insn
& (1 << 22)) {
1754 if (insn
& (1 << 20))
1755 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1757 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1759 if (insn
& (1 << 20))
1760 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1762 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1764 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1765 gen_op_iwmmxt_set_mup();
1766 gen_op_iwmmxt_set_cup();
1768 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1769 wrd
= (insn
>> 12) & 0xf;
1770 rd0
= (insn
>> 16) & 0xf;
1771 rd1
= (insn
>> 0) & 0xf;
1772 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1773 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1774 gen_op_movl_T1_im(7);
1775 gen_op_andl_T0_T1();
1776 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1777 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1778 gen_op_iwmmxt_set_mup();
1780 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1781 rd
= (insn
>> 12) & 0xf;
1782 wrd
= (insn
>> 16) & 0xf;
1783 gen_movl_T0_reg(s
, rd
);
1784 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1785 switch ((insn
>> 6) & 3) {
1787 gen_op_movl_T1_im(0xff);
1788 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1791 gen_op_movl_T1_im(0xffff);
1792 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1795 gen_op_movl_T1_im(0xffffffff);
1796 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1801 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1802 gen_op_iwmmxt_set_mup();
1804 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1805 rd
= (insn
>> 12) & 0xf;
1806 wrd
= (insn
>> 16) & 0xf;
1809 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1810 switch ((insn
>> 22) & 3) {
1813 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1815 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1820 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1822 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1826 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1831 gen_movl_reg_T0(s
, rd
);
1833 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1834 if ((insn
& 0x000ff008) != 0x0003f000)
1836 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1837 switch ((insn
>> 22) & 3) {
1839 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1842 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1845 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1850 gen_op_shll_T1_im(28);
1851 gen_set_nzcv(cpu_T
[1]);
1853 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1854 rd
= (insn
>> 12) & 0xf;
1855 wrd
= (insn
>> 16) & 0xf;
1856 gen_movl_T0_reg(s
, rd
);
1857 switch ((insn
>> 6) & 3) {
1859 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1862 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1865 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1870 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1871 gen_op_iwmmxt_set_mup();
1873 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1874 if ((insn
& 0x000ff00f) != 0x0003f000)
1876 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1877 gen_op_movl_T0_T1();
1878 switch ((insn
>> 22) & 3) {
1880 for (i
= 0; i
< 7; i
++) {
1881 gen_op_shll_T1_im(4);
1882 gen_op_andl_T0_T1();
1886 for (i
= 0; i
< 3; i
++) {
1887 gen_op_shll_T1_im(8);
1888 gen_op_andl_T0_T1();
1892 gen_op_shll_T1_im(16);
1893 gen_op_andl_T0_T1();
1898 gen_set_nzcv(cpu_T
[0]);
1900 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1901 wrd
= (insn
>> 12) & 0xf;
1902 rd0
= (insn
>> 16) & 0xf;
1903 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1904 switch ((insn
>> 22) & 3) {
1906 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1909 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1912 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1917 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1918 gen_op_iwmmxt_set_mup();
1920 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1921 if ((insn
& 0x000ff00f) != 0x0003f000)
1923 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1924 gen_op_movl_T0_T1();
1925 switch ((insn
>> 22) & 3) {
1927 for (i
= 0; i
< 7; i
++) {
1928 gen_op_shll_T1_im(4);
1933 for (i
= 0; i
< 3; i
++) {
1934 gen_op_shll_T1_im(8);
1939 gen_op_shll_T1_im(16);
1945 gen_set_nzcv(cpu_T
[0]);
1947 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1948 rd
= (insn
>> 12) & 0xf;
1949 rd0
= (insn
>> 16) & 0xf;
1950 if ((insn
& 0xf) != 0)
1952 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1953 switch ((insn
>> 22) & 3) {
1955 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
1958 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
1961 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
1966 gen_movl_reg_T0(s
, rd
);
1968 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1969 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1970 wrd
= (insn
>> 12) & 0xf;
1971 rd0
= (insn
>> 16) & 0xf;
1972 rd1
= (insn
>> 0) & 0xf;
1973 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1974 switch ((insn
>> 22) & 3) {
1976 if (insn
& (1 << 21))
1977 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1979 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1982 if (insn
& (1 << 21))
1983 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1985 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1988 if (insn
& (1 << 21))
1989 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1991 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1996 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1997 gen_op_iwmmxt_set_mup();
1998 gen_op_iwmmxt_set_cup();
2000 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2001 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2002 wrd
= (insn
>> 12) & 0xf;
2003 rd0
= (insn
>> 16) & 0xf;
2004 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2005 switch ((insn
>> 22) & 3) {
2007 if (insn
& (1 << 21))
2008 gen_op_iwmmxt_unpacklsb_M0();
2010 gen_op_iwmmxt_unpacklub_M0();
2013 if (insn
& (1 << 21))
2014 gen_op_iwmmxt_unpacklsw_M0();
2016 gen_op_iwmmxt_unpackluw_M0();
2019 if (insn
& (1 << 21))
2020 gen_op_iwmmxt_unpacklsl_M0();
2022 gen_op_iwmmxt_unpacklul_M0();
2027 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2028 gen_op_iwmmxt_set_mup();
2029 gen_op_iwmmxt_set_cup();
2031 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2032 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2033 wrd
= (insn
>> 12) & 0xf;
2034 rd0
= (insn
>> 16) & 0xf;
2035 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2036 switch ((insn
>> 22) & 3) {
2038 if (insn
& (1 << 21))
2039 gen_op_iwmmxt_unpackhsb_M0();
2041 gen_op_iwmmxt_unpackhub_M0();
2044 if (insn
& (1 << 21))
2045 gen_op_iwmmxt_unpackhsw_M0();
2047 gen_op_iwmmxt_unpackhuw_M0();
2050 if (insn
& (1 << 21))
2051 gen_op_iwmmxt_unpackhsl_M0();
2053 gen_op_iwmmxt_unpackhul_M0();
2058 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2059 gen_op_iwmmxt_set_mup();
2060 gen_op_iwmmxt_set_cup();
2062 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2063 case 0x214: case 0x614: case 0xa14: case 0xe14:
2064 wrd
= (insn
>> 12) & 0xf;
2065 rd0
= (insn
>> 16) & 0xf;
2066 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2067 if (gen_iwmmxt_shift(insn
, 0xff))
2069 switch ((insn
>> 22) & 3) {
2073 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2076 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2079 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2082 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2086 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2087 case 0x014: case 0x414: case 0x814: case 0xc14:
2088 wrd
= (insn
>> 12) & 0xf;
2089 rd0
= (insn
>> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2091 if (gen_iwmmxt_shift(insn
, 0xff))
2093 switch ((insn
>> 22) & 3) {
2097 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2100 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2103 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2106 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2107 gen_op_iwmmxt_set_mup();
2108 gen_op_iwmmxt_set_cup();
2110 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2111 case 0x114: case 0x514: case 0x914: case 0xd14:
2112 wrd
= (insn
>> 12) & 0xf;
2113 rd0
= (insn
>> 16) & 0xf;
2114 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2115 if (gen_iwmmxt_shift(insn
, 0xff))
2117 switch ((insn
>> 22) & 3) {
2121 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2124 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2127 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2130 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2131 gen_op_iwmmxt_set_mup();
2132 gen_op_iwmmxt_set_cup();
2134 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2135 case 0x314: case 0x714: case 0xb14: case 0xf14:
2136 wrd
= (insn
>> 12) & 0xf;
2137 rd0
= (insn
>> 16) & 0xf;
2138 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2139 switch ((insn
>> 22) & 3) {
2143 if (gen_iwmmxt_shift(insn
, 0xf))
2145 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2148 if (gen_iwmmxt_shift(insn
, 0x1f))
2150 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2153 if (gen_iwmmxt_shift(insn
, 0x3f))
2155 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2158 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2159 gen_op_iwmmxt_set_mup();
2160 gen_op_iwmmxt_set_cup();
2162 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2163 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2164 wrd
= (insn
>> 12) & 0xf;
2165 rd0
= (insn
>> 16) & 0xf;
2166 rd1
= (insn
>> 0) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2168 switch ((insn
>> 22) & 3) {
2170 if (insn
& (1 << 21))
2171 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2173 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2176 if (insn
& (1 << 21))
2177 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2179 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2182 if (insn
& (1 << 21))
2183 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2185 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2190 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2191 gen_op_iwmmxt_set_mup();
2193 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2194 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2195 wrd
= (insn
>> 12) & 0xf;
2196 rd0
= (insn
>> 16) & 0xf;
2197 rd1
= (insn
>> 0) & 0xf;
2198 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2199 switch ((insn
>> 22) & 3) {
2201 if (insn
& (1 << 21))
2202 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2204 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2207 if (insn
& (1 << 21))
2208 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2210 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2213 if (insn
& (1 << 21))
2214 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2216 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2221 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2222 gen_op_iwmmxt_set_mup();
2224 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2225 case 0x402: case 0x502: case 0x602: case 0x702:
2226 wrd
= (insn
>> 12) & 0xf;
2227 rd0
= (insn
>> 16) & 0xf;
2228 rd1
= (insn
>> 0) & 0xf;
2229 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2230 gen_op_movl_T0_im((insn
>> 20) & 3);
2231 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2232 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2233 gen_op_iwmmxt_set_mup();
2235 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2236 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2237 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2238 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2239 wrd
= (insn
>> 12) & 0xf;
2240 rd0
= (insn
>> 16) & 0xf;
2241 rd1
= (insn
>> 0) & 0xf;
2242 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2243 switch ((insn
>> 20) & 0xf) {
2245 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2248 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2251 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2254 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2257 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2260 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2263 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2266 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2269 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2274 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2275 gen_op_iwmmxt_set_mup();
2276 gen_op_iwmmxt_set_cup();
2278 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2279 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2280 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2281 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2282 wrd
= (insn
>> 12) & 0xf;
2283 rd0
= (insn
>> 16) & 0xf;
2284 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2285 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2286 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2288 gen_op_iwmmxt_set_mup();
2289 gen_op_iwmmxt_set_cup();
2291 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2292 case 0x418: case 0x518: case 0x618: case 0x718:
2293 case 0x818: case 0x918: case 0xa18: case 0xb18:
2294 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2295 wrd
= (insn
>> 12) & 0xf;
2296 rd0
= (insn
>> 16) & 0xf;
2297 rd1
= (insn
>> 0) & 0xf;
2298 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2299 switch ((insn
>> 20) & 0xf) {
2301 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2304 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2307 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2310 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2313 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2316 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2319 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2322 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2325 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2330 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2331 gen_op_iwmmxt_set_mup();
2332 gen_op_iwmmxt_set_cup();
2334 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2335 case 0x408: case 0x508: case 0x608: case 0x708:
2336 case 0x808: case 0x908: case 0xa08: case 0xb08:
2337 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2338 wrd
= (insn
>> 12) & 0xf;
2339 rd0
= (insn
>> 16) & 0xf;
2340 rd1
= (insn
>> 0) & 0xf;
2341 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2342 if (!(insn
& (1 << 20)))
2344 switch ((insn
>> 22) & 3) {
2348 if (insn
& (1 << 21))
2349 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2351 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2354 if (insn
& (1 << 21))
2355 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2357 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2360 if (insn
& (1 << 21))
2361 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2363 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2366 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2367 gen_op_iwmmxt_set_mup();
2368 gen_op_iwmmxt_set_cup();
2370 case 0x201: case 0x203: case 0x205: case 0x207:
2371 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2372 case 0x211: case 0x213: case 0x215: case 0x217:
2373 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2374 wrd
= (insn
>> 5) & 0xf;
2375 rd0
= (insn
>> 12) & 0xf;
2376 rd1
= (insn
>> 0) & 0xf;
2377 if (rd0
== 0xf || rd1
== 0xf)
2379 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2380 switch ((insn
>> 16) & 0xf) {
2381 case 0x0: /* TMIA */
2382 gen_movl_T0_reg(s
, rd0
);
2383 gen_movl_T1_reg(s
, rd1
);
2384 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2386 case 0x8: /* TMIAPH */
2387 gen_movl_T0_reg(s
, rd0
);
2388 gen_movl_T1_reg(s
, rd1
);
2389 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2391 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2392 gen_movl_T1_reg(s
, rd0
);
2393 if (insn
& (1 << 16))
2394 gen_op_shrl_T1_im(16);
2395 gen_op_movl_T0_T1();
2396 gen_movl_T1_reg(s
, rd1
);
2397 if (insn
& (1 << 17))
2398 gen_op_shrl_T1_im(16);
2399 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2404 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2405 gen_op_iwmmxt_set_mup();
2414 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2415 (ie. an undefined instruction). */
2416 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2418 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2420 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2421 /* Multiply with Internal Accumulate Format */
2422 rd0
= (insn
>> 12) & 0xf;
2424 acc
= (insn
>> 5) & 7;
2429 switch ((insn
>> 16) & 0xf) {
2431 gen_movl_T0_reg(s
, rd0
);
2432 gen_movl_T1_reg(s
, rd1
);
2433 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2435 case 0x8: /* MIAPH */
2436 gen_movl_T0_reg(s
, rd0
);
2437 gen_movl_T1_reg(s
, rd1
);
2438 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2440 case 0xc: /* MIABB */
2441 case 0xd: /* MIABT */
2442 case 0xe: /* MIATB */
2443 case 0xf: /* MIATT */
2444 gen_movl_T1_reg(s
, rd0
);
2445 if (insn
& (1 << 16))
2446 gen_op_shrl_T1_im(16);
2447 gen_op_movl_T0_T1();
2448 gen_movl_T1_reg(s
, rd1
);
2449 if (insn
& (1 << 17))
2450 gen_op_shrl_T1_im(16);
2451 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2457 gen_op_iwmmxt_movq_wRn_M0(acc
);
2461 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2462 /* Internal Accumulator Access Format */
2463 rdhi
= (insn
>> 16) & 0xf;
2464 rdlo
= (insn
>> 12) & 0xf;
2470 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2471 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2472 gen_movl_reg_T0(s
, rdlo
);
2473 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2474 gen_op_andl_T0_T1();
2475 gen_movl_reg_T0(s
, rdhi
);
2477 gen_movl_T0_reg(s
, rdlo
);
2478 gen_movl_T1_reg(s
, rdhi
);
2479 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2487 /* Disassemble system coprocessor instruction. Return nonzero if
2488 instruction is not defined. */
2489 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2492 uint32_t rd
= (insn
>> 12) & 0xf;
2493 uint32_t cp
= (insn
>> 8) & 0xf;
2498 if (insn
& ARM_CP_RW_BIT
) {
2499 if (!env
->cp
[cp
].cp_read
)
2501 gen_set_pc_im(s
->pc
);
2503 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2504 store_reg(s
, rd
, tmp
);
2506 if (!env
->cp
[cp
].cp_write
)
2508 gen_set_pc_im(s
->pc
);
2509 tmp
= load_reg(s
, rd
);
2510 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2516 static int cp15_user_ok(uint32_t insn
)
2518 int cpn
= (insn
>> 16) & 0xf;
2519 int cpm
= insn
& 0xf;
2520 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2522 if (cpn
== 13 && cpm
== 0) {
2524 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2528 /* ISB, DSB, DMB. */
2529 if ((cpm
== 5 && op
== 4)
2530 || (cpm
== 10 && (op
== 4 || op
== 5)))
2536 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2537 instruction is not defined. */
2538 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2543 /* M profile cores use memory mapped registers instead of cp15. */
2544 if (arm_feature(env
, ARM_FEATURE_M
))
2547 if ((insn
& (1 << 25)) == 0) {
2548 if (insn
& (1 << 20)) {
2552 /* mcrr. Used for block cache operations, so implement as no-op. */
2555 if ((insn
& (1 << 4)) == 0) {
2559 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2562 if ((insn
& 0x0fff0fff) == 0x0e070f90
2563 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2564 /* Wait for interrupt. */
2565 gen_set_pc_im(s
->pc
);
2566 s
->is_jmp
= DISAS_WFI
;
2569 rd
= (insn
>> 12) & 0xf;
2570 if (insn
& ARM_CP_RW_BIT
) {
2572 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2573 /* If the destination register is r15 then sets condition codes. */
2575 store_reg(s
, rd
, tmp
);
2579 tmp
= load_reg(s
, rd
);
2580 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2582 /* Normally we would always end the TB here, but Linux
2583 * arch/arm/mach-pxa/sleep.S expects two instructions following
2584 * an MMU enable to execute from cache. Imitate this behaviour. */
2585 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2586 (insn
& 0x0fff0fff) != 0x0e010f10)
2592 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2593 #define VFP_SREG(insn, bigbit, smallbit) \
2594 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2595 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2596 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2597 reg = (((insn) >> (bigbit)) & 0x0f) \
2598 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2600 if (insn & (1 << (smallbit))) \
2602 reg = ((insn) >> (bigbit)) & 0x0f; \
2605 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2606 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2607 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2608 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2609 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2610 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2612 /* Move between integer and VFP cores. */
2613 static TCGv
gen_vfp_mrs(void)
2615 TCGv tmp
= new_tmp();
2616 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2620 static void gen_vfp_msr(TCGv tmp
)
2622 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2627 vfp_enabled(CPUState
* env
)
2629 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2632 static void gen_neon_dup_u8(TCGv var
, int shift
)
2634 TCGv tmp
= new_tmp();
2636 tcg_gen_shri_i32(var
, var
, shift
);
2637 tcg_gen_ext8u_i32(var
, var
);
2638 tcg_gen_shli_i32(tmp
, var
, 8);
2639 tcg_gen_or_i32(var
, var
, tmp
);
2640 tcg_gen_shli_i32(tmp
, var
, 16);
2641 tcg_gen_or_i32(var
, var
, tmp
);
2645 static void gen_neon_dup_low16(TCGv var
)
2647 TCGv tmp
= new_tmp();
2648 tcg_gen_ext16u_i32(var
, var
);
2649 tcg_gen_shli_i32(tmp
, var
, 16);
2650 tcg_gen_or_i32(var
, var
, tmp
);
2654 static void gen_neon_dup_high16(TCGv var
)
2656 TCGv tmp
= new_tmp();
2657 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2658 tcg_gen_shri_i32(tmp
, var
, 16);
2659 tcg_gen_or_i32(var
, var
, tmp
);
2663 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2664 (ie. an undefined instruction). */
2665 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2667 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2672 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2675 if (!vfp_enabled(env
)) {
2676 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2677 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2679 rn
= (insn
>> 16) & 0xf;
2680 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2681 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2684 dp
= ((insn
& 0xf00) == 0xb00);
2685 switch ((insn
>> 24) & 0xf) {
2687 if (insn
& (1 << 4)) {
2688 /* single register transfer */
2689 rd
= (insn
>> 12) & 0xf;
2694 VFP_DREG_N(rn
, insn
);
2697 if (insn
& 0x00c00060
2698 && !arm_feature(env
, ARM_FEATURE_NEON
))
2701 pass
= (insn
>> 21) & 1;
2702 if (insn
& (1 << 22)) {
2704 offset
= ((insn
>> 5) & 3) * 8;
2705 } else if (insn
& (1 << 5)) {
2707 offset
= (insn
& (1 << 6)) ? 16 : 0;
2712 if (insn
& ARM_CP_RW_BIT
) {
2714 tmp
= neon_load_reg(rn
, pass
);
2718 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2719 if (insn
& (1 << 23))
2725 if (insn
& (1 << 23)) {
2727 tcg_gen_shri_i32(tmp
, tmp
, 16);
2733 tcg_gen_sari_i32(tmp
, tmp
, 16);
2742 store_reg(s
, rd
, tmp
);
2745 tmp
= load_reg(s
, rd
);
2746 if (insn
& (1 << 23)) {
2749 gen_neon_dup_u8(tmp
, 0);
2750 } else if (size
== 1) {
2751 gen_neon_dup_low16(tmp
);
2753 for (n
= 0; n
<= pass
* 2; n
++) {
2755 tcg_gen_mov_i32(tmp2
, tmp
);
2756 neon_store_reg(rn
, n
, tmp2
);
2758 neon_store_reg(rn
, n
, tmp
);
2763 tmp2
= neon_load_reg(rn
, pass
);
2764 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2768 tmp2
= neon_load_reg(rn
, pass
);
2769 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2775 neon_store_reg(rn
, pass
, tmp
);
2779 if ((insn
& 0x6f) != 0x00)
2781 rn
= VFP_SREG_N(insn
);
2782 if (insn
& ARM_CP_RW_BIT
) {
2784 if (insn
& (1 << 21)) {
2785 /* system register */
2790 /* VFP2 allows access to FSID from userspace.
2791 VFP3 restricts all id registers to privileged
2794 && arm_feature(env
, ARM_FEATURE_VFP3
))
2796 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2801 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2803 case ARM_VFP_FPINST
:
2804 case ARM_VFP_FPINST2
:
2805 /* Not present in VFP3. */
2807 || arm_feature(env
, ARM_FEATURE_VFP3
))
2809 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2813 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2814 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2817 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2823 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2825 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2831 gen_mov_F0_vreg(0, rn
);
2832 tmp
= gen_vfp_mrs();
2835 /* Set the 4 flag bits in the CPSR. */
2839 store_reg(s
, rd
, tmp
);
2843 tmp
= load_reg(s
, rd
);
2844 if (insn
& (1 << 21)) {
2846 /* system register */
2851 /* Writes are ignored. */
2854 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2861 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2864 case ARM_VFP_FPINST
:
2865 case ARM_VFP_FPINST2
:
2866 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2873 gen_mov_vreg_F0(0, rn
);
2878 /* data processing */
2879 /* The opcode is in bits 23, 21, 20 and 6. */
2880 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2884 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2886 /* rn is register number */
2887 VFP_DREG_N(rn
, insn
);
2890 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2891 /* Integer or single precision destination. */
2892 rd
= VFP_SREG_D(insn
);
2894 VFP_DREG_D(rd
, insn
);
2897 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2898 /* Integer source. */
2899 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2901 VFP_DREG_M(rm
, insn
);
2904 rn
= VFP_SREG_N(insn
);
2905 if (op
== 15 && rn
== 15) {
2906 /* Double precision destination. */
2907 VFP_DREG_D(rd
, insn
);
2909 rd
= VFP_SREG_D(insn
);
2911 rm
= VFP_SREG_M(insn
);
2914 veclen
= env
->vfp
.vec_len
;
2915 if (op
== 15 && rn
> 3)
2918 /* Shut up compiler warnings. */
2929 /* Figure out what type of vector operation this is. */
2930 if ((rd
& bank_mask
) == 0) {
2935 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2937 delta_d
= env
->vfp
.vec_stride
+ 1;
2939 if ((rm
& bank_mask
) == 0) {
2940 /* mixed scalar/vector */
2949 /* Load the initial operands. */
2954 /* Integer source */
2955 gen_mov_F0_vreg(0, rm
);
2960 gen_mov_F0_vreg(dp
, rd
);
2961 gen_mov_F1_vreg(dp
, rm
);
2965 /* Compare with zero */
2966 gen_mov_F0_vreg(dp
, rd
);
2977 /* Source and destination the same. */
2978 gen_mov_F0_vreg(dp
, rd
);
2981 /* One source operand. */
2982 gen_mov_F0_vreg(dp
, rm
);
2986 /* Two source operands. */
2987 gen_mov_F0_vreg(dp
, rn
);
2988 gen_mov_F1_vreg(dp
, rm
);
2992 /* Perform the calculation. */
2994 case 0: /* mac: fd + (fn * fm) */
2996 gen_mov_F1_vreg(dp
, rd
);
2999 case 1: /* nmac: fd - (fn * fm) */
3002 gen_mov_F1_vreg(dp
, rd
);
3005 case 2: /* msc: -fd + (fn * fm) */
3007 gen_mov_F1_vreg(dp
, rd
);
3010 case 3: /* nmsc: -fd - (fn * fm) */
3013 gen_mov_F1_vreg(dp
, rd
);
3016 case 4: /* mul: fn * fm */
3019 case 5: /* nmul: -(fn * fm) */
3023 case 6: /* add: fn + fm */
3026 case 7: /* sub: fn - fm */
3029 case 8: /* div: fn / fm */
3032 case 14: /* fconst */
3033 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3036 n
= (insn
<< 12) & 0x80000000;
3037 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3044 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3051 tcg_gen_movi_i32(cpu_F0s
, n
);
3054 case 15: /* extension space */
3077 case 11: /* cmpez */
3081 case 15: /* single<->double conversion */
3083 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3085 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3087 case 16: /* fuito */
3090 case 17: /* fsito */
3093 case 20: /* fshto */
3094 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3096 gen_vfp_shto(dp
, 16 - rm
);
3098 case 21: /* fslto */
3099 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3101 gen_vfp_slto(dp
, 32 - rm
);
3103 case 22: /* fuhto */
3104 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3106 gen_vfp_uhto(dp
, 16 - rm
);
3108 case 23: /* fulto */
3109 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3111 gen_vfp_ulto(dp
, 32 - rm
);
3113 case 24: /* ftoui */
3116 case 25: /* ftouiz */
3119 case 26: /* ftosi */
3122 case 27: /* ftosiz */
3125 case 28: /* ftosh */
3126 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3128 gen_vfp_tosh(dp
, 16 - rm
);
3130 case 29: /* ftosl */
3131 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3133 gen_vfp_tosl(dp
, 32 - rm
);
3135 case 30: /* ftouh */
3136 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3138 gen_vfp_touh(dp
, 16 - rm
);
3140 case 31: /* ftoul */
3141 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3143 gen_vfp_toul(dp
, 32 - rm
);
3145 default: /* undefined */
3146 printf ("rn:%d\n", rn
);
3150 default: /* undefined */
3151 printf ("op:%d\n", op
);
3155 /* Write back the result. */
3156 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3157 ; /* Comparison, do nothing. */
3158 else if (op
== 15 && rn
> 17)
3159 /* Integer result. */
3160 gen_mov_vreg_F0(0, rd
);
3161 else if (op
== 15 && rn
== 15)
3163 gen_mov_vreg_F0(!dp
, rd
);
3165 gen_mov_vreg_F0(dp
, rd
);
3167 /* break out of the loop if we have finished */
3171 if (op
== 15 && delta_m
== 0) {
3172 /* single source one-many */
3174 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3176 gen_mov_vreg_F0(dp
, rd
);
3180 /* Setup the next operands. */
3182 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3186 /* One source operand. */
3187 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3189 gen_mov_F0_vreg(dp
, rm
);
3191 /* Two source operands. */
3192 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3194 gen_mov_F0_vreg(dp
, rn
);
3196 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3198 gen_mov_F1_vreg(dp
, rm
);
3206 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3207 /* two-register transfer */
3208 rn
= (insn
>> 16) & 0xf;
3209 rd
= (insn
>> 12) & 0xf;
3211 VFP_DREG_M(rm
, insn
);
3213 rm
= VFP_SREG_M(insn
);
3216 if (insn
& ARM_CP_RW_BIT
) {
3219 gen_mov_F0_vreg(0, rm
* 2);
3220 tmp
= gen_vfp_mrs();
3221 store_reg(s
, rd
, tmp
);
3222 gen_mov_F0_vreg(0, rm
* 2 + 1);
3223 tmp
= gen_vfp_mrs();
3224 store_reg(s
, rn
, tmp
);
3226 gen_mov_F0_vreg(0, rm
);
3227 tmp
= gen_vfp_mrs();
3228 store_reg(s
, rn
, tmp
);
3229 gen_mov_F0_vreg(0, rm
+ 1);
3230 tmp
= gen_vfp_mrs();
3231 store_reg(s
, rd
, tmp
);
3236 tmp
= load_reg(s
, rd
);
3238 gen_mov_vreg_F0(0, rm
* 2);
3239 tmp
= load_reg(s
, rn
);
3241 gen_mov_vreg_F0(0, rm
* 2 + 1);
3243 tmp
= load_reg(s
, rn
);
3245 gen_mov_vreg_F0(0, rm
);
3246 tmp
= load_reg(s
, rd
);
3248 gen_mov_vreg_F0(0, rm
+ 1);
3253 rn
= (insn
>> 16) & 0xf;
3255 VFP_DREG_D(rd
, insn
);
3257 rd
= VFP_SREG_D(insn
);
3258 if (s
->thumb
&& rn
== 15) {
3259 gen_op_movl_T1_im(s
->pc
& ~2);
3261 gen_movl_T1_reg(s
, rn
);
3263 if ((insn
& 0x01200000) == 0x01000000) {
3264 /* Single load/store */
3265 offset
= (insn
& 0xff) << 2;
3266 if ((insn
& (1 << 23)) == 0)
3268 gen_op_addl_T1_im(offset
);
3269 if (insn
& (1 << 20)) {
3271 gen_mov_vreg_F0(dp
, rd
);
3273 gen_mov_F0_vreg(dp
, rd
);
3277 /* load/store multiple */
3279 n
= (insn
>> 1) & 0x7f;
3283 if (insn
& (1 << 24)) /* pre-decrement */
3284 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3290 for (i
= 0; i
< n
; i
++) {
3291 if (insn
& ARM_CP_RW_BIT
) {
3294 gen_mov_vreg_F0(dp
, rd
+ i
);
3297 gen_mov_F0_vreg(dp
, rd
+ i
);
3300 gen_op_addl_T1_im(offset
);
3302 if (insn
& (1 << 21)) {
3304 if (insn
& (1 << 24))
3305 offset
= -offset
* n
;
3306 else if (dp
&& (insn
& 1))
3312 gen_op_addl_T1_im(offset
);
3313 gen_movl_reg_T1(s
, rn
);
3319 /* Should never happen. */
3325 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3327 TranslationBlock
*tb
;
3330 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3332 gen_set_pc_im(dest
);
3333 tcg_gen_exit_tb((long)tb
+ n
);
3335 gen_set_pc_im(dest
);
3340 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3342 if (unlikely(s
->singlestep_enabled
)) {
3343 /* An indirect jump so that we still trigger the debug exception. */
3348 gen_goto_tb(s
, 0, dest
);
3349 s
->is_jmp
= DISAS_TB_JUMP
;
3353 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3356 tcg_gen_sari_i32(t0
, t0
, 16);
3360 tcg_gen_sari_i32(t1
, t1
, 16);
3363 tcg_gen_mul_i32(t0
, t0
, t1
);
3366 /* Return the mask of PSR bits set by a MSR instruction. */
3367 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3371 if (flags
& (1 << 0))
3373 if (flags
& (1 << 1))
3375 if (flags
& (1 << 2))
3377 if (flags
& (1 << 3))
3380 /* Mask out undefined bits. */
3381 mask
&= ~CPSR_RESERVED
;
3382 if (!arm_feature(env
, ARM_FEATURE_V6
))
3383 mask
&= ~(CPSR_E
| CPSR_GE
);
3384 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3386 /* Mask out execution state bits. */
3389 /* Mask out privileged bits. */
3395 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3396 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3400 /* ??? This is also undefined in system mode. */
3404 tmp
= load_cpu_field(spsr
);
3405 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3406 tcg_gen_andi_i32(t0
, t0
, mask
);
3407 tcg_gen_or_i32(tmp
, tmp
, t0
);
3408 store_cpu_field(tmp
, spsr
);
3410 gen_set_cpsr(t0
, mask
);
3417 /* Returns nonzero if access to the PSR is not permitted. */
3418 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3422 tcg_gen_movi_i32(tmp
, val
);
3423 return gen_set_psr(s
, mask
, spsr
, tmp
);
3426 /* Generate an old-style exception return. Marks pc as dead. */
3427 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3430 store_reg(s
, 15, pc
);
3431 tmp
= load_cpu_field(spsr
);
3432 gen_set_cpsr(tmp
, 0xffffffff);
3434 s
->is_jmp
= DISAS_UPDATE
;
3437 /* Generate a v6 exception return. Marks both values as dead. */
3438 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3440 gen_set_cpsr(cpsr
, 0xffffffff);
3442 store_reg(s
, 15, pc
);
3443 s
->is_jmp
= DISAS_UPDATE
;
3447 gen_set_condexec (DisasContext
*s
)
3449 if (s
->condexec_mask
) {
3450 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3451 TCGv tmp
= new_tmp();
3452 tcg_gen_movi_i32(tmp
, val
);
3453 store_cpu_field(tmp
, condexec_bits
);
3457 static void gen_nop_hint(DisasContext
*s
, int val
)
3461 gen_set_pc_im(s
->pc
);
3462 s
->is_jmp
= DISAS_WFI
;
3466 /* TODO: Implement SEV and WFE. May help SMP performance. */
3472 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3474 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3477 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3478 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3479 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3485 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3488 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3489 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3490 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3495 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3496 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3497 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3498 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3499 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3501 /* FIXME: This is wrong. They set the wrong overflow bit. */
3502 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3503 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3504 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3505 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3507 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3508 switch ((size << 1) | u) { \
3510 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3513 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3516 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3519 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3522 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3525 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3527 default: return 1; \
3530 #define GEN_NEON_INTEGER_OP(name) do { \
3531 switch ((size << 1) | u) { \
3533 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3536 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3539 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3542 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3545 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3548 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3550 default: return 1; \
3553 static TCGv
neon_load_scratch(int scratch
)
3555 TCGv tmp
= new_tmp();
3556 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3560 static void neon_store_scratch(int scratch
, TCGv var
)
3562 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3566 static inline TCGv
neon_get_scalar(int size
, int reg
)
3570 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3572 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3574 gen_neon_dup_low16(tmp
);
3576 gen_neon_dup_high16(tmp
);
3582 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3590 tcg_gen_andi_i32(rd
, t0
, 0xff);
3591 tcg_gen_shri_i32(tmp
, t0
, 8);
3592 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3593 tcg_gen_or_i32(rd
, rd
, tmp
);
3594 tcg_gen_shli_i32(tmp
, t1
, 16);
3595 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3596 tcg_gen_or_i32(rd
, rd
, tmp
);
3597 tcg_gen_shli_i32(tmp
, t1
, 8);
3598 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3599 tcg_gen_or_i32(rd
, rd
, tmp
);
3601 tcg_gen_shri_i32(rm
, t0
, 8);
3602 tcg_gen_andi_i32(rm
, rm
, 0xff);
3603 tcg_gen_shri_i32(tmp
, t0
, 16);
3604 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3605 tcg_gen_or_i32(rm
, rm
, tmp
);
3606 tcg_gen_shli_i32(tmp
, t1
, 8);
3607 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3608 tcg_gen_or_i32(rm
, rm
, tmp
);
3609 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3610 tcg_gen_or_i32(t1
, rm
, tmp
);
3611 tcg_gen_mov_i32(t0
, rd
);
3618 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3626 tcg_gen_andi_i32(rd
, t0
, 0xff);
3627 tcg_gen_shli_i32(tmp
, t1
, 8);
3628 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3629 tcg_gen_or_i32(rd
, rd
, tmp
);
3630 tcg_gen_shli_i32(tmp
, t0
, 16);
3631 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3632 tcg_gen_or_i32(rd
, rd
, tmp
);
3633 tcg_gen_shli_i32(tmp
, t1
, 24);
3634 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3635 tcg_gen_or_i32(rd
, rd
, tmp
);
3637 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3638 tcg_gen_shri_i32(tmp
, t0
, 8);
3639 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3640 tcg_gen_or_i32(rm
, rm
, tmp
);
3641 tcg_gen_shri_i32(tmp
, t1
, 8);
3642 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3643 tcg_gen_or_i32(rm
, rm
, tmp
);
3644 tcg_gen_shri_i32(tmp
, t0
, 16);
3645 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3646 tcg_gen_or_i32(t1
, rm
, tmp
);
3647 tcg_gen_mov_i32(t0
, rd
);
3654 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3661 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3662 tcg_gen_shli_i32(tmp2
, t1
, 16);
3663 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3664 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3665 tcg_gen_shri_i32(tmp2
, t0
, 16);
3666 tcg_gen_or_i32(t1
, t1
, tmp2
);
3667 tcg_gen_mov_i32(t0
, tmp
);
3673 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3678 for (n
= 0; n
< q
+ 1; n
+= 2) {
3679 t0
= neon_load_reg(reg
, n
);
3680 t1
= neon_load_reg(reg
, n
+ 1);
3682 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3683 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3684 case 2: /* no-op */; break;
3687 neon_store_scratch(tmp
+ n
, t0
);
3688 neon_store_scratch(tmp
+ n
+ 1, t1
);
3692 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3699 tcg_gen_shli_i32(rd
, t0
, 8);
3700 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3701 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3702 tcg_gen_or_i32(rd
, rd
, tmp
);
3704 tcg_gen_shri_i32(t1
, t1
, 8);
3705 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3706 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3707 tcg_gen_or_i32(t1
, t1
, tmp
);
3708 tcg_gen_mov_i32(t0
, rd
);
3714 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3721 tcg_gen_shli_i32(rd
, t0
, 16);
3722 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3723 tcg_gen_or_i32(rd
, rd
, tmp
);
3724 tcg_gen_shri_i32(t1
, t1
, 16);
3725 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3726 tcg_gen_or_i32(t1
, t1
, tmp
);
3727 tcg_gen_mov_i32(t0
, rd
);
3738 } neon_ls_element_type
[11] = {
3752 /* Translate a NEON load/store element instruction. Return nonzero if the
3753 instruction is invalid. */
3754 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3771 if (!vfp_enabled(env
))
3773 VFP_DREG_D(rd
, insn
);
3774 rn
= (insn
>> 16) & 0xf;
3776 load
= (insn
& (1 << 21)) != 0;
3778 if ((insn
& (1 << 23)) == 0) {
3779 /* Load store all elements. */
3780 op
= (insn
>> 8) & 0xf;
3781 size
= (insn
>> 6) & 3;
3782 if (op
> 10 || size
== 3)
3784 nregs
= neon_ls_element_type
[op
].nregs
;
3785 interleave
= neon_ls_element_type
[op
].interleave
;
3786 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3787 stride
= (1 << size
) * interleave
;
3788 for (reg
= 0; reg
< nregs
; reg
++) {
3789 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3790 tcg_gen_addi_i32(addr
, cpu_R
[rn
], (1 << size
) * reg
);
3791 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3792 tcg_gen_addi_i32(addr
, cpu_R
[rn
], 1 << size
);
3794 for (pass
= 0; pass
< 2; pass
++) {
3797 tmp
= gen_ld32(addr
, IS_USER(s
));
3798 neon_store_reg(rd
, pass
, tmp
);
3800 tmp
= neon_load_reg(rd
, pass
);
3801 gen_st32(tmp
, addr
, IS_USER(s
));
3803 tcg_gen_addi_i32(addr
, addr
, stride
);
3804 } else if (size
== 1) {
3806 tmp
= gen_ld16u(addr
, IS_USER(s
));
3807 tcg_gen_addi_i32(addr
, addr
, stride
);
3808 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3809 tcg_gen_addi_i32(addr
, addr
, stride
);
3810 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3812 neon_store_reg(rd
, pass
, tmp
);
3814 tmp
= neon_load_reg(rd
, pass
);
3816 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3817 gen_st16(tmp
, addr
, IS_USER(s
));
3818 tcg_gen_addi_i32(addr
, addr
, stride
);
3819 gen_st16(tmp2
, addr
, IS_USER(s
));
3820 tcg_gen_addi_i32(addr
, addr
, stride
);
3822 } else /* size == 0 */ {
3825 for (n
= 0; n
< 4; n
++) {
3826 tmp
= gen_ld8u(addr
, IS_USER(s
));
3827 tcg_gen_addi_i32(addr
, addr
, stride
);
3831 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3835 neon_store_reg(rd
, pass
, tmp2
);
3837 tmp2
= neon_load_reg(rd
, pass
);
3838 for (n
= 0; n
< 4; n
++) {
3841 tcg_gen_mov_i32(tmp
, tmp2
);
3843 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3845 gen_st8(tmp
, addr
, IS_USER(s
));
3846 tcg_gen_addi_i32(addr
, addr
, stride
);
3852 rd
+= neon_ls_element_type
[op
].spacing
;
3856 size
= (insn
>> 10) & 3;
3858 /* Load single element to all lanes. */
3861 size
= (insn
>> 6) & 3;
3862 nregs
= ((insn
>> 8) & 3) + 1;
3863 stride
= (insn
& (1 << 5)) ? 2 : 1;
3864 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3865 for (reg
= 0; reg
< nregs
; reg
++) {
3868 tmp
= gen_ld8u(addr
, IS_USER(s
));
3869 gen_neon_dup_u8(tmp
, 0);
3872 tmp
= gen_ld16u(addr
, IS_USER(s
));
3873 gen_neon_dup_low16(tmp
);
3876 tmp
= gen_ld32(addr
, IS_USER(s
));
3880 default: /* Avoid compiler warnings. */
3883 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3885 tcg_gen_mov_i32(tmp2
, tmp
);
3886 neon_store_reg(rd
, 0, tmp2
);
3887 neon_store_reg(rd
, 1, tmp
);
3890 stride
= (1 << size
) * nregs
;
3892 /* Single element. */
3893 pass
= (insn
>> 7) & 1;
3896 shift
= ((insn
>> 5) & 3) * 8;
3900 shift
= ((insn
>> 6) & 1) * 16;
3901 stride
= (insn
& (1 << 5)) ? 2 : 1;
3905 stride
= (insn
& (1 << 6)) ? 2 : 1;
3910 nregs
= ((insn
>> 8) & 3) + 1;
3911 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3912 for (reg
= 0; reg
< nregs
; reg
++) {
3916 tmp
= gen_ld8u(addr
, IS_USER(s
));
3919 tmp
= gen_ld16u(addr
, IS_USER(s
));
3922 tmp
= gen_ld32(addr
, IS_USER(s
));
3924 default: /* Avoid compiler warnings. */
3928 tmp2
= neon_load_reg(rd
, pass
);
3929 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3932 neon_store_reg(rd
, pass
, tmp
);
3933 } else { /* Store */
3934 tmp
= neon_load_reg(rd
, pass
);
3936 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3939 gen_st8(tmp
, addr
, IS_USER(s
));
3942 gen_st16(tmp
, addr
, IS_USER(s
));
3945 gen_st32(tmp
, addr
, IS_USER(s
));
3950 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3952 stride
= nregs
* (1 << size
);
3959 base
= load_reg(s
, rn
);
3961 tcg_gen_addi_i32(base
, base
, stride
);
3964 index
= load_reg(s
, rm
);
3965 tcg_gen_add_i32(base
, base
, index
);
3968 store_reg(s
, rn
, base
);
3973 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3974 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3976 tcg_gen_and_i32(t
, t
, c
);
3977 tcg_gen_bic_i32(f
, f
, c
);
3978 tcg_gen_or_i32(dest
, t
, f
);
3981 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3984 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3985 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3986 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3991 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3994 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3995 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3996 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4001 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4004 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4005 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4006 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4011 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4017 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4018 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4023 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4024 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4031 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4032 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4037 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4038 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4045 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4049 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4050 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4051 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4056 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4057 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4058 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4065 static inline void gen_neon_addl(int size
)
4068 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4069 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4070 case 2: tcg_gen_add_i64(CPU_V001
); break;
4075 static inline void gen_neon_subl(int size
)
4078 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4079 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4080 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4085 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4088 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4089 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4090 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4095 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4098 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4099 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4104 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4108 switch ((size
<< 1) | u
) {
4109 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4110 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4111 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4112 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4114 tmp
= gen_muls_i64_i32(a
, b
);
4115 tcg_gen_mov_i64(dest
, tmp
);
4118 tmp
= gen_mulu_i64_i32(a
, b
);
4119 tcg_gen_mov_i64(dest
, tmp
);
4125 /* Translate a NEON data processing instruction. Return nonzero if the
4126 instruction is invalid.
4127 We process data in a mixture of 32-bit and 64-bit chunks.
4128 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4130 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4148 if (!vfp_enabled(env
))
4150 q
= (insn
& (1 << 6)) != 0;
4151 u
= (insn
>> 24) & 1;
4152 VFP_DREG_D(rd
, insn
);
4153 VFP_DREG_N(rn
, insn
);
4154 VFP_DREG_M(rm
, insn
);
4155 size
= (insn
>> 20) & 3;
4156 if ((insn
& (1 << 23)) == 0) {
4157 /* Three register same length. */
4158 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4159 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4160 || op
== 10 || op
== 11 || op
== 16)) {
4161 /* 64-bit element instructions. */
4162 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4163 neon_load_reg64(cpu_V0
, rn
+ pass
);
4164 neon_load_reg64(cpu_V1
, rm
+ pass
);
4168 gen_helper_neon_add_saturate_u64(CPU_V001
);
4170 gen_helper_neon_add_saturate_s64(CPU_V001
);
4175 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4177 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4182 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4184 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4189 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4192 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4196 case 10: /* VRSHL */
4198 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4200 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4203 case 11: /* VQRSHL */
4205 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4208 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4214 tcg_gen_sub_i64(CPU_V001
);
4216 tcg_gen_add_i64(CPU_V001
);
4222 neon_store_reg64(cpu_V0
, rd
+ pass
);
4229 case 10: /* VRSHL */
4230 case 11: /* VQRSHL */
4233 /* Shift instruction operands are reversed. */
4240 case 20: /* VPMAX */
4241 case 21: /* VPMIN */
4242 case 23: /* VPADD */
4245 case 26: /* VPADD (float) */
4246 pairwise
= (u
&& size
< 2);
4248 case 30: /* VPMIN/VPMAX (float) */
4256 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4265 tmp
= neon_load_reg(rn
, n
);
4266 tmp2
= neon_load_reg(rn
, n
+ 1);
4268 tmp
= neon_load_reg(rm
, n
);
4269 tmp2
= neon_load_reg(rm
, n
+ 1);
4273 tmp
= neon_load_reg(rn
, pass
);
4274 tmp2
= neon_load_reg(rm
, pass
);
4278 GEN_NEON_INTEGER_OP(hadd
);
4281 GEN_NEON_INTEGER_OP_ENV(qadd
);
4283 case 2: /* VRHADD */
4284 GEN_NEON_INTEGER_OP(rhadd
);
4286 case 3: /* Logic ops. */
4287 switch ((u
<< 2) | size
) {
4289 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4292 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4295 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4298 tcg_gen_not_i32(tmp2
, tmp2
);
4299 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4302 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4305 tmp3
= neon_load_reg(rd
, pass
);
4306 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4310 tmp3
= neon_load_reg(rd
, pass
);
4311 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4315 tmp3
= neon_load_reg(rd
, pass
);
4316 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4322 GEN_NEON_INTEGER_OP(hsub
);
4325 GEN_NEON_INTEGER_OP_ENV(qsub
);
4328 GEN_NEON_INTEGER_OP(cgt
);
4331 GEN_NEON_INTEGER_OP(cge
);
4334 GEN_NEON_INTEGER_OP(shl
);
4337 GEN_NEON_INTEGER_OP_ENV(qshl
);
4339 case 10: /* VRSHL */
4340 GEN_NEON_INTEGER_OP(rshl
);
4342 case 11: /* VQRSHL */
4343 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4346 GEN_NEON_INTEGER_OP(max
);
4349 GEN_NEON_INTEGER_OP(min
);
4352 GEN_NEON_INTEGER_OP(abd
);
4355 GEN_NEON_INTEGER_OP(abd
);
4357 tmp2
= neon_load_reg(rd
, pass
);
4358 gen_neon_add(size
, tmp
, tmp2
);
4361 if (!u
) { /* VADD */
4362 if (gen_neon_add(size
, tmp
, tmp2
))
4366 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4367 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4368 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4374 if (!u
) { /* VTST */
4376 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4377 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4378 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4383 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4384 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4385 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4390 case 18: /* Multiply. */
4392 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4393 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4394 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4398 tmp2
= neon_load_reg(rd
, pass
);
4400 gen_neon_rsb(size
, tmp
, tmp2
);
4402 gen_neon_add(size
, tmp
, tmp2
);
4406 if (u
) { /* polynomial */
4407 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4408 } else { /* Integer */
4410 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4411 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4412 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4417 case 20: /* VPMAX */
4418 GEN_NEON_INTEGER_OP(pmax
);
4420 case 21: /* VPMIN */
4421 GEN_NEON_INTEGER_OP(pmin
);
4423 case 22: /* Hultiply high. */
4424 if (!u
) { /* VQDMULH */
4426 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4427 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4430 } else { /* VQRDHMUL */
4432 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4433 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4438 case 23: /* VPADD */
4442 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4443 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4444 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4448 case 26: /* Floating point arithnetic. */
4449 switch ((u
<< 2) | size
) {
4451 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4454 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4457 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4460 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4466 case 27: /* Float multiply. */
4467 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4470 tmp2
= neon_load_reg(rd
, pass
);
4472 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4474 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4478 case 28: /* Float compare. */
4480 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4483 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4485 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4488 case 29: /* Float compare absolute. */
4492 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4494 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4496 case 30: /* Float min/max. */
4498 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4500 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4504 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4506 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4513 /* Save the result. For elementwise operations we can put it
4514 straight into the destination register. For pairwise operations
4515 we have to be careful to avoid clobbering the source operands. */
4516 if (pairwise
&& rd
== rm
) {
4517 neon_store_scratch(pass
, tmp
);
4519 neon_store_reg(rd
, pass
, tmp
);
4523 if (pairwise
&& rd
== rm
) {
4524 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4525 tmp
= neon_load_scratch(pass
);
4526 neon_store_reg(rd
, pass
, tmp
);
4529 /* End of 3 register same size operations. */
4530 } else if (insn
& (1 << 4)) {
4531 if ((insn
& 0x00380080) != 0) {
4532 /* Two registers and shift. */
4533 op
= (insn
>> 8) & 0xf;
4534 if (insn
& (1 << 7)) {
4539 while ((insn
& (1 << (size
+ 19))) == 0)
4542 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4543 /* To avoid excessive dumplication of ops we implement shift
4544 by immediate using the variable shift operations. */
4546 /* Shift by immediate:
4547 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4548 /* Right shifts are encoded as N - shift, where N is the
4549 element size in bits. */
4551 shift
= shift
- (1 << (size
+ 3));
4559 imm
= (uint8_t) shift
;
4564 imm
= (uint16_t) shift
;
4575 for (pass
= 0; pass
< count
; pass
++) {
4577 neon_load_reg64(cpu_V0
, rm
+ pass
);
4578 tcg_gen_movi_i64(cpu_V1
, imm
);
4583 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4585 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4590 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4592 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4597 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4599 case 5: /* VSHL, VSLI */
4600 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4604 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4606 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4608 case 7: /* VQSHLU */
4609 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4612 if (op
== 1 || op
== 3) {
4614 neon_load_reg64(cpu_V0
, rd
+ pass
);
4615 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4616 } else if (op
== 4 || (op
== 5 && u
)) {
4618 cpu_abort(env
, "VS[LR]I.64 not implemented");
4620 neon_store_reg64(cpu_V0
, rd
+ pass
);
4621 } else { /* size < 3 */
4622 /* Operands in T0 and T1. */
4623 tmp
= neon_load_reg(rm
, pass
);
4625 tcg_gen_movi_i32(tmp2
, imm
);
4629 GEN_NEON_INTEGER_OP(shl
);
4633 GEN_NEON_INTEGER_OP(rshl
);
4638 GEN_NEON_INTEGER_OP(shl
);
4640 case 5: /* VSHL, VSLI */
4642 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4643 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4644 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4649 GEN_NEON_INTEGER_OP_ENV(qshl
);
4651 case 7: /* VQSHLU */
4653 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4654 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4655 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4662 if (op
== 1 || op
== 3) {
4664 tmp2
= neon_load_reg(rd
, pass
);
4665 gen_neon_add(size
, tmp2
, tmp
);
4667 } else if (op
== 4 || (op
== 5 && u
)) {
4672 imm
= 0xff >> -shift
;
4674 imm
= (uint8_t)(0xff << shift
);
4680 imm
= 0xffff >> -shift
;
4682 imm
= (uint16_t)(0xffff << shift
);
4687 imm
= 0xffffffffu
>> -shift
;
4689 imm
= 0xffffffffu
<< shift
;
4694 tmp2
= neon_load_reg(rd
, pass
);
4695 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4696 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4697 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4700 neon_store_reg(rd
, pass
, tmp
);
4703 } else if (op
< 10) {
4704 /* Shift by immediate and narrow:
4705 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4706 shift
= shift
- (1 << (size
+ 3));
4710 imm
= (uint16_t)shift
;
4712 tmp2
= tcg_const_i32(imm
);
4713 TCGV_UNUSED_I64(tmp64
);
4716 imm
= (uint32_t)shift
;
4717 tmp2
= tcg_const_i32(imm
);
4718 TCGV_UNUSED_I64(tmp64
);
4721 tmp64
= tcg_const_i64(shift
);
4728 for (pass
= 0; pass
< 2; pass
++) {
4730 neon_load_reg64(cpu_V0
, rm
+ pass
);
4733 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4735 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4738 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4740 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4743 tmp
= neon_load_reg(rm
+ pass
, 0);
4744 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4745 tmp3
= neon_load_reg(rm
+ pass
, 1);
4746 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4747 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4752 if (op
== 8 && !u
) {
4753 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4756 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4758 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4763 neon_store_reg(rd
, 0, tmp2
);
4764 neon_store_reg(rd
, 1, tmp
);
4767 } else if (op
== 10) {
4771 tmp
= neon_load_reg(rm
, 0);
4772 tmp2
= neon_load_reg(rm
, 1);
4773 for (pass
= 0; pass
< 2; pass
++) {
4777 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4780 /* The shift is less than the width of the source
4781 type, so we can just shift the whole register. */
4782 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4783 if (size
< 2 || !u
) {
4786 imm
= (0xffu
>> (8 - shift
));
4789 imm
= 0xffff >> (16 - shift
);
4791 imm64
= imm
| (((uint64_t)imm
) << 32);
4792 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4795 neon_store_reg64(cpu_V0
, rd
+ pass
);
4797 } else if (op
== 15 || op
== 16) {
4798 /* VCVT fixed-point. */
4799 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4800 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4803 gen_vfp_ulto(0, shift
);
4805 gen_vfp_slto(0, shift
);
4808 gen_vfp_toul(0, shift
);
4810 gen_vfp_tosl(0, shift
);
4812 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4817 } else { /* (insn & 0x00380080) == 0 */
4820 op
= (insn
>> 8) & 0xf;
4821 /* One register and immediate. */
4822 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4823 invert
= (insn
& (1 << 5)) != 0;
4841 imm
= (imm
<< 8) | (imm
<< 24);
4844 imm
= (imm
< 8) | 0xff;
4847 imm
= (imm
<< 16) | 0xffff;
4850 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4855 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4856 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4862 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4863 if (op
& 1 && op
< 12) {
4864 tmp
= neon_load_reg(rd
, pass
);
4866 /* The immediate value has already been inverted, so
4868 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4870 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4875 if (op
== 14 && invert
) {
4878 for (n
= 0; n
< 4; n
++) {
4879 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4880 val
|= 0xff << (n
* 8);
4882 tcg_gen_movi_i32(tmp
, val
);
4884 tcg_gen_movi_i32(tmp
, imm
);
4887 neon_store_reg(rd
, pass
, tmp
);
4890 } else { /* (insn & 0x00800010 == 0x00800000) */
4892 op
= (insn
>> 8) & 0xf;
4893 if ((insn
& (1 << 6)) == 0) {
4894 /* Three registers of different lengths. */
4898 /* prewiden, src1_wide, src2_wide */
4899 static const int neon_3reg_wide
[16][3] = {
4900 {1, 0, 0}, /* VADDL */
4901 {1, 1, 0}, /* VADDW */
4902 {1, 0, 0}, /* VSUBL */
4903 {1, 1, 0}, /* VSUBW */
4904 {0, 1, 1}, /* VADDHN */
4905 {0, 0, 0}, /* VABAL */
4906 {0, 1, 1}, /* VSUBHN */
4907 {0, 0, 0}, /* VABDL */
4908 {0, 0, 0}, /* VMLAL */
4909 {0, 0, 0}, /* VQDMLAL */
4910 {0, 0, 0}, /* VMLSL */
4911 {0, 0, 0}, /* VQDMLSL */
4912 {0, 0, 0}, /* Integer VMULL */
4913 {0, 0, 0}, /* VQDMULL */
4914 {0, 0, 0} /* Polynomial VMULL */
4917 prewiden
= neon_3reg_wide
[op
][0];
4918 src1_wide
= neon_3reg_wide
[op
][1];
4919 src2_wide
= neon_3reg_wide
[op
][2];
4921 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4924 /* Avoid overlapping operands. Wide source operands are
4925 always aligned so will never overlap with wide
4926 destinations in problematic ways. */
4927 if (rd
== rm
&& !src2_wide
) {
4928 tmp
= neon_load_reg(rm
, 1);
4929 neon_store_scratch(2, tmp
);
4930 } else if (rd
== rn
&& !src1_wide
) {
4931 tmp
= neon_load_reg(rn
, 1);
4932 neon_store_scratch(2, tmp
);
4935 for (pass
= 0; pass
< 2; pass
++) {
4937 neon_load_reg64(cpu_V0
, rn
+ pass
);
4940 if (pass
== 1 && rd
== rn
) {
4941 tmp
= neon_load_scratch(2);
4943 tmp
= neon_load_reg(rn
, pass
);
4946 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4950 neon_load_reg64(cpu_V1
, rm
+ pass
);
4953 if (pass
== 1 && rd
== rm
) {
4954 tmp2
= neon_load_scratch(2);
4956 tmp2
= neon_load_reg(rm
, pass
);
4959 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4963 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4964 gen_neon_addl(size
);
4966 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4967 gen_neon_subl(size
);
4969 case 5: case 7: /* VABAL, VABDL */
4970 switch ((size
<< 1) | u
) {
4972 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4975 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4978 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4981 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4984 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4987 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4994 case 8: case 9: case 10: case 11: case 12: case 13:
4995 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4996 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5000 case 14: /* Polynomial VMULL */
5001 cpu_abort(env
, "Polynomial VMULL not implemented");
5003 default: /* 15 is RESERVED. */
5006 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5008 if (op
== 10 || op
== 11) {
5009 gen_neon_negl(cpu_V0
, size
);
5013 neon_load_reg64(cpu_V1
, rd
+ pass
);
5017 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5018 gen_neon_addl(size
);
5020 case 9: case 11: /* VQDMLAL, VQDMLSL */
5021 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5022 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5025 case 13: /* VQDMULL */
5026 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5031 neon_store_reg64(cpu_V0
, rd
+ pass
);
5032 } else if (op
== 4 || op
== 6) {
5033 /* Narrowing operation. */
5038 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5041 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5044 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5045 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5052 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5055 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5058 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5059 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5060 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5068 neon_store_reg(rd
, 0, tmp3
);
5069 neon_store_reg(rd
, 1, tmp
);
5072 /* Write back the result. */
5073 neon_store_reg64(cpu_V0
, rd
+ pass
);
5077 /* Two registers and a scalar. */
5079 case 0: /* Integer VMLA scalar */
5080 case 1: /* Float VMLA scalar */
5081 case 4: /* Integer VMLS scalar */
5082 case 5: /* Floating point VMLS scalar */
5083 case 8: /* Integer VMUL scalar */
5084 case 9: /* Floating point VMUL scalar */
5085 case 12: /* VQDMULH scalar */
5086 case 13: /* VQRDMULH scalar */
5087 tmp
= neon_get_scalar(size
, rm
);
5088 neon_store_scratch(0, tmp
);
5089 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5090 tmp
= neon_load_scratch(0);
5091 tmp2
= neon_load_reg(rn
, pass
);
5094 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5096 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5098 } else if (op
== 13) {
5100 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5102 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5104 } else if (op
& 1) {
5105 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5108 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5109 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5110 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5117 tmp2
= neon_load_reg(rd
, pass
);
5120 gen_neon_add(size
, tmp
, tmp2
);
5123 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5126 gen_neon_rsb(size
, tmp
, tmp2
);
5129 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5136 neon_store_reg(rd
, pass
, tmp
);
5139 case 2: /* VMLAL sclar */
5140 case 3: /* VQDMLAL scalar */
5141 case 6: /* VMLSL scalar */
5142 case 7: /* VQDMLSL scalar */
5143 case 10: /* VMULL scalar */
5144 case 11: /* VQDMULL scalar */
5145 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5148 tmp2
= neon_get_scalar(size
, rm
);
5149 tmp3
= neon_load_reg(rn
, 1);
5151 for (pass
= 0; pass
< 2; pass
++) {
5153 tmp
= neon_load_reg(rn
, 0);
5157 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5159 if (op
== 6 || op
== 7) {
5160 gen_neon_negl(cpu_V0
, size
);
5163 neon_load_reg64(cpu_V1
, rd
+ pass
);
5167 gen_neon_addl(size
);
5170 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5171 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5177 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5182 neon_store_reg64(cpu_V0
, rd
+ pass
);
5188 default: /* 14 and 15 are RESERVED */
5192 } else { /* size == 3 */
5195 imm
= (insn
>> 8) & 0xf;
5202 neon_load_reg64(cpu_V0
, rn
);
5204 neon_load_reg64(cpu_V1
, rn
+ 1);
5206 } else if (imm
== 8) {
5207 neon_load_reg64(cpu_V0
, rn
+ 1);
5209 neon_load_reg64(cpu_V1
, rm
);
5212 tmp64
= tcg_temp_new_i64();
5214 neon_load_reg64(cpu_V0
, rn
);
5215 neon_load_reg64(tmp64
, rn
+ 1);
5217 neon_load_reg64(cpu_V0
, rn
+ 1);
5218 neon_load_reg64(tmp64
, rm
);
5220 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5221 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5222 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5224 neon_load_reg64(cpu_V1
, rm
);
5226 neon_load_reg64(cpu_V1
, rm
+ 1);
5229 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5230 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5231 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5234 neon_load_reg64(cpu_V0
, rn
);
5235 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5236 neon_load_reg64(cpu_V1
, rm
);
5237 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5238 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5240 neon_store_reg64(cpu_V0
, rd
);
5242 neon_store_reg64(cpu_V1
, rd
+ 1);
5244 } else if ((insn
& (1 << 11)) == 0) {
5245 /* Two register misc. */
5246 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5247 size
= (insn
>> 18) & 3;
5249 case 0: /* VREV64 */
5252 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5253 tmp
= neon_load_reg(rm
, pass
* 2);
5254 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5256 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5257 case 1: gen_swap_half(tmp
); break;
5258 case 2: /* no-op */ break;
5261 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5263 neon_store_reg(rd
, pass
* 2, tmp2
);
5266 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5267 case 1: gen_swap_half(tmp2
); break;
5270 neon_store_reg(rd
, pass
* 2, tmp2
);
5274 case 4: case 5: /* VPADDL */
5275 case 12: case 13: /* VPADAL */
5278 for (pass
= 0; pass
< q
+ 1; pass
++) {
5279 tmp
= neon_load_reg(rm
, pass
* 2);
5280 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5281 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5282 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5284 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5285 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5286 case 2: tcg_gen_add_i64(CPU_V001
); break;
5291 neon_load_reg64(cpu_V1
, rd
+ pass
);
5292 gen_neon_addl(size
);
5294 neon_store_reg64(cpu_V0
, rd
+ pass
);
5299 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5300 tmp
= neon_load_reg(rm
, n
);
5301 tmp2
= neon_load_reg(rd
, n
+ 1);
5302 neon_store_reg(rm
, n
, tmp2
);
5303 neon_store_reg(rd
, n
+ 1, tmp
);
5311 Rd A3 A2 A1 A0 B2 B0 A2 A0
5312 Rm B3 B2 B1 B0 B3 B1 A3 A1
5316 gen_neon_unzip(rd
, q
, 0, size
);
5317 gen_neon_unzip(rm
, q
, 4, size
);
5319 static int unzip_order_q
[8] =
5320 {0, 2, 4, 6, 1, 3, 5, 7};
5321 for (n
= 0; n
< 8; n
++) {
5322 int reg
= (n
< 4) ? rd
: rm
;
5323 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5324 neon_store_reg(reg
, n
% 4, tmp
);
5327 static int unzip_order
[4] =
5329 for (n
= 0; n
< 4; n
++) {
5330 int reg
= (n
< 2) ? rd
: rm
;
5331 tmp
= neon_load_scratch(unzip_order
[n
]);
5332 neon_store_reg(reg
, n
% 2, tmp
);
5338 Rd A3 A2 A1 A0 B1 A1 B0 A0
5339 Rm B3 B2 B1 B0 B3 A3 B2 A2
5343 count
= (q
? 4 : 2);
5344 for (n
= 0; n
< count
; n
++) {
5345 tmp
= neon_load_reg(rd
, n
);
5346 tmp2
= neon_load_reg(rd
, n
);
5348 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5349 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5350 case 2: /* no-op */; break;
5353 neon_store_scratch(n
* 2, tmp
);
5354 neon_store_scratch(n
* 2 + 1, tmp2
);
5356 for (n
= 0; n
< count
* 2; n
++) {
5357 int reg
= (n
< count
) ? rd
: rm
;
5358 tmp
= neon_load_scratch(n
);
5359 neon_store_reg(reg
, n
% count
, tmp
);
5362 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5366 for (pass
= 0; pass
< 2; pass
++) {
5367 neon_load_reg64(cpu_V0
, rm
+ pass
);
5369 if (op
== 36 && q
== 0) {
5370 gen_neon_narrow(size
, tmp
, cpu_V0
);
5372 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5374 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5379 neon_store_reg(rd
, 0, tmp2
);
5380 neon_store_reg(rd
, 1, tmp
);
5384 case 38: /* VSHLL */
5387 tmp
= neon_load_reg(rm
, 0);
5388 tmp2
= neon_load_reg(rm
, 1);
5389 for (pass
= 0; pass
< 2; pass
++) {
5392 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5393 neon_store_reg64(cpu_V0
, rd
+ pass
);
5398 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5399 if (op
== 30 || op
== 31 || op
>= 58) {
5400 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5401 neon_reg_offset(rm
, pass
));
5404 tmp
= neon_load_reg(rm
, pass
);
5407 case 1: /* VREV32 */
5409 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5410 case 1: gen_swap_half(tmp
); break;
5414 case 2: /* VREV16 */
5421 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5422 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5423 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5429 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5430 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5431 case 2: gen_helper_clz(tmp
, tmp
); break;
5438 gen_helper_neon_cnt_u8(tmp
, tmp
);
5443 tcg_gen_not_i32(tmp
, tmp
);
5445 case 14: /* VQABS */
5447 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5448 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5449 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5453 case 15: /* VQNEG */
5455 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5456 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5457 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5461 case 16: case 19: /* VCGT #0, VCLE #0 */
5462 tmp2
= tcg_const_i32(0);
5464 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5465 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5466 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5469 tcg_temp_free(tmp2
);
5471 tcg_gen_not_i32(tmp
, tmp
);
5473 case 17: case 20: /* VCGE #0, VCLT #0 */
5474 tmp2
= tcg_const_i32(0);
5476 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5477 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5478 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5481 tcg_temp_free(tmp2
);
5483 tcg_gen_not_i32(tmp
, tmp
);
5485 case 18: /* VCEQ #0 */
5486 tmp2
= tcg_const_i32(0);
5488 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5489 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5490 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5493 tcg_temp_free(tmp2
);
5497 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5498 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5499 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5506 tmp2
= tcg_const_i32(0);
5507 gen_neon_rsb(size
, tmp
, tmp2
);
5508 tcg_temp_free(tmp2
);
5510 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5511 tmp2
= tcg_const_i32(0);
5512 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5513 tcg_temp_free(tmp2
);
5515 tcg_gen_not_i32(tmp
, tmp
);
5517 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5518 tmp2
= tcg_const_i32(0);
5519 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5520 tcg_temp_free(tmp2
);
5522 tcg_gen_not_i32(tmp
, tmp
);
5524 case 26: /* Float VCEQ #0 */
5525 tmp2
= tcg_const_i32(0);
5526 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5527 tcg_temp_free(tmp2
);
5529 case 30: /* Float VABS */
5532 case 31: /* Float VNEG */
5536 tmp2
= neon_load_reg(rd
, pass
);
5537 neon_store_reg(rm
, pass
, tmp2
);
5540 tmp2
= neon_load_reg(rd
, pass
);
5542 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5543 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5547 neon_store_reg(rm
, pass
, tmp2
);
5549 case 56: /* Integer VRECPE */
5550 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5552 case 57: /* Integer VRSQRTE */
5553 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5555 case 58: /* Float VRECPE */
5556 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5558 case 59: /* Float VRSQRTE */
5559 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5561 case 60: /* VCVT.F32.S32 */
5564 case 61: /* VCVT.F32.U32 */
5567 case 62: /* VCVT.S32.F32 */
5570 case 63: /* VCVT.U32.F32 */
5574 /* Reserved: 21, 29, 39-56 */
5577 if (op
== 30 || op
== 31 || op
>= 58) {
5578 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5579 neon_reg_offset(rd
, pass
));
5581 neon_store_reg(rd
, pass
, tmp
);
5586 } else if ((insn
& (1 << 10)) == 0) {
5588 n
= ((insn
>> 5) & 0x18) + 8;
5589 if (insn
& (1 << 6)) {
5590 tmp
= neon_load_reg(rd
, 0);
5593 tcg_gen_movi_i32(tmp
, 0);
5595 tmp2
= neon_load_reg(rm
, 0);
5596 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5599 if (insn
& (1 << 6)) {
5600 tmp
= neon_load_reg(rd
, 1);
5603 tcg_gen_movi_i32(tmp
, 0);
5605 tmp3
= neon_load_reg(rm
, 1);
5606 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5608 neon_store_reg(rd
, 0, tmp2
);
5609 neon_store_reg(rd
, 1, tmp3
);
5611 } else if ((insn
& 0x380) == 0) {
5613 if (insn
& (1 << 19)) {
5614 tmp
= neon_load_reg(rm
, 1);
5616 tmp
= neon_load_reg(rm
, 0);
5618 if (insn
& (1 << 16)) {
5619 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5620 } else if (insn
& (1 << 17)) {
5621 if ((insn
>> 18) & 1)
5622 gen_neon_dup_high16(tmp
);
5624 gen_neon_dup_low16(tmp
);
5626 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5628 tcg_gen_mov_i32(tmp2
, tmp
);
5629 neon_store_reg(rd
, pass
, tmp2
);
5640 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5642 int crn
= (insn
>> 16) & 0xf;
5643 int crm
= insn
& 0xf;
5644 int op1
= (insn
>> 21) & 7;
5645 int op2
= (insn
>> 5) & 7;
5646 int rt
= (insn
>> 12) & 0xf;
5649 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5650 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5654 tmp
= load_cpu_field(teecr
);
5655 store_reg(s
, rt
, tmp
);
5658 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5660 if (IS_USER(s
) && (env
->teecr
& 1))
5662 tmp
= load_cpu_field(teehbr
);
5663 store_reg(s
, rt
, tmp
);
5667 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5668 op1
, crn
, crm
, op2
);
5672 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5674 int crn
= (insn
>> 16) & 0xf;
5675 int crm
= insn
& 0xf;
5676 int op1
= (insn
>> 21) & 7;
5677 int op2
= (insn
>> 5) & 7;
5678 int rt
= (insn
>> 12) & 0xf;
5681 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5682 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5686 tmp
= load_reg(s
, rt
);
5687 gen_helper_set_teecr(cpu_env
, tmp
);
5691 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5693 if (IS_USER(s
) && (env
->teecr
& 1))
5695 tmp
= load_reg(s
, rt
);
5696 store_cpu_field(tmp
, teehbr
);
5700 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5701 op1
, crn
, crm
, op2
);
5705 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5709 cpnum
= (insn
>> 8) & 0xf;
5710 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5711 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5717 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5718 return disas_iwmmxt_insn(env
, s
, insn
);
5719 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5720 return disas_dsp_insn(env
, s
, insn
);
5725 return disas_vfp_insn (env
, s
, insn
);
5727 /* Coprocessors 7-15 are architecturally reserved by ARM.
5728 Unfortunately Intel decided to ignore this. */
5729 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5731 if (insn
& (1 << 20))
5732 return disas_cp14_read(env
, s
, insn
);
5734 return disas_cp14_write(env
, s
, insn
);
5736 return disas_cp15_insn (env
, s
, insn
);
5739 /* Unknown coprocessor. See if the board has hooked it. */
5740 return disas_cp_insn (env
, s
, insn
);
5745 /* Store a 64-bit value to a register pair. Clobbers val. */
5746 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5750 tcg_gen_trunc_i64_i32(tmp
, val
);
5751 store_reg(s
, rlow
, tmp
);
5753 tcg_gen_shri_i64(val
, val
, 32);
5754 tcg_gen_trunc_i64_i32(tmp
, val
);
5755 store_reg(s
, rhigh
, tmp
);
5758 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5759 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5764 /* Load value and extend to 64 bits. */
5765 tmp
= tcg_temp_new_i64();
5766 tmp2
= load_reg(s
, rlow
);
5767 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5769 tcg_gen_add_i64(val
, val
, tmp
);
5772 /* load and add a 64-bit value from a register pair. */
5773 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5779 /* Load 64-bit value rd:rn. */
5780 tmpl
= load_reg(s
, rlow
);
5781 tmph
= load_reg(s
, rhigh
);
5782 tmp
= tcg_temp_new_i64();
5783 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5786 tcg_gen_add_i64(val
, val
, tmp
);
5789 /* Set N and Z flags from a 64-bit value. */
5790 static void gen_logicq_cc(TCGv_i64 val
)
5792 TCGv tmp
= new_tmp();
5793 gen_helper_logicq_cc(tmp
, val
);
5798 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5800 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5807 insn
= ldl_code(s
->pc
);
5810 /* M variants do not implement ARM mode. */
5815 /* Unconditional instructions. */
5816 if (((insn
>> 25) & 7) == 1) {
5817 /* NEON Data processing. */
5818 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5821 if (disas_neon_data_insn(env
, s
, insn
))
5825 if ((insn
& 0x0f100000) == 0x04000000) {
5826 /* NEON load/store. */
5827 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5830 if (disas_neon_ls_insn(env
, s
, insn
))
5834 if ((insn
& 0x0d70f000) == 0x0550f000)
5836 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5839 if (insn
& (1 << 9)) {
5840 /* BE8 mode not implemented. */
5844 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5845 switch ((insn
>> 4) & 0xf) {
5848 gen_helper_clrex(cpu_env
);
5854 /* We don't emulate caches so these are a no-op. */
5859 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5865 op1
= (insn
& 0x1f);
5866 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5867 addr
= load_reg(s
, 13);
5870 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5872 i
= (insn
>> 23) & 3;
5874 case 0: offset
= -4; break; /* DA */
5875 case 1: offset
= 0; break; /* IA */
5876 case 2: offset
= -8; break; /* DB */
5877 case 3: offset
= 4; break; /* IB */
5881 tcg_gen_addi_i32(addr
, addr
, offset
);
5882 tmp
= load_reg(s
, 14);
5883 gen_st32(tmp
, addr
, 0);
5884 tmp
= load_cpu_field(spsr
);
5885 tcg_gen_addi_i32(addr
, addr
, 4);
5886 gen_st32(tmp
, addr
, 0);
5887 if (insn
& (1 << 21)) {
5888 /* Base writeback. */
5890 case 0: offset
= -8; break;
5891 case 1: offset
= 4; break;
5892 case 2: offset
= -4; break;
5893 case 3: offset
= 0; break;
5897 tcg_gen_addi_i32(addr
, addr
, offset
);
5898 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5899 store_reg(s
, 13, addr
);
5901 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5907 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5913 rn
= (insn
>> 16) & 0xf;
5914 addr
= load_reg(s
, rn
);
5915 i
= (insn
>> 23) & 3;
5917 case 0: offset
= -4; break; /* DA */
5918 case 1: offset
= 0; break; /* IA */
5919 case 2: offset
= -8; break; /* DB */
5920 case 3: offset
= 4; break; /* IB */
5924 tcg_gen_addi_i32(addr
, addr
, offset
);
5925 /* Load PC into tmp and CPSR into tmp2. */
5926 tmp
= gen_ld32(addr
, 0);
5927 tcg_gen_addi_i32(addr
, addr
, 4);
5928 tmp2
= gen_ld32(addr
, 0);
5929 if (insn
& (1 << 21)) {
5930 /* Base writeback. */
5932 case 0: offset
= -8; break;
5933 case 1: offset
= 4; break;
5934 case 2: offset
= -4; break;
5935 case 3: offset
= 0; break;
5939 tcg_gen_addi_i32(addr
, addr
, offset
);
5940 store_reg(s
, rn
, addr
);
5944 gen_rfe(s
, tmp
, tmp2
);
5946 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5947 /* branch link and change to thumb (blx <offset>) */
5950 val
= (uint32_t)s
->pc
;
5952 tcg_gen_movi_i32(tmp
, val
);
5953 store_reg(s
, 14, tmp
);
5954 /* Sign-extend the 24-bit offset */
5955 offset
= (((int32_t)insn
) << 8) >> 8;
5956 /* offset * 4 + bit24 * 2 + (thumb bit) */
5957 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5958 /* pipeline offset */
5962 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5963 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5964 /* iWMMXt register transfer. */
5965 if (env
->cp15
.c15_cpar
& (1 << 1))
5966 if (!disas_iwmmxt_insn(env
, s
, insn
))
5969 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5970 /* Coprocessor double register transfer. */
5971 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5972 /* Additional coprocessor register transfer. */
5973 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5976 /* cps (privileged) */
5980 if (insn
& (1 << 19)) {
5981 if (insn
& (1 << 8))
5983 if (insn
& (1 << 7))
5985 if (insn
& (1 << 6))
5987 if (insn
& (1 << 18))
5990 if (insn
& (1 << 17)) {
5992 val
|= (insn
& 0x1f);
5995 gen_set_psr_im(s
, mask
, 0, val
);
6002 /* if not always execute, we generate a conditional jump to
6004 s
->condlabel
= gen_new_label();
6005 gen_test_cc(cond
^ 1, s
->condlabel
);
6008 if ((insn
& 0x0f900000) == 0x03000000) {
6009 if ((insn
& (1 << 21)) == 0) {
6011 rd
= (insn
>> 12) & 0xf;
6012 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6013 if ((insn
& (1 << 22)) == 0) {
6016 tcg_gen_movi_i32(tmp
, val
);
6019 tmp
= load_reg(s
, rd
);
6020 tcg_gen_ext16u_i32(tmp
, tmp
);
6021 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6023 store_reg(s
, rd
, tmp
);
6025 if (((insn
>> 12) & 0xf) != 0xf)
6027 if (((insn
>> 16) & 0xf) == 0) {
6028 gen_nop_hint(s
, insn
& 0xff);
6030 /* CPSR = immediate */
6032 shift
= ((insn
>> 8) & 0xf) * 2;
6034 val
= (val
>> shift
) | (val
<< (32 - shift
));
6035 i
= ((insn
& (1 << 22)) != 0);
6036 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6040 } else if ((insn
& 0x0f900000) == 0x01000000
6041 && (insn
& 0x00000090) != 0x00000090) {
6042 /* miscellaneous instructions */
6043 op1
= (insn
>> 21) & 3;
6044 sh
= (insn
>> 4) & 0xf;
6047 case 0x0: /* move program status register */
6050 tmp
= load_reg(s
, rm
);
6051 i
= ((op1
& 2) != 0);
6052 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6056 rd
= (insn
>> 12) & 0xf;
6060 tmp
= load_cpu_field(spsr
);
6063 gen_helper_cpsr_read(tmp
);
6065 store_reg(s
, rd
, tmp
);
6070 /* branch/exchange thumb (bx). */
6071 tmp
= load_reg(s
, rm
);
6073 } else if (op1
== 3) {
6075 rd
= (insn
>> 12) & 0xf;
6076 tmp
= load_reg(s
, rm
);
6077 gen_helper_clz(tmp
, tmp
);
6078 store_reg(s
, rd
, tmp
);
6086 /* Trivial implementation equivalent to bx. */
6087 tmp
= load_reg(s
, rm
);
6097 /* branch link/exchange thumb (blx) */
6098 tmp
= load_reg(s
, rm
);
6100 tcg_gen_movi_i32(tmp2
, s
->pc
);
6101 store_reg(s
, 14, tmp2
);
6104 case 0x5: /* saturating add/subtract */
6105 rd
= (insn
>> 12) & 0xf;
6106 rn
= (insn
>> 16) & 0xf;
6107 tmp
= load_reg(s
, rm
);
6108 tmp2
= load_reg(s
, rn
);
6110 gen_helper_double_saturate(tmp2
, tmp2
);
6112 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6114 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6116 store_reg(s
, rd
, tmp
);
6119 gen_set_condexec(s
);
6120 gen_set_pc_im(s
->pc
- 4);
6121 gen_exception(EXCP_BKPT
);
6122 s
->is_jmp
= DISAS_JUMP
;
6124 case 0x8: /* signed multiply */
6128 rs
= (insn
>> 8) & 0xf;
6129 rn
= (insn
>> 12) & 0xf;
6130 rd
= (insn
>> 16) & 0xf;
6132 /* (32 * 16) >> 16 */
6133 tmp
= load_reg(s
, rm
);
6134 tmp2
= load_reg(s
, rs
);
6136 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6139 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6140 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6142 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6143 if ((sh
& 2) == 0) {
6144 tmp2
= load_reg(s
, rn
);
6145 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6148 store_reg(s
, rd
, tmp
);
6151 tmp
= load_reg(s
, rm
);
6152 tmp2
= load_reg(s
, rs
);
6153 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6156 tmp64
= tcg_temp_new_i64();
6157 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6159 gen_addq(s
, tmp64
, rn
, rd
);
6160 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6163 tmp2
= load_reg(s
, rn
);
6164 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6167 store_reg(s
, rd
, tmp
);
6174 } else if (((insn
& 0x0e000000) == 0 &&
6175 (insn
& 0x00000090) != 0x90) ||
6176 ((insn
& 0x0e000000) == (1 << 25))) {
6177 int set_cc
, logic_cc
, shiftop
;
6179 op1
= (insn
>> 21) & 0xf;
6180 set_cc
= (insn
>> 20) & 1;
6181 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6183 /* data processing instruction */
6184 if (insn
& (1 << 25)) {
6185 /* immediate operand */
6187 shift
= ((insn
>> 8) & 0xf) * 2;
6189 val
= (val
>> shift
) | (val
<< (32 - shift
));
6192 tcg_gen_movi_i32(tmp2
, val
);
6193 if (logic_cc
&& shift
) {
6194 gen_set_CF_bit31(tmp2
);
6199 tmp2
= load_reg(s
, rm
);
6200 shiftop
= (insn
>> 5) & 3;
6201 if (!(insn
& (1 << 4))) {
6202 shift
= (insn
>> 7) & 0x1f;
6203 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6205 rs
= (insn
>> 8) & 0xf;
6206 tmp
= load_reg(s
, rs
);
6207 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6210 if (op1
!= 0x0f && op1
!= 0x0d) {
6211 rn
= (insn
>> 16) & 0xf;
6212 tmp
= load_reg(s
, rn
);
6216 rd
= (insn
>> 12) & 0xf;
6219 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6223 store_reg_bx(env
, s
, rd
, tmp
);
6226 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6230 store_reg_bx(env
, s
, rd
, tmp
);
6233 if (set_cc
&& rd
== 15) {
6234 /* SUBS r15, ... is used for exception return. */
6238 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6239 gen_exception_return(s
, tmp
);
6242 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6244 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6246 store_reg_bx(env
, s
, rd
, tmp
);
6251 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6253 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6255 store_reg_bx(env
, s
, rd
, tmp
);
6259 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6261 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6263 store_reg_bx(env
, s
, rd
, tmp
);
6267 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6269 gen_add_carry(tmp
, tmp
, tmp2
);
6271 store_reg_bx(env
, s
, rd
, tmp
);
6275 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6277 gen_sub_carry(tmp
, tmp
, tmp2
);
6279 store_reg_bx(env
, s
, rd
, tmp
);
6283 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6285 gen_sub_carry(tmp
, tmp2
, tmp
);
6287 store_reg_bx(env
, s
, rd
, tmp
);
6291 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6298 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6305 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6311 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6316 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6320 store_reg_bx(env
, s
, rd
, tmp
);
6323 if (logic_cc
&& rd
== 15) {
6324 /* MOVS r15, ... is used for exception return. */
6328 gen_exception_return(s
, tmp2
);
6333 store_reg_bx(env
, s
, rd
, tmp2
);
6337 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6341 store_reg_bx(env
, s
, rd
, tmp
);
6345 tcg_gen_not_i32(tmp2
, tmp2
);
6349 store_reg_bx(env
, s
, rd
, tmp2
);
6352 if (op1
!= 0x0f && op1
!= 0x0d) {
6356 /* other instructions */
6357 op1
= (insn
>> 24) & 0xf;
6361 /* multiplies, extra load/stores */
6362 sh
= (insn
>> 5) & 3;
6365 rd
= (insn
>> 16) & 0xf;
6366 rn
= (insn
>> 12) & 0xf;
6367 rs
= (insn
>> 8) & 0xf;
6369 op1
= (insn
>> 20) & 0xf;
6371 case 0: case 1: case 2: case 3: case 6:
6373 tmp
= load_reg(s
, rs
);
6374 tmp2
= load_reg(s
, rm
);
6375 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6377 if (insn
& (1 << 22)) {
6378 /* Subtract (mls) */
6380 tmp2
= load_reg(s
, rn
);
6381 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6383 } else if (insn
& (1 << 21)) {
6385 tmp2
= load_reg(s
, rn
);
6386 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6389 if (insn
& (1 << 20))
6391 store_reg(s
, rd
, tmp
);
6395 tmp
= load_reg(s
, rs
);
6396 tmp2
= load_reg(s
, rm
);
6397 if (insn
& (1 << 22))
6398 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6400 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6401 if (insn
& (1 << 21)) /* mult accumulate */
6402 gen_addq(s
, tmp64
, rn
, rd
);
6403 if (!(insn
& (1 << 23))) { /* double accumulate */
6405 gen_addq_lo(s
, tmp64
, rn
);
6406 gen_addq_lo(s
, tmp64
, rd
);
6408 if (insn
& (1 << 20))
6409 gen_logicq_cc(tmp64
);
6410 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6414 rn
= (insn
>> 16) & 0xf;
6415 rd
= (insn
>> 12) & 0xf;
6416 if (insn
& (1 << 23)) {
6417 /* load/store exclusive */
6418 op1
= (insn
>> 21) & 0x3;
6423 addr
= tcg_temp_local_new_i32();
6424 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
6425 if (insn
& (1 << 20)) {
6426 gen_helper_mark_exclusive(cpu_env
, addr
);
6429 tmp
= gen_ld32(addr
, IS_USER(s
));
6431 case 1: /* ldrexd */
6432 tmp
= gen_ld32(addr
, IS_USER(s
));
6433 store_reg(s
, rd
, tmp
);
6434 tcg_gen_addi_i32(addr
, addr
, 4);
6435 tmp
= gen_ld32(addr
, IS_USER(s
));
6438 case 2: /* ldrexb */
6439 tmp
= gen_ld8u(addr
, IS_USER(s
));
6441 case 3: /* ldrexh */
6442 tmp
= gen_ld16u(addr
, IS_USER(s
));
6447 store_reg(s
, rd
, tmp
);
6449 int label
= gen_new_label();
6451 tmp2
= tcg_temp_local_new_i32();
6452 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6453 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6454 tmp
= load_reg(s
,rm
);
6457 gen_st32(tmp
, addr
, IS_USER(s
));
6459 case 1: /* strexd */
6460 gen_st32(tmp
, addr
, IS_USER(s
));
6461 tcg_gen_addi_i32(addr
, addr
, 4);
6462 tmp
= load_reg(s
, rm
+ 1);
6463 gen_st32(tmp
, addr
, IS_USER(s
));
6465 case 2: /* strexb */
6466 gen_st8(tmp
, addr
, IS_USER(s
));
6468 case 3: /* strexh */
6469 gen_st16(tmp
, addr
, IS_USER(s
));
6474 gen_set_label(label
);
6475 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6476 tcg_temp_free(tmp2
);
6478 tcg_temp_free(addr
);
6480 /* SWP instruction */
6483 /* ??? This is not really atomic. However we know
6484 we never have multiple CPUs running in parallel,
6485 so it is good enough. */
6486 addr
= load_reg(s
, rn
);
6487 tmp
= load_reg(s
, rm
);
6488 if (insn
& (1 << 22)) {
6489 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6490 gen_st8(tmp
, addr
, IS_USER(s
));
6492 tmp2
= gen_ld32(addr
, IS_USER(s
));
6493 gen_st32(tmp
, addr
, IS_USER(s
));
6496 store_reg(s
, rd
, tmp2
);
6502 /* Misc load/store */
6503 rn
= (insn
>> 16) & 0xf;
6504 rd
= (insn
>> 12) & 0xf;
6505 addr
= load_reg(s
, rn
);
6506 if (insn
& (1 << 24))
6507 gen_add_datah_offset(s
, insn
, 0, addr
);
6509 if (insn
& (1 << 20)) {
6513 tmp
= gen_ld16u(addr
, IS_USER(s
));
6516 tmp
= gen_ld8s(addr
, IS_USER(s
));
6520 tmp
= gen_ld16s(addr
, IS_USER(s
));
6524 } else if (sh
& 2) {
6528 tmp
= load_reg(s
, rd
);
6529 gen_st32(tmp
, addr
, IS_USER(s
));
6530 tcg_gen_addi_i32(addr
, addr
, 4);
6531 tmp
= load_reg(s
, rd
+ 1);
6532 gen_st32(tmp
, addr
, IS_USER(s
));
6536 tmp
= gen_ld32(addr
, IS_USER(s
));
6537 store_reg(s
, rd
, tmp
);
6538 tcg_gen_addi_i32(addr
, addr
, 4);
6539 tmp
= gen_ld32(addr
, IS_USER(s
));
6543 address_offset
= -4;
6546 tmp
= load_reg(s
, rd
);
6547 gen_st16(tmp
, addr
, IS_USER(s
));
6550 /* Perform base writeback before the loaded value to
6551 ensure correct behavior with overlapping index registers.
6552 ldrd with base writeback is is undefined if the
6553 destination and index registers overlap. */
6554 if (!(insn
& (1 << 24))) {
6555 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6556 store_reg(s
, rn
, addr
);
6557 } else if (insn
& (1 << 21)) {
6559 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6560 store_reg(s
, rn
, addr
);
6565 /* Complete the load. */
6566 store_reg(s
, rd
, tmp
);
6575 if (insn
& (1 << 4)) {
6577 /* Armv6 Media instructions. */
6579 rn
= (insn
>> 16) & 0xf;
6580 rd
= (insn
>> 12) & 0xf;
6581 rs
= (insn
>> 8) & 0xf;
6582 switch ((insn
>> 23) & 3) {
6583 case 0: /* Parallel add/subtract. */
6584 op1
= (insn
>> 20) & 7;
6585 tmp
= load_reg(s
, rn
);
6586 tmp2
= load_reg(s
, rm
);
6587 sh
= (insn
>> 5) & 7;
6588 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6590 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6592 store_reg(s
, rd
, tmp
);
6595 if ((insn
& 0x00700020) == 0) {
6596 /* Halfword pack. */
6597 tmp
= load_reg(s
, rn
);
6598 tmp2
= load_reg(s
, rm
);
6599 shift
= (insn
>> 7) & 0x1f;
6600 if (insn
& (1 << 6)) {
6604 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6605 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6606 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6610 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6611 tcg_gen_ext16u_i32(tmp
, tmp
);
6612 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6614 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6616 store_reg(s
, rd
, tmp
);
6617 } else if ((insn
& 0x00200020) == 0x00200000) {
6619 tmp
= load_reg(s
, rm
);
6620 shift
= (insn
>> 7) & 0x1f;
6621 if (insn
& (1 << 6)) {
6624 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6626 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6628 sh
= (insn
>> 16) & 0x1f;
6630 if (insn
& (1 << 22))
6631 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6633 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6635 store_reg(s
, rd
, tmp
);
6636 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6638 tmp
= load_reg(s
, rm
);
6639 sh
= (insn
>> 16) & 0x1f;
6641 if (insn
& (1 << 22))
6642 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6644 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6646 store_reg(s
, rd
, tmp
);
6647 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6649 tmp
= load_reg(s
, rn
);
6650 tmp2
= load_reg(s
, rm
);
6652 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6653 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6656 store_reg(s
, rd
, tmp
);
6657 } else if ((insn
& 0x000003e0) == 0x00000060) {
6658 tmp
= load_reg(s
, rm
);
6659 shift
= (insn
>> 10) & 3;
6660 /* ??? In many cases it's not neccessary to do a
6661 rotate, a shift is sufficient. */
6663 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6664 op1
= (insn
>> 20) & 7;
6666 case 0: gen_sxtb16(tmp
); break;
6667 case 2: gen_sxtb(tmp
); break;
6668 case 3: gen_sxth(tmp
); break;
6669 case 4: gen_uxtb16(tmp
); break;
6670 case 6: gen_uxtb(tmp
); break;
6671 case 7: gen_uxth(tmp
); break;
6672 default: goto illegal_op
;
6675 tmp2
= load_reg(s
, rn
);
6676 if ((op1
& 3) == 0) {
6677 gen_add16(tmp
, tmp2
);
6679 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6683 store_reg(s
, rd
, tmp
);
6684 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6686 tmp
= load_reg(s
, rm
);
6687 if (insn
& (1 << 22)) {
6688 if (insn
& (1 << 7)) {
6692 gen_helper_rbit(tmp
, tmp
);
6695 if (insn
& (1 << 7))
6698 tcg_gen_bswap32_i32(tmp
, tmp
);
6700 store_reg(s
, rd
, tmp
);
6705 case 2: /* Multiplies (Type 3). */
6706 tmp
= load_reg(s
, rm
);
6707 tmp2
= load_reg(s
, rs
);
6708 if (insn
& (1 << 20)) {
6709 /* Signed multiply most significant [accumulate]. */
6710 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6711 if (insn
& (1 << 5))
6712 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6713 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6715 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6717 tmp2
= load_reg(s
, rd
);
6718 if (insn
& (1 << 6)) {
6719 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6721 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6725 store_reg(s
, rn
, tmp
);
6727 if (insn
& (1 << 5))
6728 gen_swap_half(tmp2
);
6729 gen_smul_dual(tmp
, tmp2
);
6730 /* This addition cannot overflow. */
6731 if (insn
& (1 << 6)) {
6732 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6734 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6737 if (insn
& (1 << 22)) {
6738 /* smlald, smlsld */
6739 tmp64
= tcg_temp_new_i64();
6740 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6742 gen_addq(s
, tmp64
, rd
, rn
);
6743 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6745 /* smuad, smusd, smlad, smlsd */
6748 tmp2
= load_reg(s
, rd
);
6749 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6752 store_reg(s
, rn
, tmp
);
6757 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6759 case 0: /* Unsigned sum of absolute differences. */
6761 tmp
= load_reg(s
, rm
);
6762 tmp2
= load_reg(s
, rs
);
6763 gen_helper_usad8(tmp
, tmp
, tmp2
);
6766 tmp2
= load_reg(s
, rd
);
6767 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6770 store_reg(s
, rn
, tmp
);
6772 case 0x20: case 0x24: case 0x28: case 0x2c:
6773 /* Bitfield insert/clear. */
6775 shift
= (insn
>> 7) & 0x1f;
6776 i
= (insn
>> 16) & 0x1f;
6780 tcg_gen_movi_i32(tmp
, 0);
6782 tmp
= load_reg(s
, rm
);
6785 tmp2
= load_reg(s
, rd
);
6786 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6789 store_reg(s
, rd
, tmp
);
6791 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6792 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6794 tmp
= load_reg(s
, rm
);
6795 shift
= (insn
>> 7) & 0x1f;
6796 i
= ((insn
>> 16) & 0x1f) + 1;
6801 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6803 gen_sbfx(tmp
, shift
, i
);
6806 store_reg(s
, rd
, tmp
);
6816 /* Check for undefined extension instructions
6817 * per the ARM Bible IE:
6818 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6820 sh
= (0xf << 20) | (0xf << 4);
6821 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6825 /* load/store byte/word */
6826 rn
= (insn
>> 16) & 0xf;
6827 rd
= (insn
>> 12) & 0xf;
6828 tmp2
= load_reg(s
, rn
);
6829 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6830 if (insn
& (1 << 24))
6831 gen_add_data_offset(s
, insn
, tmp2
);
6832 if (insn
& (1 << 20)) {
6834 if (insn
& (1 << 22)) {
6835 tmp
= gen_ld8u(tmp2
, i
);
6837 tmp
= gen_ld32(tmp2
, i
);
6841 tmp
= load_reg(s
, rd
);
6842 if (insn
& (1 << 22))
6843 gen_st8(tmp
, tmp2
, i
);
6845 gen_st32(tmp
, tmp2
, i
);
6847 if (!(insn
& (1 << 24))) {
6848 gen_add_data_offset(s
, insn
, tmp2
);
6849 store_reg(s
, rn
, tmp2
);
6850 } else if (insn
& (1 << 21)) {
6851 store_reg(s
, rn
, tmp2
);
6855 if (insn
& (1 << 20)) {
6856 /* Complete the load. */
6860 store_reg(s
, rd
, tmp
);
6866 int j
, n
, user
, loaded_base
;
6868 /* load/store multiple words */
6869 /* XXX: store correct base if write back */
6871 if (insn
& (1 << 22)) {
6873 goto illegal_op
; /* only usable in supervisor mode */
6875 if ((insn
& (1 << 15)) == 0)
6878 rn
= (insn
>> 16) & 0xf;
6879 addr
= load_reg(s
, rn
);
6881 /* compute total size */
6883 TCGV_UNUSED(loaded_var
);
6886 if (insn
& (1 << i
))
6889 /* XXX: test invalid n == 0 case ? */
6890 if (insn
& (1 << 23)) {
6891 if (insn
& (1 << 24)) {
6893 tcg_gen_addi_i32(addr
, addr
, 4);
6895 /* post increment */
6898 if (insn
& (1 << 24)) {
6900 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6902 /* post decrement */
6904 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6909 if (insn
& (1 << i
)) {
6910 if (insn
& (1 << 20)) {
6912 tmp
= gen_ld32(addr
, IS_USER(s
));
6916 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6918 } else if (i
== rn
) {
6922 store_reg(s
, i
, tmp
);
6927 /* special case: r15 = PC + 8 */
6928 val
= (long)s
->pc
+ 4;
6930 tcg_gen_movi_i32(tmp
, val
);
6933 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6935 tmp
= load_reg(s
, i
);
6937 gen_st32(tmp
, addr
, IS_USER(s
));
6940 /* no need to add after the last transfer */
6942 tcg_gen_addi_i32(addr
, addr
, 4);
6945 if (insn
& (1 << 21)) {
6947 if (insn
& (1 << 23)) {
6948 if (insn
& (1 << 24)) {
6951 /* post increment */
6952 tcg_gen_addi_i32(addr
, addr
, 4);
6955 if (insn
& (1 << 24)) {
6958 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6960 /* post decrement */
6961 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6964 store_reg(s
, rn
, addr
);
6969 store_reg(s
, rn
, loaded_var
);
6971 if ((insn
& (1 << 22)) && !user
) {
6972 /* Restore CPSR from SPSR. */
6973 tmp
= load_cpu_field(spsr
);
6974 gen_set_cpsr(tmp
, 0xffffffff);
6976 s
->is_jmp
= DISAS_UPDATE
;
6985 /* branch (and link) */
6986 val
= (int32_t)s
->pc
;
6987 if (insn
& (1 << 24)) {
6989 tcg_gen_movi_i32(tmp
, val
);
6990 store_reg(s
, 14, tmp
);
6992 offset
= (((int32_t)insn
<< 8) >> 8);
6993 val
+= (offset
<< 2) + 4;
7001 if (disas_coproc_insn(env
, s
, insn
))
7006 gen_set_pc_im(s
->pc
);
7007 s
->is_jmp
= DISAS_SWI
;
7011 gen_set_condexec(s
);
7012 gen_set_pc_im(s
->pc
- 4);
7013 gen_exception(EXCP_UDEF
);
7014 s
->is_jmp
= DISAS_JUMP
;
7020 /* Return true if this is a Thumb-2 logical op. */
7022 thumb2_logic_op(int op
)
7027 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7028 then set condition code flags based on the result of the operation.
7029 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7030 to the high bit of T1.
7031 Returns zero if the opcode is valid. */
7034 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7041 tcg_gen_and_i32(t0
, t0
, t1
);
7045 tcg_gen_bic_i32(t0
, t0
, t1
);
7049 tcg_gen_or_i32(t0
, t0
, t1
);
7053 tcg_gen_not_i32(t1
, t1
);
7054 tcg_gen_or_i32(t0
, t0
, t1
);
7058 tcg_gen_xor_i32(t0
, t0
, t1
);
7063 gen_helper_add_cc(t0
, t0
, t1
);
7065 tcg_gen_add_i32(t0
, t0
, t1
);
7069 gen_helper_adc_cc(t0
, t0
, t1
);
7075 gen_helper_sbc_cc(t0
, t0
, t1
);
7077 gen_sub_carry(t0
, t0
, t1
);
7081 gen_helper_sub_cc(t0
, t0
, t1
);
7083 tcg_gen_sub_i32(t0
, t0
, t1
);
7087 gen_helper_sub_cc(t0
, t1
, t0
);
7089 tcg_gen_sub_i32(t0
, t1
, t0
);
7091 default: /* 5, 6, 7, 9, 12, 15. */
7097 gen_set_CF_bit31(t1
);
7102 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7104 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7106 uint32_t insn
, imm
, shift
, offset
;
7107 uint32_t rd
, rn
, rm
, rs
;
7118 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7119 || arm_feature (env
, ARM_FEATURE_M
))) {
7120 /* Thumb-1 cores may need to treat bl and blx as a pair of
7121 16-bit instructions to get correct prefetch abort behavior. */
7123 if ((insn
& (1 << 12)) == 0) {
7124 /* Second half of blx. */
7125 offset
= ((insn
& 0x7ff) << 1);
7126 tmp
= load_reg(s
, 14);
7127 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7128 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7131 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7132 store_reg(s
, 14, tmp2
);
7136 if (insn
& (1 << 11)) {
7137 /* Second half of bl. */
7138 offset
= ((insn
& 0x7ff) << 1) | 1;
7139 tmp
= load_reg(s
, 14);
7140 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7143 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7144 store_reg(s
, 14, tmp2
);
7148 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7149 /* Instruction spans a page boundary. Implement it as two
7150 16-bit instructions in case the second half causes an
7152 offset
= ((int32_t)insn
<< 21) >> 9;
7153 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7156 /* Fall through to 32-bit decode. */
7159 insn
= lduw_code(s
->pc
);
7161 insn
|= (uint32_t)insn_hw1
<< 16;
7163 if ((insn
& 0xf800e800) != 0xf000e800) {
7167 rn
= (insn
>> 16) & 0xf;
7168 rs
= (insn
>> 12) & 0xf;
7169 rd
= (insn
>> 8) & 0xf;
7171 switch ((insn
>> 25) & 0xf) {
7172 case 0: case 1: case 2: case 3:
7173 /* 16-bit instructions. Should never happen. */
7176 if (insn
& (1 << 22)) {
7177 /* Other load/store, table branch. */
7178 if (insn
& 0x01200000) {
7179 /* Load/store doubleword. */
7182 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7184 addr
= load_reg(s
, rn
);
7186 offset
= (insn
& 0xff) * 4;
7187 if ((insn
& (1 << 23)) == 0)
7189 if (insn
& (1 << 24)) {
7190 tcg_gen_addi_i32(addr
, addr
, offset
);
7193 if (insn
& (1 << 20)) {
7195 tmp
= gen_ld32(addr
, IS_USER(s
));
7196 store_reg(s
, rs
, tmp
);
7197 tcg_gen_addi_i32(addr
, addr
, 4);
7198 tmp
= gen_ld32(addr
, IS_USER(s
));
7199 store_reg(s
, rd
, tmp
);
7202 tmp
= load_reg(s
, rs
);
7203 gen_st32(tmp
, addr
, IS_USER(s
));
7204 tcg_gen_addi_i32(addr
, addr
, 4);
7205 tmp
= load_reg(s
, rd
);
7206 gen_st32(tmp
, addr
, IS_USER(s
));
7208 if (insn
& (1 << 21)) {
7209 /* Base writeback. */
7212 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7213 store_reg(s
, rn
, addr
);
7217 } else if ((insn
& (1 << 23)) == 0) {
7218 /* Load/store exclusive word. */
7219 addr
= tcg_temp_local_new();
7220 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7221 if (insn
& (1 << 20)) {
7222 gen_helper_mark_exclusive(cpu_env
, addr
);
7223 tmp
= gen_ld32(addr
, IS_USER(s
));
7224 store_reg(s
, rd
, tmp
);
7226 int label
= gen_new_label();
7227 tmp2
= tcg_temp_local_new();
7228 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7229 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7230 tmp
= load_reg(s
, rs
);
7231 gen_st32(tmp
, addr
, IS_USER(s
));
7232 gen_set_label(label
);
7233 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7234 tcg_temp_free(tmp2
);
7236 tcg_temp_free(addr
);
7237 } else if ((insn
& (1 << 6)) == 0) {
7241 tcg_gen_movi_i32(addr
, s
->pc
);
7243 addr
= load_reg(s
, rn
);
7245 tmp
= load_reg(s
, rm
);
7246 tcg_gen_add_i32(addr
, addr
, tmp
);
7247 if (insn
& (1 << 4)) {
7249 tcg_gen_add_i32(addr
, addr
, tmp
);
7251 tmp
= gen_ld16u(addr
, IS_USER(s
));
7254 tmp
= gen_ld8u(addr
, IS_USER(s
));
7257 tcg_gen_shli_i32(tmp
, tmp
, 1);
7258 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7259 store_reg(s
, 15, tmp
);
7261 /* Load/store exclusive byte/halfword/doubleword. */
7262 /* ??? These are not really atomic. However we know
7263 we never have multiple CPUs running in parallel,
7264 so it is good enough. */
7265 op
= (insn
>> 4) & 0x3;
7266 addr
= tcg_temp_local_new();
7267 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7268 if (insn
& (1 << 20)) {
7269 gen_helper_mark_exclusive(cpu_env
, addr
);
7272 tmp
= gen_ld8u(addr
, IS_USER(s
));
7275 tmp
= gen_ld16u(addr
, IS_USER(s
));
7278 tmp
= gen_ld32(addr
, IS_USER(s
));
7279 tcg_gen_addi_i32(addr
, addr
, 4);
7280 tmp2
= gen_ld32(addr
, IS_USER(s
));
7281 store_reg(s
, rd
, tmp2
);
7286 store_reg(s
, rs
, tmp
);
7288 int label
= gen_new_label();
7289 tmp2
= tcg_temp_local_new();
7290 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7291 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7292 tmp
= load_reg(s
, rs
);
7295 gen_st8(tmp
, addr
, IS_USER(s
));
7298 gen_st16(tmp
, addr
, IS_USER(s
));
7301 gen_st32(tmp
, addr
, IS_USER(s
));
7302 tcg_gen_addi_i32(addr
, addr
, 4);
7303 tmp
= load_reg(s
, rd
);
7304 gen_st32(tmp
, addr
, IS_USER(s
));
7309 gen_set_label(label
);
7310 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7311 tcg_temp_free(tmp2
);
7313 tcg_temp_free(addr
);
7316 /* Load/store multiple, RFE, SRS. */
7317 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7318 /* Not available in user mode. */
7321 if (insn
& (1 << 20)) {
7323 addr
= load_reg(s
, rn
);
7324 if ((insn
& (1 << 24)) == 0)
7325 tcg_gen_addi_i32(addr
, addr
, -8);
7326 /* Load PC into tmp and CPSR into tmp2. */
7327 tmp
= gen_ld32(addr
, 0);
7328 tcg_gen_addi_i32(addr
, addr
, 4);
7329 tmp2
= gen_ld32(addr
, 0);
7330 if (insn
& (1 << 21)) {
7331 /* Base writeback. */
7332 if (insn
& (1 << 24)) {
7333 tcg_gen_addi_i32(addr
, addr
, 4);
7335 tcg_gen_addi_i32(addr
, addr
, -4);
7337 store_reg(s
, rn
, addr
);
7341 gen_rfe(s
, tmp
, tmp2
);
7345 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7346 addr
= load_reg(s
, 13);
7349 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7351 if ((insn
& (1 << 24)) == 0) {
7352 tcg_gen_addi_i32(addr
, addr
, -8);
7354 tmp
= load_reg(s
, 14);
7355 gen_st32(tmp
, addr
, 0);
7356 tcg_gen_addi_i32(addr
, addr
, 4);
7358 gen_helper_cpsr_read(tmp
);
7359 gen_st32(tmp
, addr
, 0);
7360 if (insn
& (1 << 21)) {
7361 if ((insn
& (1 << 24)) == 0) {
7362 tcg_gen_addi_i32(addr
, addr
, -4);
7364 tcg_gen_addi_i32(addr
, addr
, 4);
7366 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7367 store_reg(s
, 13, addr
);
7369 gen_helper_set_r13_banked(cpu_env
,
7370 tcg_const_i32(op
), addr
);
7378 /* Load/store multiple. */
7379 addr
= load_reg(s
, rn
);
7381 for (i
= 0; i
< 16; i
++) {
7382 if (insn
& (1 << i
))
7385 if (insn
& (1 << 24)) {
7386 tcg_gen_addi_i32(addr
, addr
, -offset
);
7389 for (i
= 0; i
< 16; i
++) {
7390 if ((insn
& (1 << i
)) == 0)
7392 if (insn
& (1 << 20)) {
7394 tmp
= gen_ld32(addr
, IS_USER(s
));
7398 store_reg(s
, i
, tmp
);
7402 tmp
= load_reg(s
, i
);
7403 gen_st32(tmp
, addr
, IS_USER(s
));
7405 tcg_gen_addi_i32(addr
, addr
, 4);
7407 if (insn
& (1 << 21)) {
7408 /* Base register writeback. */
7409 if (insn
& (1 << 24)) {
7410 tcg_gen_addi_i32(addr
, addr
, -offset
);
7412 /* Fault if writeback register is in register list. */
7413 if (insn
& (1 << rn
))
7415 store_reg(s
, rn
, addr
);
7422 case 5: /* Data processing register constant shift. */
7425 tcg_gen_movi_i32(tmp
, 0);
7427 tmp
= load_reg(s
, rn
);
7429 tmp2
= load_reg(s
, rm
);
7430 op
= (insn
>> 21) & 0xf;
7431 shiftop
= (insn
>> 4) & 3;
7432 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7433 conds
= (insn
& (1 << 20)) != 0;
7434 logic_cc
= (conds
&& thumb2_logic_op(op
));
7435 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7436 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7440 store_reg(s
, rd
, tmp
);
7445 case 13: /* Misc data processing. */
7446 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7447 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7450 case 0: /* Register controlled shift. */
7451 tmp
= load_reg(s
, rn
);
7452 tmp2
= load_reg(s
, rm
);
7453 if ((insn
& 0x70) != 0)
7455 op
= (insn
>> 21) & 3;
7456 logic_cc
= (insn
& (1 << 20)) != 0;
7457 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7460 store_reg_bx(env
, s
, rd
, tmp
);
7462 case 1: /* Sign/zero extend. */
7463 tmp
= load_reg(s
, rm
);
7464 shift
= (insn
>> 4) & 3;
7465 /* ??? In many cases it's not neccessary to do a
7466 rotate, a shift is sufficient. */
7468 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7469 op
= (insn
>> 20) & 7;
7471 case 0: gen_sxth(tmp
); break;
7472 case 1: gen_uxth(tmp
); break;
7473 case 2: gen_sxtb16(tmp
); break;
7474 case 3: gen_uxtb16(tmp
); break;
7475 case 4: gen_sxtb(tmp
); break;
7476 case 5: gen_uxtb(tmp
); break;
7477 default: goto illegal_op
;
7480 tmp2
= load_reg(s
, rn
);
7481 if ((op
>> 1) == 1) {
7482 gen_add16(tmp
, tmp2
);
7484 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7488 store_reg(s
, rd
, tmp
);
7490 case 2: /* SIMD add/subtract. */
7491 op
= (insn
>> 20) & 7;
7492 shift
= (insn
>> 4) & 7;
7493 if ((op
& 3) == 3 || (shift
& 3) == 3)
7495 tmp
= load_reg(s
, rn
);
7496 tmp2
= load_reg(s
, rm
);
7497 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7499 store_reg(s
, rd
, tmp
);
7501 case 3: /* Other data processing. */
7502 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7504 /* Saturating add/subtract. */
7505 tmp
= load_reg(s
, rn
);
7506 tmp2
= load_reg(s
, rm
);
7508 gen_helper_double_saturate(tmp
, tmp
);
7510 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7512 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7515 tmp
= load_reg(s
, rn
);
7517 case 0x0a: /* rbit */
7518 gen_helper_rbit(tmp
, tmp
);
7520 case 0x08: /* rev */
7521 tcg_gen_bswap32_i32(tmp
, tmp
);
7523 case 0x09: /* rev16 */
7526 case 0x0b: /* revsh */
7529 case 0x10: /* sel */
7530 tmp2
= load_reg(s
, rm
);
7532 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7533 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7537 case 0x18: /* clz */
7538 gen_helper_clz(tmp
, tmp
);
7544 store_reg(s
, rd
, tmp
);
7546 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7547 op
= (insn
>> 4) & 0xf;
7548 tmp
= load_reg(s
, rn
);
7549 tmp2
= load_reg(s
, rm
);
7550 switch ((insn
>> 20) & 7) {
7551 case 0: /* 32 x 32 -> 32 */
7552 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7555 tmp2
= load_reg(s
, rs
);
7557 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7559 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7563 case 1: /* 16 x 16 -> 32 */
7564 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7567 tmp2
= load_reg(s
, rs
);
7568 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7572 case 2: /* Dual multiply add. */
7573 case 4: /* Dual multiply subtract. */
7575 gen_swap_half(tmp2
);
7576 gen_smul_dual(tmp
, tmp2
);
7577 /* This addition cannot overflow. */
7578 if (insn
& (1 << 22)) {
7579 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7581 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7586 tmp2
= load_reg(s
, rs
);
7587 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7591 case 3: /* 32 * 16 -> 32msb */
7593 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7596 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7597 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7599 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7602 tmp2
= load_reg(s
, rs
);
7603 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7607 case 5: case 6: /* 32 * 32 -> 32msb */
7608 gen_imull(tmp
, tmp2
);
7609 if (insn
& (1 << 5)) {
7610 gen_roundqd(tmp
, tmp2
);
7617 tmp2
= load_reg(s
, rs
);
7618 if (insn
& (1 << 21)) {
7619 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7621 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7626 case 7: /* Unsigned sum of absolute differences. */
7627 gen_helper_usad8(tmp
, tmp
, tmp2
);
7630 tmp2
= load_reg(s
, rs
);
7631 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7636 store_reg(s
, rd
, tmp
);
7638 case 6: case 7: /* 64-bit multiply, Divide. */
7639 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7640 tmp
= load_reg(s
, rn
);
7641 tmp2
= load_reg(s
, rm
);
7642 if ((op
& 0x50) == 0x10) {
7644 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7647 gen_helper_udiv(tmp
, tmp
, tmp2
);
7649 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7651 store_reg(s
, rd
, tmp
);
7652 } else if ((op
& 0xe) == 0xc) {
7653 /* Dual multiply accumulate long. */
7655 gen_swap_half(tmp2
);
7656 gen_smul_dual(tmp
, tmp2
);
7658 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7660 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7664 tmp64
= tcg_temp_new_i64();
7665 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7667 gen_addq(s
, tmp64
, rs
, rd
);
7668 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7671 /* Unsigned 64-bit multiply */
7672 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7676 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7678 tmp64
= tcg_temp_new_i64();
7679 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7682 /* Signed 64-bit multiply */
7683 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7688 gen_addq_lo(s
, tmp64
, rs
);
7689 gen_addq_lo(s
, tmp64
, rd
);
7690 } else if (op
& 0x40) {
7691 /* 64-bit accumulate. */
7692 gen_addq(s
, tmp64
, rs
, rd
);
7694 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7699 case 6: case 7: case 14: case 15:
7701 if (((insn
>> 24) & 3) == 3) {
7702 /* Translate into the equivalent ARM encoding. */
7703 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7704 if (disas_neon_data_insn(env
, s
, insn
))
7707 if (insn
& (1 << 28))
7709 if (disas_coproc_insn (env
, s
, insn
))
7713 case 8: case 9: case 10: case 11:
7714 if (insn
& (1 << 15)) {
7715 /* Branches, misc control. */
7716 if (insn
& 0x5000) {
7717 /* Unconditional branch. */
7718 /* signextend(hw1[10:0]) -> offset[:12]. */
7719 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7720 /* hw1[10:0] -> offset[11:1]. */
7721 offset
|= (insn
& 0x7ff) << 1;
7722 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7723 offset[24:22] already have the same value because of the
7724 sign extension above. */
7725 offset
^= ((~insn
) & (1 << 13)) << 10;
7726 offset
^= ((~insn
) & (1 << 11)) << 11;
7728 if (insn
& (1 << 14)) {
7729 /* Branch and link. */
7730 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7734 if (insn
& (1 << 12)) {
7739 offset
&= ~(uint32_t)2;
7740 gen_bx_im(s
, offset
);
7742 } else if (((insn
>> 23) & 7) == 7) {
7744 if (insn
& (1 << 13))
7747 if (insn
& (1 << 26)) {
7748 /* Secure monitor call (v6Z) */
7749 goto illegal_op
; /* not implemented. */
7751 op
= (insn
>> 20) & 7;
7753 case 0: /* msr cpsr. */
7755 tmp
= load_reg(s
, rn
);
7756 addr
= tcg_const_i32(insn
& 0xff);
7757 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7762 case 1: /* msr spsr. */
7765 tmp
= load_reg(s
, rn
);
7767 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7771 case 2: /* cps, nop-hint. */
7772 if (((insn
>> 8) & 7) == 0) {
7773 gen_nop_hint(s
, insn
& 0xff);
7775 /* Implemented as NOP in user mode. */
7780 if (insn
& (1 << 10)) {
7781 if (insn
& (1 << 7))
7783 if (insn
& (1 << 6))
7785 if (insn
& (1 << 5))
7787 if (insn
& (1 << 9))
7788 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7790 if (insn
& (1 << 8)) {
7792 imm
|= (insn
& 0x1f);
7795 gen_set_psr_im(s
, offset
, 0, imm
);
7798 case 3: /* Special control operations. */
7799 op
= (insn
>> 4) & 0xf;
7802 gen_helper_clrex(cpu_env
);
7807 /* These execute as NOPs. */
7815 /* Trivial implementation equivalent to bx. */
7816 tmp
= load_reg(s
, rn
);
7819 case 5: /* Exception return. */
7820 /* Unpredictable in user mode. */
7822 case 6: /* mrs cpsr. */
7825 addr
= tcg_const_i32(insn
& 0xff);
7826 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7828 gen_helper_cpsr_read(tmp
);
7830 store_reg(s
, rd
, tmp
);
7832 case 7: /* mrs spsr. */
7833 /* Not accessible in user mode. */
7834 if (IS_USER(s
) || IS_M(env
))
7836 tmp
= load_cpu_field(spsr
);
7837 store_reg(s
, rd
, tmp
);
7842 /* Conditional branch. */
7843 op
= (insn
>> 22) & 0xf;
7844 /* Generate a conditional jump to next instruction. */
7845 s
->condlabel
= gen_new_label();
7846 gen_test_cc(op
^ 1, s
->condlabel
);
7849 /* offset[11:1] = insn[10:0] */
7850 offset
= (insn
& 0x7ff) << 1;
7851 /* offset[17:12] = insn[21:16]. */
7852 offset
|= (insn
& 0x003f0000) >> 4;
7853 /* offset[31:20] = insn[26]. */
7854 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7855 /* offset[18] = insn[13]. */
7856 offset
|= (insn
& (1 << 13)) << 5;
7857 /* offset[19] = insn[11]. */
7858 offset
|= (insn
& (1 << 11)) << 8;
7860 /* jump to the offset */
7861 gen_jmp(s
, s
->pc
+ offset
);
7864 /* Data processing immediate. */
7865 if (insn
& (1 << 25)) {
7866 if (insn
& (1 << 24)) {
7867 if (insn
& (1 << 20))
7869 /* Bitfield/Saturate. */
7870 op
= (insn
>> 21) & 7;
7872 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7875 tcg_gen_movi_i32(tmp
, 0);
7877 tmp
= load_reg(s
, rn
);
7880 case 2: /* Signed bitfield extract. */
7882 if (shift
+ imm
> 32)
7885 gen_sbfx(tmp
, shift
, imm
);
7887 case 6: /* Unsigned bitfield extract. */
7889 if (shift
+ imm
> 32)
7892 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7894 case 3: /* Bitfield insert/clear. */
7897 imm
= imm
+ 1 - shift
;
7899 tmp2
= load_reg(s
, rd
);
7900 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7906 default: /* Saturate. */
7909 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7911 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7913 tmp2
= tcg_const_i32(imm
);
7916 if ((op
& 1) && shift
== 0)
7917 gen_helper_usat16(tmp
, tmp
, tmp2
);
7919 gen_helper_usat(tmp
, tmp
, tmp2
);
7922 if ((op
& 1) && shift
== 0)
7923 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7925 gen_helper_ssat(tmp
, tmp
, tmp2
);
7929 store_reg(s
, rd
, tmp
);
7931 imm
= ((insn
& 0x04000000) >> 15)
7932 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7933 if (insn
& (1 << 22)) {
7934 /* 16-bit immediate. */
7935 imm
|= (insn
>> 4) & 0xf000;
7936 if (insn
& (1 << 23)) {
7938 tmp
= load_reg(s
, rd
);
7939 tcg_gen_ext16u_i32(tmp
, tmp
);
7940 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7944 tcg_gen_movi_i32(tmp
, imm
);
7947 /* Add/sub 12-bit immediate. */
7949 offset
= s
->pc
& ~(uint32_t)3;
7950 if (insn
& (1 << 23))
7955 tcg_gen_movi_i32(tmp
, offset
);
7957 tmp
= load_reg(s
, rn
);
7958 if (insn
& (1 << 23))
7959 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7961 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7964 store_reg(s
, rd
, tmp
);
7967 int shifter_out
= 0;
7968 /* modified 12-bit immediate. */
7969 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7970 imm
= (insn
& 0xff);
7973 /* Nothing to do. */
7975 case 1: /* 00XY00XY */
7978 case 2: /* XY00XY00 */
7982 case 3: /* XYXYXYXY */
7986 default: /* Rotated constant. */
7987 shift
= (shift
<< 1) | (imm
>> 7);
7989 imm
= imm
<< (32 - shift
);
7994 tcg_gen_movi_i32(tmp2
, imm
);
7995 rn
= (insn
>> 16) & 0xf;
7998 tcg_gen_movi_i32(tmp
, 0);
8000 tmp
= load_reg(s
, rn
);
8002 op
= (insn
>> 21) & 0xf;
8003 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8004 shifter_out
, tmp
, tmp2
))
8007 rd
= (insn
>> 8) & 0xf;
8009 store_reg(s
, rd
, tmp
);
8016 case 12: /* Load/store single data item. */
8021 if ((insn
& 0x01100000) == 0x01000000) {
8022 if (disas_neon_ls_insn(env
, s
, insn
))
8030 /* s->pc has already been incremented by 4. */
8031 imm
= s
->pc
& 0xfffffffc;
8032 if (insn
& (1 << 23))
8033 imm
+= insn
& 0xfff;
8035 imm
-= insn
& 0xfff;
8036 tcg_gen_movi_i32(addr
, imm
);
8038 addr
= load_reg(s
, rn
);
8039 if (insn
& (1 << 23)) {
8040 /* Positive offset. */
8042 tcg_gen_addi_i32(addr
, addr
, imm
);
8044 op
= (insn
>> 8) & 7;
8047 case 0: case 8: /* Shifted Register. */
8048 shift
= (insn
>> 4) & 0xf;
8051 tmp
= load_reg(s
, rm
);
8053 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8054 tcg_gen_add_i32(addr
, addr
, tmp
);
8057 case 4: /* Negative offset. */
8058 tcg_gen_addi_i32(addr
, addr
, -imm
);
8060 case 6: /* User privilege. */
8061 tcg_gen_addi_i32(addr
, addr
, imm
);
8064 case 1: /* Post-decrement. */
8067 case 3: /* Post-increment. */
8071 case 5: /* Pre-decrement. */
8074 case 7: /* Pre-increment. */
8075 tcg_gen_addi_i32(addr
, addr
, imm
);
8083 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8084 if (insn
& (1 << 20)) {
8086 if (rs
== 15 && op
!= 2) {
8089 /* Memory hint. Implemented as NOP. */
8092 case 0: tmp
= gen_ld8u(addr
, user
); break;
8093 case 4: tmp
= gen_ld8s(addr
, user
); break;
8094 case 1: tmp
= gen_ld16u(addr
, user
); break;
8095 case 5: tmp
= gen_ld16s(addr
, user
); break;
8096 case 2: tmp
= gen_ld32(addr
, user
); break;
8097 default: goto illegal_op
;
8102 store_reg(s
, rs
, tmp
);
8109 tmp
= load_reg(s
, rs
);
8111 case 0: gen_st8(tmp
, addr
, user
); break;
8112 case 1: gen_st16(tmp
, addr
, user
); break;
8113 case 2: gen_st32(tmp
, addr
, user
); break;
8114 default: goto illegal_op
;
8118 tcg_gen_addi_i32(addr
, addr
, imm
);
8120 store_reg(s
, rn
, addr
);
8134 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8136 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8143 if (s
->condexec_mask
) {
8144 cond
= s
->condexec_cond
;
8145 s
->condlabel
= gen_new_label();
8146 gen_test_cc(cond
^ 1, s
->condlabel
);
8150 insn
= lduw_code(s
->pc
);
8153 switch (insn
>> 12) {
8157 op
= (insn
>> 11) & 3;
8160 rn
= (insn
>> 3) & 7;
8161 tmp
= load_reg(s
, rn
);
8162 if (insn
& (1 << 10)) {
8165 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8168 rm
= (insn
>> 6) & 7;
8169 tmp2
= load_reg(s
, rm
);
8171 if (insn
& (1 << 9)) {
8172 if (s
->condexec_mask
)
8173 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8175 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8177 if (s
->condexec_mask
)
8178 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8180 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8183 store_reg(s
, rd
, tmp
);
8185 /* shift immediate */
8186 rm
= (insn
>> 3) & 7;
8187 shift
= (insn
>> 6) & 0x1f;
8188 tmp
= load_reg(s
, rm
);
8189 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8190 if (!s
->condexec_mask
)
8192 store_reg(s
, rd
, tmp
);
8196 /* arithmetic large immediate */
8197 op
= (insn
>> 11) & 3;
8198 rd
= (insn
>> 8) & 0x7;
8199 if (op
== 0) { /* mov */
8201 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8202 if (!s
->condexec_mask
)
8204 store_reg(s
, rd
, tmp
);
8206 tmp
= load_reg(s
, rd
);
8208 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8211 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8216 if (s
->condexec_mask
)
8217 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8219 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8221 store_reg(s
, rd
, tmp
);
8224 if (s
->condexec_mask
)
8225 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8227 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8229 store_reg(s
, rd
, tmp
);
8235 if (insn
& (1 << 11)) {
8236 rd
= (insn
>> 8) & 7;
8237 /* load pc-relative. Bit 1 of PC is ignored. */
8238 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8239 val
&= ~(uint32_t)2;
8241 tcg_gen_movi_i32(addr
, val
);
8242 tmp
= gen_ld32(addr
, IS_USER(s
));
8244 store_reg(s
, rd
, tmp
);
8247 if (insn
& (1 << 10)) {
8248 /* data processing extended or blx */
8249 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8250 rm
= (insn
>> 3) & 0xf;
8251 op
= (insn
>> 8) & 3;
8254 tmp
= load_reg(s
, rd
);
8255 tmp2
= load_reg(s
, rm
);
8256 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8258 store_reg(s
, rd
, tmp
);
8261 tmp
= load_reg(s
, rd
);
8262 tmp2
= load_reg(s
, rm
);
8263 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8267 case 2: /* mov/cpy */
8268 tmp
= load_reg(s
, rm
);
8269 store_reg(s
, rd
, tmp
);
8271 case 3:/* branch [and link] exchange thumb register */
8272 tmp
= load_reg(s
, rm
);
8273 if (insn
& (1 << 7)) {
8274 val
= (uint32_t)s
->pc
| 1;
8276 tcg_gen_movi_i32(tmp2
, val
);
8277 store_reg(s
, 14, tmp2
);
8285 /* data processing register */
8287 rm
= (insn
>> 3) & 7;
8288 op
= (insn
>> 6) & 0xf;
8289 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8290 /* the shift/rotate ops want the operands backwards */
8299 if (op
== 9) { /* neg */
8301 tcg_gen_movi_i32(tmp
, 0);
8302 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8303 tmp
= load_reg(s
, rd
);
8308 tmp2
= load_reg(s
, rm
);
8311 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8312 if (!s
->condexec_mask
)
8316 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8317 if (!s
->condexec_mask
)
8321 if (s
->condexec_mask
) {
8322 gen_helper_shl(tmp2
, tmp2
, tmp
);
8324 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8329 if (s
->condexec_mask
) {
8330 gen_helper_shr(tmp2
, tmp2
, tmp
);
8332 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8337 if (s
->condexec_mask
) {
8338 gen_helper_sar(tmp2
, tmp2
, tmp
);
8340 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8345 if (s
->condexec_mask
)
8348 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8351 if (s
->condexec_mask
)
8352 gen_sub_carry(tmp
, tmp
, tmp2
);
8354 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8357 if (s
->condexec_mask
) {
8358 gen_helper_ror(tmp2
, tmp2
, tmp
);
8360 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8365 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8370 if (s
->condexec_mask
)
8371 tcg_gen_neg_i32(tmp
, tmp2
);
8373 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8376 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8380 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8384 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8385 if (!s
->condexec_mask
)
8389 gen_mull(tmp
, tmp2
);
8390 if (!s
->condexec_mask
)
8394 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8395 if (!s
->condexec_mask
)
8399 tcg_gen_not_i32(tmp2
, tmp2
);
8400 if (!s
->condexec_mask
)
8408 store_reg(s
, rm
, tmp2
);
8412 store_reg(s
, rd
, tmp
);
8422 /* load/store register offset. */
8424 rn
= (insn
>> 3) & 7;
8425 rm
= (insn
>> 6) & 7;
8426 op
= (insn
>> 9) & 7;
8427 addr
= load_reg(s
, rn
);
8428 tmp
= load_reg(s
, rm
);
8429 tcg_gen_add_i32(addr
, addr
, tmp
);
8432 if (op
< 3) /* store */
8433 tmp
= load_reg(s
, rd
);
8437 gen_st32(tmp
, addr
, IS_USER(s
));
8440 gen_st16(tmp
, addr
, IS_USER(s
));
8443 gen_st8(tmp
, addr
, IS_USER(s
));
8446 tmp
= gen_ld8s(addr
, IS_USER(s
));
8449 tmp
= gen_ld32(addr
, IS_USER(s
));
8452 tmp
= gen_ld16u(addr
, IS_USER(s
));
8455 tmp
= gen_ld8u(addr
, IS_USER(s
));
8458 tmp
= gen_ld16s(addr
, IS_USER(s
));
8461 if (op
>= 3) /* load */
8462 store_reg(s
, rd
, tmp
);
8467 /* load/store word immediate offset */
8469 rn
= (insn
>> 3) & 7;
8470 addr
= load_reg(s
, rn
);
8471 val
= (insn
>> 4) & 0x7c;
8472 tcg_gen_addi_i32(addr
, addr
, val
);
8474 if (insn
& (1 << 11)) {
8476 tmp
= gen_ld32(addr
, IS_USER(s
));
8477 store_reg(s
, rd
, tmp
);
8480 tmp
= load_reg(s
, rd
);
8481 gen_st32(tmp
, addr
, IS_USER(s
));
8487 /* load/store byte immediate offset */
8489 rn
= (insn
>> 3) & 7;
8490 addr
= load_reg(s
, rn
);
8491 val
= (insn
>> 6) & 0x1f;
8492 tcg_gen_addi_i32(addr
, addr
, val
);
8494 if (insn
& (1 << 11)) {
8496 tmp
= gen_ld8u(addr
, IS_USER(s
));
8497 store_reg(s
, rd
, tmp
);
8500 tmp
= load_reg(s
, rd
);
8501 gen_st8(tmp
, addr
, IS_USER(s
));
8507 /* load/store halfword immediate offset */
8509 rn
= (insn
>> 3) & 7;
8510 addr
= load_reg(s
, rn
);
8511 val
= (insn
>> 5) & 0x3e;
8512 tcg_gen_addi_i32(addr
, addr
, val
);
8514 if (insn
& (1 << 11)) {
8516 tmp
= gen_ld16u(addr
, IS_USER(s
));
8517 store_reg(s
, rd
, tmp
);
8520 tmp
= load_reg(s
, rd
);
8521 gen_st16(tmp
, addr
, IS_USER(s
));
8527 /* load/store from stack */
8528 rd
= (insn
>> 8) & 7;
8529 addr
= load_reg(s
, 13);
8530 val
= (insn
& 0xff) * 4;
8531 tcg_gen_addi_i32(addr
, addr
, val
);
8533 if (insn
& (1 << 11)) {
8535 tmp
= gen_ld32(addr
, IS_USER(s
));
8536 store_reg(s
, rd
, tmp
);
8539 tmp
= load_reg(s
, rd
);
8540 gen_st32(tmp
, addr
, IS_USER(s
));
8546 /* add to high reg */
8547 rd
= (insn
>> 8) & 7;
8548 if (insn
& (1 << 11)) {
8550 tmp
= load_reg(s
, 13);
8552 /* PC. bit 1 is ignored. */
8554 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8556 val
= (insn
& 0xff) * 4;
8557 tcg_gen_addi_i32(tmp
, tmp
, val
);
8558 store_reg(s
, rd
, tmp
);
8563 op
= (insn
>> 8) & 0xf;
8566 /* adjust stack pointer */
8567 tmp
= load_reg(s
, 13);
8568 val
= (insn
& 0x7f) * 4;
8569 if (insn
& (1 << 7))
8570 val
= -(int32_t)val
;
8571 tcg_gen_addi_i32(tmp
, tmp
, val
);
8572 store_reg(s
, 13, tmp
);
8575 case 2: /* sign/zero extend. */
8578 rm
= (insn
>> 3) & 7;
8579 tmp
= load_reg(s
, rm
);
8580 switch ((insn
>> 6) & 3) {
8581 case 0: gen_sxth(tmp
); break;
8582 case 1: gen_sxtb(tmp
); break;
8583 case 2: gen_uxth(tmp
); break;
8584 case 3: gen_uxtb(tmp
); break;
8586 store_reg(s
, rd
, tmp
);
8588 case 4: case 5: case 0xc: case 0xd:
8590 addr
= load_reg(s
, 13);
8591 if (insn
& (1 << 8))
8595 for (i
= 0; i
< 8; i
++) {
8596 if (insn
& (1 << i
))
8599 if ((insn
& (1 << 11)) == 0) {
8600 tcg_gen_addi_i32(addr
, addr
, -offset
);
8602 for (i
= 0; i
< 8; i
++) {
8603 if (insn
& (1 << i
)) {
8604 if (insn
& (1 << 11)) {
8606 tmp
= gen_ld32(addr
, IS_USER(s
));
8607 store_reg(s
, i
, tmp
);
8610 tmp
= load_reg(s
, i
);
8611 gen_st32(tmp
, addr
, IS_USER(s
));
8613 /* advance to the next address. */
8614 tcg_gen_addi_i32(addr
, addr
, 4);
8618 if (insn
& (1 << 8)) {
8619 if (insn
& (1 << 11)) {
8621 tmp
= gen_ld32(addr
, IS_USER(s
));
8622 /* don't set the pc until the rest of the instruction
8626 tmp
= load_reg(s
, 14);
8627 gen_st32(tmp
, addr
, IS_USER(s
));
8629 tcg_gen_addi_i32(addr
, addr
, 4);
8631 if ((insn
& (1 << 11)) == 0) {
8632 tcg_gen_addi_i32(addr
, addr
, -offset
);
8634 /* write back the new stack pointer */
8635 store_reg(s
, 13, addr
);
8636 /* set the new PC value */
8637 if ((insn
& 0x0900) == 0x0900)
8641 case 1: case 3: case 9: case 11: /* czb */
8643 tmp
= load_reg(s
, rm
);
8644 s
->condlabel
= gen_new_label();
8646 if (insn
& (1 << 11))
8647 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8649 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8651 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8652 val
= (uint32_t)s
->pc
+ 2;
8657 case 15: /* IT, nop-hint. */
8658 if ((insn
& 0xf) == 0) {
8659 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8663 s
->condexec_cond
= (insn
>> 4) & 0xe;
8664 s
->condexec_mask
= insn
& 0x1f;
8665 /* No actual code generated for this insn, just setup state. */
8668 case 0xe: /* bkpt */
8669 gen_set_condexec(s
);
8670 gen_set_pc_im(s
->pc
- 2);
8671 gen_exception(EXCP_BKPT
);
8672 s
->is_jmp
= DISAS_JUMP
;
8677 rn
= (insn
>> 3) & 0x7;
8679 tmp
= load_reg(s
, rn
);
8680 switch ((insn
>> 6) & 3) {
8681 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8682 case 1: gen_rev16(tmp
); break;
8683 case 3: gen_revsh(tmp
); break;
8684 default: goto illegal_op
;
8686 store_reg(s
, rd
, tmp
);
8694 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8697 addr
= tcg_const_i32(16);
8698 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8702 addr
= tcg_const_i32(17);
8703 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8707 if (insn
& (1 << 4))
8708 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8711 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8721 /* load/store multiple */
8722 rn
= (insn
>> 8) & 0x7;
8723 addr
= load_reg(s
, rn
);
8724 for (i
= 0; i
< 8; i
++) {
8725 if (insn
& (1 << i
)) {
8726 if (insn
& (1 << 11)) {
8728 tmp
= gen_ld32(addr
, IS_USER(s
));
8729 store_reg(s
, i
, tmp
);
8732 tmp
= load_reg(s
, i
);
8733 gen_st32(tmp
, addr
, IS_USER(s
));
8735 /* advance to the next address */
8736 tcg_gen_addi_i32(addr
, addr
, 4);
8739 /* Base register writeback. */
8740 if ((insn
& (1 << rn
)) == 0) {
8741 store_reg(s
, rn
, addr
);
8748 /* conditional branch or swi */
8749 cond
= (insn
>> 8) & 0xf;
8755 gen_set_condexec(s
);
8756 gen_set_pc_im(s
->pc
);
8757 s
->is_jmp
= DISAS_SWI
;
8760 /* generate a conditional jump to next instruction */
8761 s
->condlabel
= gen_new_label();
8762 gen_test_cc(cond
^ 1, s
->condlabel
);
8765 /* jump to the offset */
8766 val
= (uint32_t)s
->pc
+ 2;
8767 offset
= ((int32_t)insn
<< 24) >> 24;
8773 if (insn
& (1 << 11)) {
8774 if (disas_thumb2_insn(env
, s
, insn
))
8778 /* unconditional branch */
8779 val
= (uint32_t)s
->pc
;
8780 offset
= ((int32_t)insn
<< 21) >> 21;
8781 val
+= (offset
<< 1) + 2;
8786 if (disas_thumb2_insn(env
, s
, insn
))
8792 gen_set_condexec(s
);
8793 gen_set_pc_im(s
->pc
- 4);
8794 gen_exception(EXCP_UDEF
);
8795 s
->is_jmp
= DISAS_JUMP
;
8799 gen_set_condexec(s
);
8800 gen_set_pc_im(s
->pc
- 2);
8801 gen_exception(EXCP_UDEF
);
8802 s
->is_jmp
= DISAS_JUMP
;
8805 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8806 basic block 'tb'. If search_pc is TRUE, also generate PC
8807 information for each intermediate instruction. */
8808 static inline void gen_intermediate_code_internal(CPUState
*env
,
8809 TranslationBlock
*tb
,
8812 DisasContext dc1
, *dc
= &dc1
;
8814 uint16_t *gen_opc_end
;
8816 target_ulong pc_start
;
8817 uint32_t next_page_start
;
8821 /* generate intermediate code */
8828 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8830 dc
->is_jmp
= DISAS_NEXT
;
8832 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8834 dc
->thumb
= env
->thumb
;
8835 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8836 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8837 #if !defined(CONFIG_USER_ONLY)
8839 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8841 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8844 cpu_F0s
= tcg_temp_new_i32();
8845 cpu_F1s
= tcg_temp_new_i32();
8846 cpu_F0d
= tcg_temp_new_i64();
8847 cpu_F1d
= tcg_temp_new_i64();
8850 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8851 cpu_M0
= tcg_temp_new_i64();
8852 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8855 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8857 max_insns
= CF_COUNT_MASK
;
8860 /* Reset the conditional execution bits immediately. This avoids
8861 complications trying to do it at the end of the block. */
8862 if (env
->condexec_bits
)
8864 TCGv tmp
= new_tmp();
8865 tcg_gen_movi_i32(tmp
, 0);
8866 store_cpu_field(tmp
, condexec_bits
);
8869 #ifdef CONFIG_USER_ONLY
8870 /* Intercept jump to the magic kernel page. */
8871 if (dc
->pc
>= 0xffff0000) {
8872 /* We always get here via a jump, so know we are not in a
8873 conditional execution block. */
8874 gen_exception(EXCP_KERNEL_TRAP
);
8875 dc
->is_jmp
= DISAS_UPDATE
;
8879 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8880 /* We always get here via a jump, so know we are not in a
8881 conditional execution block. */
8882 gen_exception(EXCP_EXCEPTION_EXIT
);
8883 dc
->is_jmp
= DISAS_UPDATE
;
8888 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8889 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8890 if (bp
->pc
== dc
->pc
) {
8891 gen_set_condexec(dc
);
8892 gen_set_pc_im(dc
->pc
);
8893 gen_exception(EXCP_DEBUG
);
8894 dc
->is_jmp
= DISAS_JUMP
;
8895 /* Advance PC so that clearing the breakpoint will
8896 invalidate this TB. */
8898 goto done_generating
;
8904 j
= gen_opc_ptr
- gen_opc_buf
;
8908 gen_opc_instr_start
[lj
++] = 0;
8910 gen_opc_pc
[lj
] = dc
->pc
;
8911 gen_opc_instr_start
[lj
] = 1;
8912 gen_opc_icount
[lj
] = num_insns
;
8915 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8919 disas_thumb_insn(env
, dc
);
8920 if (dc
->condexec_mask
) {
8921 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8922 | ((dc
->condexec_mask
>> 4) & 1);
8923 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8924 if (dc
->condexec_mask
== 0) {
8925 dc
->condexec_cond
= 0;
8929 disas_arm_insn(env
, dc
);
8932 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8936 if (dc
->condjmp
&& !dc
->is_jmp
) {
8937 gen_set_label(dc
->condlabel
);
8940 /* Translation stops when a conditional branch is encountered.
8941 * Otherwise the subsequent code could get translated several times.
8942 * Also stop translation when a page boundary is reached. This
8943 * ensures prefetch aborts occur at the right place. */
8945 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8946 !env
->singlestep_enabled
&&
8948 dc
->pc
< next_page_start
&&
8949 num_insns
< max_insns
);
8951 if (tb
->cflags
& CF_LAST_IO
) {
8953 /* FIXME: This can theoretically happen with self-modifying
8955 cpu_abort(env
, "IO on conditional branch instruction");
8960 /* At this stage dc->condjmp will only be set when the skipped
8961 instruction was a conditional branch or trap, and the PC has
8962 already been written. */
8963 if (unlikely(env
->singlestep_enabled
)) {
8964 /* Make sure the pc is updated, and raise a debug exception. */
8966 gen_set_condexec(dc
);
8967 if (dc
->is_jmp
== DISAS_SWI
) {
8968 gen_exception(EXCP_SWI
);
8970 gen_exception(EXCP_DEBUG
);
8972 gen_set_label(dc
->condlabel
);
8974 if (dc
->condjmp
|| !dc
->is_jmp
) {
8975 gen_set_pc_im(dc
->pc
);
8978 gen_set_condexec(dc
);
8979 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8980 gen_exception(EXCP_SWI
);
8982 /* FIXME: Single stepping a WFI insn will not halt
8984 gen_exception(EXCP_DEBUG
);
8987 /* While branches must always occur at the end of an IT block,
8988 there are a few other things that can cause us to terminate
8989 the TB in the middel of an IT block:
8990 - Exception generating instructions (bkpt, swi, undefined).
8992 - Hardware watchpoints.
8993 Hardware breakpoints have already been handled and skip this code.
8995 gen_set_condexec(dc
);
8996 switch(dc
->is_jmp
) {
8998 gen_goto_tb(dc
, 1, dc
->pc
);
9003 /* indicate that the hash table must be used to find the next TB */
9007 /* nothing more to generate */
9013 gen_exception(EXCP_SWI
);
9017 gen_set_label(dc
->condlabel
);
9018 gen_set_condexec(dc
);
9019 gen_goto_tb(dc
, 1, dc
->pc
);
9025 gen_icount_end(tb
, num_insns
);
9026 *gen_opc_ptr
= INDEX_op_end
;
9029 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9030 qemu_log("----------------\n");
9031 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9032 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9037 j
= gen_opc_ptr
- gen_opc_buf
;
9040 gen_opc_instr_start
[lj
++] = 0;
9042 tb
->size
= dc
->pc
- pc_start
;
9043 tb
->icount
= num_insns
;
9047 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9049 gen_intermediate_code_internal(env
, tb
, 0);
9052 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9054 gen_intermediate_code_internal(env
, tb
, 1);
9057 static const char *cpu_mode_names
[16] = {
9058 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9059 "???", "???", "???", "und", "???", "???", "???", "sys"
9062 void cpu_dump_state(CPUState
*env
, FILE *f
,
9063 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9073 /* ??? This assumes float64 and double have the same layout.
9074 Oh well, it's only debug dumps. */
9083 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9085 cpu_fprintf(f
, "\n");
9087 cpu_fprintf(f
, " ");
9089 psr
= cpsr_read(env
);
9090 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9092 psr
& (1 << 31) ? 'N' : '-',
9093 psr
& (1 << 30) ? 'Z' : '-',
9094 psr
& (1 << 29) ? 'C' : '-',
9095 psr
& (1 << 28) ? 'V' : '-',
9096 psr
& CPSR_T
? 'T' : 'A',
9097 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9100 for (i
= 0; i
< 16; i
++) {
9101 d
.d
= env
->vfp
.regs
[i
];
9105 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9106 i
* 2, (int)s0
.i
, s0
.s
,
9107 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9108 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9111 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9115 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9116 unsigned long searched_pc
, int pc_pos
, void *puc
)
9118 env
->regs
[15] = gen_opc_pc
[pc_pos
];