]>
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
)
3770 if (!vfp_enabled(env
))
3772 VFP_DREG_D(rd
, insn
);
3773 rn
= (insn
>> 16) & 0xf;
3775 load
= (insn
& (1 << 21)) != 0;
3776 if ((insn
& (1 << 23)) == 0) {
3777 /* Load store all elements. */
3778 op
= (insn
>> 8) & 0xf;
3779 size
= (insn
>> 6) & 3;
3780 if (op
> 10 || size
== 3)
3782 nregs
= neon_ls_element_type
[op
].nregs
;
3783 interleave
= neon_ls_element_type
[op
].interleave
;
3784 gen_movl_T1_reg(s
, rn
);
3785 stride
= (1 << size
) * interleave
;
3786 for (reg
= 0; reg
< nregs
; reg
++) {
3787 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3788 gen_movl_T1_reg(s
, rn
);
3789 gen_op_addl_T1_im((1 << size
) * reg
);
3790 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3791 gen_movl_T1_reg(s
, rn
);
3792 gen_op_addl_T1_im(1 << size
);
3794 for (pass
= 0; pass
< 2; pass
++) {
3797 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3798 neon_store_reg(rd
, pass
, tmp
);
3800 tmp
= neon_load_reg(rd
, pass
);
3801 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3803 gen_op_addl_T1_im(stride
);
3804 } else if (size
== 1) {
3806 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3807 gen_op_addl_T1_im(stride
);
3808 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3809 gen_op_addl_T1_im(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
, cpu_T
[1], IS_USER(s
));
3818 gen_op_addl_T1_im(stride
);
3819 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3820 gen_op_addl_T1_im(stride
);
3822 } else /* size == 0 */ {
3825 for (n
= 0; n
< 4; n
++) {
3826 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3827 gen_op_addl_T1_im(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
, cpu_T
[1], IS_USER(s
));
3846 gen_op_addl_T1_im(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 gen_movl_T1_reg(s
, rn
);
3865 for (reg
= 0; reg
< nregs
; reg
++) {
3868 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3869 gen_neon_dup_u8(tmp
, 0);
3872 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3873 gen_neon_dup_low16(tmp
);
3876 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3880 default: /* Avoid compiler warnings. */
3883 gen_op_addl_T1_im(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 gen_movl_T1_reg(s
, rn
);
3912 for (reg
= 0; reg
< nregs
; reg
++) {
3916 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3919 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3922 tmp
= gen_ld32(cpu_T
[1], 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
, cpu_T
[1], IS_USER(s
));
3942 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3945 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3950 gen_op_addl_T1_im(1 << size
);
3952 stride
= nregs
* (1 << size
);
3958 base
= load_reg(s
, rn
);
3960 tcg_gen_addi_i32(base
, base
, stride
);
3963 index
= load_reg(s
, rm
);
3964 tcg_gen_add_i32(base
, base
, index
);
3967 store_reg(s
, rn
, base
);
3972 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3973 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3975 tcg_gen_and_i32(t
, t
, c
);
3976 tcg_gen_bic_i32(f
, f
, c
);
3977 tcg_gen_or_i32(dest
, t
, f
);
3980 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3983 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3984 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3985 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3990 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3993 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3994 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3995 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4000 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4003 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4004 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4005 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4010 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4016 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4017 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4022 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4023 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4030 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4031 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4036 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4037 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4044 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4048 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4049 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4050 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4055 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4056 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4057 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4064 static inline void gen_neon_addl(int size
)
4067 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4068 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4069 case 2: tcg_gen_add_i64(CPU_V001
); break;
4074 static inline void gen_neon_subl(int size
)
4077 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4078 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4079 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4084 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4087 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4088 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4089 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4094 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4097 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4098 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4103 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4107 switch ((size
<< 1) | u
) {
4108 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4109 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4110 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4111 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4113 tmp
= gen_muls_i64_i32(a
, b
);
4114 tcg_gen_mov_i64(dest
, tmp
);
4117 tmp
= gen_mulu_i64_i32(a
, b
);
4118 tcg_gen_mov_i64(dest
, tmp
);
4124 /* Translate a NEON data processing instruction. Return nonzero if the
4125 instruction is invalid.
4126 We process data in a mixture of 32-bit and 64-bit chunks.
4127 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4129 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4147 if (!vfp_enabled(env
))
4149 q
= (insn
& (1 << 6)) != 0;
4150 u
= (insn
>> 24) & 1;
4151 VFP_DREG_D(rd
, insn
);
4152 VFP_DREG_N(rn
, insn
);
4153 VFP_DREG_M(rm
, insn
);
4154 size
= (insn
>> 20) & 3;
4155 if ((insn
& (1 << 23)) == 0) {
4156 /* Three register same length. */
4157 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4158 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4159 || op
== 10 || op
== 11 || op
== 16)) {
4160 /* 64-bit element instructions. */
4161 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4162 neon_load_reg64(cpu_V0
, rn
+ pass
);
4163 neon_load_reg64(cpu_V1
, rm
+ pass
);
4167 gen_helper_neon_add_saturate_u64(CPU_V001
);
4169 gen_helper_neon_add_saturate_s64(CPU_V001
);
4174 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4176 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4181 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4183 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4188 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4191 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4195 case 10: /* VRSHL */
4197 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4199 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4202 case 11: /* VQRSHL */
4204 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4207 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4213 tcg_gen_sub_i64(CPU_V001
);
4215 tcg_gen_add_i64(CPU_V001
);
4221 neon_store_reg64(cpu_V0
, rd
+ pass
);
4228 case 10: /* VRSHL */
4229 case 11: /* VQRSHL */
4232 /* Shift instruction operands are reversed. */
4239 case 20: /* VPMAX */
4240 case 21: /* VPMIN */
4241 case 23: /* VPADD */
4244 case 26: /* VPADD (float) */
4245 pairwise
= (u
&& size
< 2);
4247 case 30: /* VPMIN/VPMAX (float) */
4255 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4264 tmp
= neon_load_reg(rn
, n
);
4265 tmp2
= neon_load_reg(rn
, n
+ 1);
4267 tmp
= neon_load_reg(rm
, n
);
4268 tmp2
= neon_load_reg(rm
, n
+ 1);
4272 tmp
= neon_load_reg(rn
, pass
);
4273 tmp2
= neon_load_reg(rm
, pass
);
4277 GEN_NEON_INTEGER_OP(hadd
);
4280 GEN_NEON_INTEGER_OP_ENV(qadd
);
4282 case 2: /* VRHADD */
4283 GEN_NEON_INTEGER_OP(rhadd
);
4285 case 3: /* Logic ops. */
4286 switch ((u
<< 2) | size
) {
4288 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4291 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4294 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4297 tcg_gen_not_i32(tmp2
, tmp2
);
4298 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4301 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4304 tmp3
= neon_load_reg(rd
, pass
);
4305 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4309 tmp3
= neon_load_reg(rd
, pass
);
4310 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4314 tmp3
= neon_load_reg(rd
, pass
);
4315 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4321 GEN_NEON_INTEGER_OP(hsub
);
4324 GEN_NEON_INTEGER_OP_ENV(qsub
);
4327 GEN_NEON_INTEGER_OP(cgt
);
4330 GEN_NEON_INTEGER_OP(cge
);
4333 GEN_NEON_INTEGER_OP(shl
);
4336 GEN_NEON_INTEGER_OP_ENV(qshl
);
4338 case 10: /* VRSHL */
4339 GEN_NEON_INTEGER_OP(rshl
);
4341 case 11: /* VQRSHL */
4342 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4345 GEN_NEON_INTEGER_OP(max
);
4348 GEN_NEON_INTEGER_OP(min
);
4351 GEN_NEON_INTEGER_OP(abd
);
4354 GEN_NEON_INTEGER_OP(abd
);
4356 tmp2
= neon_load_reg(rd
, pass
);
4357 gen_neon_add(size
, tmp
, tmp2
);
4360 if (!u
) { /* VADD */
4361 if (gen_neon_add(size
, tmp
, tmp2
))
4365 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4366 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4367 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4373 if (!u
) { /* VTST */
4375 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4376 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4377 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4382 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4383 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4384 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4389 case 18: /* Multiply. */
4391 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4392 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4393 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4397 tmp2
= neon_load_reg(rd
, pass
);
4399 gen_neon_rsb(size
, tmp
, tmp2
);
4401 gen_neon_add(size
, tmp
, tmp2
);
4405 if (u
) { /* polynomial */
4406 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4407 } else { /* Integer */
4409 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4410 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4411 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4416 case 20: /* VPMAX */
4417 GEN_NEON_INTEGER_OP(pmax
);
4419 case 21: /* VPMIN */
4420 GEN_NEON_INTEGER_OP(pmin
);
4422 case 22: /* Hultiply high. */
4423 if (!u
) { /* VQDMULH */
4425 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4426 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4429 } else { /* VQRDHMUL */
4431 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4432 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4437 case 23: /* VPADD */
4441 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4442 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4443 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4447 case 26: /* Floating point arithnetic. */
4448 switch ((u
<< 2) | size
) {
4450 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4453 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4456 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4459 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4465 case 27: /* Float multiply. */
4466 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4469 tmp2
= neon_load_reg(rd
, pass
);
4471 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4473 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4477 case 28: /* Float compare. */
4479 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4482 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4484 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4487 case 29: /* Float compare absolute. */
4491 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4493 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4495 case 30: /* Float min/max. */
4497 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4499 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4503 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4505 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4512 /* Save the result. For elementwise operations we can put it
4513 straight into the destination register. For pairwise operations
4514 we have to be careful to avoid clobbering the source operands. */
4515 if (pairwise
&& rd
== rm
) {
4516 neon_store_scratch(pass
, tmp
);
4518 neon_store_reg(rd
, pass
, tmp
);
4522 if (pairwise
&& rd
== rm
) {
4523 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4524 tmp
= neon_load_scratch(pass
);
4525 neon_store_reg(rd
, pass
, tmp
);
4528 /* End of 3 register same size operations. */
4529 } else if (insn
& (1 << 4)) {
4530 if ((insn
& 0x00380080) != 0) {
4531 /* Two registers and shift. */
4532 op
= (insn
>> 8) & 0xf;
4533 if (insn
& (1 << 7)) {
4538 while ((insn
& (1 << (size
+ 19))) == 0)
4541 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4542 /* To avoid excessive dumplication of ops we implement shift
4543 by immediate using the variable shift operations. */
4545 /* Shift by immediate:
4546 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4547 /* Right shifts are encoded as N - shift, where N is the
4548 element size in bits. */
4550 shift
= shift
- (1 << (size
+ 3));
4558 imm
= (uint8_t) shift
;
4563 imm
= (uint16_t) shift
;
4574 for (pass
= 0; pass
< count
; pass
++) {
4576 neon_load_reg64(cpu_V0
, rm
+ pass
);
4577 tcg_gen_movi_i64(cpu_V1
, imm
);
4582 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4584 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4589 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4591 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4596 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4598 case 5: /* VSHL, VSLI */
4599 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4603 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4605 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4607 case 7: /* VQSHLU */
4608 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4611 if (op
== 1 || op
== 3) {
4613 neon_load_reg64(cpu_V0
, rd
+ pass
);
4614 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4615 } else if (op
== 4 || (op
== 5 && u
)) {
4617 cpu_abort(env
, "VS[LR]I.64 not implemented");
4619 neon_store_reg64(cpu_V0
, rd
+ pass
);
4620 } else { /* size < 3 */
4621 /* Operands in T0 and T1. */
4622 tmp
= neon_load_reg(rm
, pass
);
4624 tcg_gen_movi_i32(tmp2
, imm
);
4628 GEN_NEON_INTEGER_OP(shl
);
4632 GEN_NEON_INTEGER_OP(rshl
);
4637 GEN_NEON_INTEGER_OP(shl
);
4639 case 5: /* VSHL, VSLI */
4641 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4642 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4643 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4648 GEN_NEON_INTEGER_OP_ENV(qshl
);
4650 case 7: /* VQSHLU */
4652 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4653 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4654 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4661 if (op
== 1 || op
== 3) {
4663 tmp2
= neon_load_reg(rd
, pass
);
4664 gen_neon_add(size
, tmp2
, tmp
);
4666 } else if (op
== 4 || (op
== 5 && u
)) {
4671 imm
= 0xff >> -shift
;
4673 imm
= (uint8_t)(0xff << shift
);
4679 imm
= 0xffff >> -shift
;
4681 imm
= (uint16_t)(0xffff << shift
);
4686 imm
= 0xffffffffu
>> -shift
;
4688 imm
= 0xffffffffu
<< shift
;
4693 tmp2
= neon_load_reg(rd
, pass
);
4694 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4695 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4696 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4699 neon_store_reg(rd
, pass
, tmp
);
4702 } else if (op
< 10) {
4703 /* Shift by immediate and narrow:
4704 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4705 shift
= shift
- (1 << (size
+ 3));
4709 imm
= (uint16_t)shift
;
4711 tmp2
= tcg_const_i32(imm
);
4712 TCGV_UNUSED_I64(tmp64
);
4715 imm
= (uint32_t)shift
;
4716 tmp2
= tcg_const_i32(imm
);
4717 TCGV_UNUSED_I64(tmp64
);
4720 tmp64
= tcg_const_i64(shift
);
4727 for (pass
= 0; pass
< 2; pass
++) {
4729 neon_load_reg64(cpu_V0
, rm
+ pass
);
4732 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4734 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4737 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4739 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4742 tmp
= neon_load_reg(rm
+ pass
, 0);
4743 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4744 tmp3
= neon_load_reg(rm
+ pass
, 1);
4745 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4746 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4751 if (op
== 8 && !u
) {
4752 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4755 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4757 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4762 neon_store_reg(rd
, 0, tmp2
);
4763 neon_store_reg(rd
, 1, tmp
);
4766 } else if (op
== 10) {
4770 tmp
= neon_load_reg(rm
, 0);
4771 tmp2
= neon_load_reg(rm
, 1);
4772 for (pass
= 0; pass
< 2; pass
++) {
4776 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4779 /* The shift is less than the width of the source
4780 type, so we can just shift the whole register. */
4781 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4782 if (size
< 2 || !u
) {
4785 imm
= (0xffu
>> (8 - shift
));
4788 imm
= 0xffff >> (16 - shift
);
4790 imm64
= imm
| (((uint64_t)imm
) << 32);
4791 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4794 neon_store_reg64(cpu_V0
, rd
+ pass
);
4796 } else if (op
== 15 || op
== 16) {
4797 /* VCVT fixed-point. */
4798 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4799 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4802 gen_vfp_ulto(0, shift
);
4804 gen_vfp_slto(0, shift
);
4807 gen_vfp_toul(0, shift
);
4809 gen_vfp_tosl(0, shift
);
4811 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4816 } else { /* (insn & 0x00380080) == 0 */
4819 op
= (insn
>> 8) & 0xf;
4820 /* One register and immediate. */
4821 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4822 invert
= (insn
& (1 << 5)) != 0;
4840 imm
= (imm
<< 8) | (imm
<< 24);
4843 imm
= (imm
< 8) | 0xff;
4846 imm
= (imm
<< 16) | 0xffff;
4849 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4854 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4855 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4861 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4862 if (op
& 1 && op
< 12) {
4863 tmp
= neon_load_reg(rd
, pass
);
4865 /* The immediate value has already been inverted, so
4867 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4869 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4874 if (op
== 14 && invert
) {
4877 for (n
= 0; n
< 4; n
++) {
4878 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4879 val
|= 0xff << (n
* 8);
4881 tcg_gen_movi_i32(tmp
, val
);
4883 tcg_gen_movi_i32(tmp
, imm
);
4886 neon_store_reg(rd
, pass
, tmp
);
4889 } else { /* (insn & 0x00800010 == 0x00800000) */
4891 op
= (insn
>> 8) & 0xf;
4892 if ((insn
& (1 << 6)) == 0) {
4893 /* Three registers of different lengths. */
4897 /* prewiden, src1_wide, src2_wide */
4898 static const int neon_3reg_wide
[16][3] = {
4899 {1, 0, 0}, /* VADDL */
4900 {1, 1, 0}, /* VADDW */
4901 {1, 0, 0}, /* VSUBL */
4902 {1, 1, 0}, /* VSUBW */
4903 {0, 1, 1}, /* VADDHN */
4904 {0, 0, 0}, /* VABAL */
4905 {0, 1, 1}, /* VSUBHN */
4906 {0, 0, 0}, /* VABDL */
4907 {0, 0, 0}, /* VMLAL */
4908 {0, 0, 0}, /* VQDMLAL */
4909 {0, 0, 0}, /* VMLSL */
4910 {0, 0, 0}, /* VQDMLSL */
4911 {0, 0, 0}, /* Integer VMULL */
4912 {0, 0, 0}, /* VQDMULL */
4913 {0, 0, 0} /* Polynomial VMULL */
4916 prewiden
= neon_3reg_wide
[op
][0];
4917 src1_wide
= neon_3reg_wide
[op
][1];
4918 src2_wide
= neon_3reg_wide
[op
][2];
4920 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4923 /* Avoid overlapping operands. Wide source operands are
4924 always aligned so will never overlap with wide
4925 destinations in problematic ways. */
4926 if (rd
== rm
&& !src2_wide
) {
4927 tmp
= neon_load_reg(rm
, 1);
4928 neon_store_scratch(2, tmp
);
4929 } else if (rd
== rn
&& !src1_wide
) {
4930 tmp
= neon_load_reg(rn
, 1);
4931 neon_store_scratch(2, tmp
);
4934 for (pass
= 0; pass
< 2; pass
++) {
4936 neon_load_reg64(cpu_V0
, rn
+ pass
);
4939 if (pass
== 1 && rd
== rn
) {
4940 tmp
= neon_load_scratch(2);
4942 tmp
= neon_load_reg(rn
, pass
);
4945 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4949 neon_load_reg64(cpu_V1
, rm
+ pass
);
4952 if (pass
== 1 && rd
== rm
) {
4953 tmp2
= neon_load_scratch(2);
4955 tmp2
= neon_load_reg(rm
, pass
);
4958 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4962 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4963 gen_neon_addl(size
);
4965 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4966 gen_neon_subl(size
);
4968 case 5: case 7: /* VABAL, VABDL */
4969 switch ((size
<< 1) | u
) {
4971 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4974 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4977 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4980 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4983 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4986 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4993 case 8: case 9: case 10: case 11: case 12: case 13:
4994 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4995 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4999 case 14: /* Polynomial VMULL */
5000 cpu_abort(env
, "Polynomial VMULL not implemented");
5002 default: /* 15 is RESERVED. */
5005 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5007 if (op
== 10 || op
== 11) {
5008 gen_neon_negl(cpu_V0
, size
);
5012 neon_load_reg64(cpu_V1
, rd
+ pass
);
5016 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5017 gen_neon_addl(size
);
5019 case 9: case 11: /* VQDMLAL, VQDMLSL */
5020 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5021 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5024 case 13: /* VQDMULL */
5025 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5030 neon_store_reg64(cpu_V0
, rd
+ pass
);
5031 } else if (op
== 4 || op
== 6) {
5032 /* Narrowing operation. */
5037 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5040 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5043 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5044 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5051 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5054 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5057 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5058 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5059 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5067 neon_store_reg(rd
, 0, tmp3
);
5068 neon_store_reg(rd
, 1, tmp
);
5071 /* Write back the result. */
5072 neon_store_reg64(cpu_V0
, rd
+ pass
);
5076 /* Two registers and a scalar. */
5078 case 0: /* Integer VMLA scalar */
5079 case 1: /* Float VMLA scalar */
5080 case 4: /* Integer VMLS scalar */
5081 case 5: /* Floating point VMLS scalar */
5082 case 8: /* Integer VMUL scalar */
5083 case 9: /* Floating point VMUL scalar */
5084 case 12: /* VQDMULH scalar */
5085 case 13: /* VQRDMULH scalar */
5086 tmp
= neon_get_scalar(size
, rm
);
5087 neon_store_scratch(0, tmp
);
5088 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5089 tmp
= neon_load_scratch(0);
5090 tmp2
= neon_load_reg(rn
, pass
);
5093 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5095 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5097 } else if (op
== 13) {
5099 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5101 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5103 } else if (op
& 1) {
5104 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5107 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5108 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5109 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5116 tmp2
= neon_load_reg(rd
, pass
);
5119 gen_neon_add(size
, tmp
, tmp2
);
5122 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5125 gen_neon_rsb(size
, tmp
, tmp2
);
5128 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5135 neon_store_reg(rd
, pass
, tmp
);
5138 case 2: /* VMLAL sclar */
5139 case 3: /* VQDMLAL scalar */
5140 case 6: /* VMLSL scalar */
5141 case 7: /* VQDMLSL scalar */
5142 case 10: /* VMULL scalar */
5143 case 11: /* VQDMULL scalar */
5144 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5147 tmp2
= neon_get_scalar(size
, rm
);
5148 tmp3
= neon_load_reg(rn
, 1);
5150 for (pass
= 0; pass
< 2; pass
++) {
5152 tmp
= neon_load_reg(rn
, 0);
5156 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5158 if (op
== 6 || op
== 7) {
5159 gen_neon_negl(cpu_V0
, size
);
5162 neon_load_reg64(cpu_V1
, rd
+ pass
);
5166 gen_neon_addl(size
);
5169 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5170 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5176 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5181 neon_store_reg64(cpu_V0
, rd
+ pass
);
5187 default: /* 14 and 15 are RESERVED */
5191 } else { /* size == 3 */
5194 imm
= (insn
>> 8) & 0xf;
5201 neon_load_reg64(cpu_V0
, rn
);
5203 neon_load_reg64(cpu_V1
, rn
+ 1);
5205 } else if (imm
== 8) {
5206 neon_load_reg64(cpu_V0
, rn
+ 1);
5208 neon_load_reg64(cpu_V1
, rm
);
5211 tmp64
= tcg_temp_new_i64();
5213 neon_load_reg64(cpu_V0
, rn
);
5214 neon_load_reg64(tmp64
, rn
+ 1);
5216 neon_load_reg64(cpu_V0
, rn
+ 1);
5217 neon_load_reg64(tmp64
, rm
);
5219 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5220 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5221 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5223 neon_load_reg64(cpu_V1
, rm
);
5225 neon_load_reg64(cpu_V1
, rm
+ 1);
5228 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5229 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5230 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5233 neon_load_reg64(cpu_V0
, rn
);
5234 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5235 neon_load_reg64(cpu_V1
, rm
);
5236 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5237 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5239 neon_store_reg64(cpu_V0
, rd
);
5241 neon_store_reg64(cpu_V1
, rd
+ 1);
5243 } else if ((insn
& (1 << 11)) == 0) {
5244 /* Two register misc. */
5245 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5246 size
= (insn
>> 18) & 3;
5248 case 0: /* VREV64 */
5251 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5252 tmp
= neon_load_reg(rm
, pass
* 2);
5253 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5255 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5256 case 1: gen_swap_half(tmp
); break;
5257 case 2: /* no-op */ break;
5260 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5262 neon_store_reg(rd
, pass
* 2, tmp2
);
5265 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5266 case 1: gen_swap_half(tmp2
); break;
5269 neon_store_reg(rd
, pass
* 2, tmp2
);
5273 case 4: case 5: /* VPADDL */
5274 case 12: case 13: /* VPADAL */
5277 for (pass
= 0; pass
< q
+ 1; pass
++) {
5278 tmp
= neon_load_reg(rm
, pass
* 2);
5279 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5280 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5281 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5283 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5284 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5285 case 2: tcg_gen_add_i64(CPU_V001
); break;
5290 neon_load_reg64(cpu_V1
, rd
+ pass
);
5291 gen_neon_addl(size
);
5293 neon_store_reg64(cpu_V0
, rd
+ pass
);
5298 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5299 tmp
= neon_load_reg(rm
, n
);
5300 tmp2
= neon_load_reg(rd
, n
+ 1);
5301 neon_store_reg(rm
, n
, tmp2
);
5302 neon_store_reg(rd
, n
+ 1, tmp
);
5310 Rd A3 A2 A1 A0 B2 B0 A2 A0
5311 Rm B3 B2 B1 B0 B3 B1 A3 A1
5315 gen_neon_unzip(rd
, q
, 0, size
);
5316 gen_neon_unzip(rm
, q
, 4, size
);
5318 static int unzip_order_q
[8] =
5319 {0, 2, 4, 6, 1, 3, 5, 7};
5320 for (n
= 0; n
< 8; n
++) {
5321 int reg
= (n
< 4) ? rd
: rm
;
5322 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5323 neon_store_reg(reg
, n
% 4, tmp
);
5326 static int unzip_order
[4] =
5328 for (n
= 0; n
< 4; n
++) {
5329 int reg
= (n
< 2) ? rd
: rm
;
5330 tmp
= neon_load_scratch(unzip_order
[n
]);
5331 neon_store_reg(reg
, n
% 2, tmp
);
5337 Rd A3 A2 A1 A0 B1 A1 B0 A0
5338 Rm B3 B2 B1 B0 B3 A3 B2 A2
5342 count
= (q
? 4 : 2);
5343 for (n
= 0; n
< count
; n
++) {
5344 tmp
= neon_load_reg(rd
, n
);
5345 tmp2
= neon_load_reg(rd
, n
);
5347 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5348 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5349 case 2: /* no-op */; break;
5352 neon_store_scratch(n
* 2, tmp
);
5353 neon_store_scratch(n
* 2 + 1, tmp2
);
5355 for (n
= 0; n
< count
* 2; n
++) {
5356 int reg
= (n
< count
) ? rd
: rm
;
5357 tmp
= neon_load_scratch(n
);
5358 neon_store_reg(reg
, n
% count
, tmp
);
5361 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5365 for (pass
= 0; pass
< 2; pass
++) {
5366 neon_load_reg64(cpu_V0
, rm
+ pass
);
5368 if (op
== 36 && q
== 0) {
5369 gen_neon_narrow(size
, tmp
, cpu_V0
);
5371 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5373 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5378 neon_store_reg(rd
, 0, tmp2
);
5379 neon_store_reg(rd
, 1, tmp
);
5383 case 38: /* VSHLL */
5386 tmp
= neon_load_reg(rm
, 0);
5387 tmp2
= neon_load_reg(rm
, 1);
5388 for (pass
= 0; pass
< 2; pass
++) {
5391 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5392 neon_store_reg64(cpu_V0
, rd
+ pass
);
5397 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5398 if (op
== 30 || op
== 31 || op
>= 58) {
5399 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5400 neon_reg_offset(rm
, pass
));
5403 tmp
= neon_load_reg(rm
, pass
);
5406 case 1: /* VREV32 */
5408 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5409 case 1: gen_swap_half(tmp
); break;
5413 case 2: /* VREV16 */
5420 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5421 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5422 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5428 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5429 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5430 case 2: gen_helper_clz(tmp
, tmp
); break;
5437 gen_helper_neon_cnt_u8(tmp
, tmp
);
5442 tcg_gen_not_i32(tmp
, tmp
);
5444 case 14: /* VQABS */
5446 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5447 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5448 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5452 case 15: /* VQNEG */
5454 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5455 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5456 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5460 case 16: case 19: /* VCGT #0, VCLE #0 */
5461 tmp2
= tcg_const_i32(0);
5463 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5464 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5465 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5468 tcg_temp_free(tmp2
);
5470 tcg_gen_not_i32(tmp
, tmp
);
5472 case 17: case 20: /* VCGE #0, VCLT #0 */
5473 tmp2
= tcg_const_i32(0);
5475 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5476 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5477 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5480 tcg_temp_free(tmp2
);
5482 tcg_gen_not_i32(tmp
, tmp
);
5484 case 18: /* VCEQ #0 */
5485 tmp2
= tcg_const_i32(0);
5487 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5488 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5489 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5492 tcg_temp_free(tmp2
);
5496 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5497 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5498 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5505 tmp2
= tcg_const_i32(0);
5506 gen_neon_rsb(size
, tmp
, tmp2
);
5507 tcg_temp_free(tmp2
);
5509 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5510 tmp2
= tcg_const_i32(0);
5511 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5512 tcg_temp_free(tmp2
);
5514 tcg_gen_not_i32(tmp
, tmp
);
5516 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5517 tmp2
= tcg_const_i32(0);
5518 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5519 tcg_temp_free(tmp2
);
5521 tcg_gen_not_i32(tmp
, tmp
);
5523 case 26: /* Float VCEQ #0 */
5524 tmp2
= tcg_const_i32(0);
5525 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5526 tcg_temp_free(tmp2
);
5528 case 30: /* Float VABS */
5531 case 31: /* Float VNEG */
5535 tmp2
= neon_load_reg(rd
, pass
);
5536 neon_store_reg(rm
, pass
, tmp2
);
5539 tmp2
= neon_load_reg(rd
, pass
);
5541 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5542 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5546 neon_store_reg(rm
, pass
, tmp2
);
5548 case 56: /* Integer VRECPE */
5549 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5551 case 57: /* Integer VRSQRTE */
5552 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5554 case 58: /* Float VRECPE */
5555 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5557 case 59: /* Float VRSQRTE */
5558 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5560 case 60: /* VCVT.F32.S32 */
5563 case 61: /* VCVT.F32.U32 */
5566 case 62: /* VCVT.S32.F32 */
5569 case 63: /* VCVT.U32.F32 */
5573 /* Reserved: 21, 29, 39-56 */
5576 if (op
== 30 || op
== 31 || op
>= 58) {
5577 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5578 neon_reg_offset(rd
, pass
));
5580 neon_store_reg(rd
, pass
, tmp
);
5585 } else if ((insn
& (1 << 10)) == 0) {
5587 n
= ((insn
>> 5) & 0x18) + 8;
5588 if (insn
& (1 << 6)) {
5589 tmp
= neon_load_reg(rd
, 0);
5592 tcg_gen_movi_i32(tmp
, 0);
5594 tmp2
= neon_load_reg(rm
, 0);
5595 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5598 if (insn
& (1 << 6)) {
5599 tmp
= neon_load_reg(rd
, 1);
5602 tcg_gen_movi_i32(tmp
, 0);
5604 tmp3
= neon_load_reg(rm
, 1);
5605 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5607 neon_store_reg(rd
, 0, tmp2
);
5608 neon_store_reg(rd
, 1, tmp3
);
5610 } else if ((insn
& 0x380) == 0) {
5612 if (insn
& (1 << 19)) {
5613 tmp
= neon_load_reg(rm
, 1);
5615 tmp
= neon_load_reg(rm
, 0);
5617 if (insn
& (1 << 16)) {
5618 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5619 } else if (insn
& (1 << 17)) {
5620 if ((insn
>> 18) & 1)
5621 gen_neon_dup_high16(tmp
);
5623 gen_neon_dup_low16(tmp
);
5625 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5627 tcg_gen_mov_i32(tmp2
, tmp
);
5628 neon_store_reg(rd
, pass
, tmp2
);
5639 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5641 int crn
= (insn
>> 16) & 0xf;
5642 int crm
= insn
& 0xf;
5643 int op1
= (insn
>> 21) & 7;
5644 int op2
= (insn
>> 5) & 7;
5645 int rt
= (insn
>> 12) & 0xf;
5648 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5649 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5653 tmp
= load_cpu_field(teecr
);
5654 store_reg(s
, rt
, tmp
);
5657 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5659 if (IS_USER(s
) && (env
->teecr
& 1))
5661 tmp
= load_cpu_field(teehbr
);
5662 store_reg(s
, rt
, tmp
);
5666 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5667 op1
, crn
, crm
, op2
);
5671 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5673 int crn
= (insn
>> 16) & 0xf;
5674 int crm
= insn
& 0xf;
5675 int op1
= (insn
>> 21) & 7;
5676 int op2
= (insn
>> 5) & 7;
5677 int rt
= (insn
>> 12) & 0xf;
5680 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5681 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5685 tmp
= load_reg(s
, rt
);
5686 gen_helper_set_teecr(cpu_env
, tmp
);
5690 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5692 if (IS_USER(s
) && (env
->teecr
& 1))
5694 tmp
= load_reg(s
, rt
);
5695 store_cpu_field(tmp
, teehbr
);
5699 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5700 op1
, crn
, crm
, op2
);
5704 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5708 cpnum
= (insn
>> 8) & 0xf;
5709 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5710 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5716 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5717 return disas_iwmmxt_insn(env
, s
, insn
);
5718 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5719 return disas_dsp_insn(env
, s
, insn
);
5724 return disas_vfp_insn (env
, s
, insn
);
5726 /* Coprocessors 7-15 are architecturally reserved by ARM.
5727 Unfortunately Intel decided to ignore this. */
5728 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5730 if (insn
& (1 << 20))
5731 return disas_cp14_read(env
, s
, insn
);
5733 return disas_cp14_write(env
, s
, insn
);
5735 return disas_cp15_insn (env
, s
, insn
);
5738 /* Unknown coprocessor. See if the board has hooked it. */
5739 return disas_cp_insn (env
, s
, insn
);
5744 /* Store a 64-bit value to a register pair. Clobbers val. */
5745 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5749 tcg_gen_trunc_i64_i32(tmp
, val
);
5750 store_reg(s
, rlow
, tmp
);
5752 tcg_gen_shri_i64(val
, val
, 32);
5753 tcg_gen_trunc_i64_i32(tmp
, val
);
5754 store_reg(s
, rhigh
, tmp
);
5757 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5758 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5763 /* Load value and extend to 64 bits. */
5764 tmp
= tcg_temp_new_i64();
5765 tmp2
= load_reg(s
, rlow
);
5766 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5768 tcg_gen_add_i64(val
, val
, tmp
);
5771 /* load and add a 64-bit value from a register pair. */
5772 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5778 /* Load 64-bit value rd:rn. */
5779 tmpl
= load_reg(s
, rlow
);
5780 tmph
= load_reg(s
, rhigh
);
5781 tmp
= tcg_temp_new_i64();
5782 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5785 tcg_gen_add_i64(val
, val
, tmp
);
5788 /* Set N and Z flags from a 64-bit value. */
5789 static void gen_logicq_cc(TCGv_i64 val
)
5791 TCGv tmp
= new_tmp();
5792 gen_helper_logicq_cc(tmp
, val
);
5797 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5799 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5806 insn
= ldl_code(s
->pc
);
5809 /* M variants do not implement ARM mode. */
5814 /* Unconditional instructions. */
5815 if (((insn
>> 25) & 7) == 1) {
5816 /* NEON Data processing. */
5817 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5820 if (disas_neon_data_insn(env
, s
, insn
))
5824 if ((insn
& 0x0f100000) == 0x04000000) {
5825 /* NEON load/store. */
5826 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5829 if (disas_neon_ls_insn(env
, s
, insn
))
5833 if ((insn
& 0x0d70f000) == 0x0550f000)
5835 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5838 if (insn
& (1 << 9)) {
5839 /* BE8 mode not implemented. */
5843 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5844 switch ((insn
>> 4) & 0xf) {
5847 gen_helper_clrex(cpu_env
);
5853 /* We don't emulate caches so these are a no-op. */
5858 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5864 op1
= (insn
& 0x1f);
5865 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5866 addr
= load_reg(s
, 13);
5869 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5871 i
= (insn
>> 23) & 3;
5873 case 0: offset
= -4; break; /* DA */
5874 case 1: offset
= 0; break; /* IA */
5875 case 2: offset
= -8; break; /* DB */
5876 case 3: offset
= 4; break; /* IB */
5880 tcg_gen_addi_i32(addr
, addr
, offset
);
5881 tmp
= load_reg(s
, 14);
5882 gen_st32(tmp
, addr
, 0);
5883 tmp
= load_cpu_field(spsr
);
5884 tcg_gen_addi_i32(addr
, addr
, 4);
5885 gen_st32(tmp
, addr
, 0);
5886 if (insn
& (1 << 21)) {
5887 /* Base writeback. */
5889 case 0: offset
= -8; break;
5890 case 1: offset
= 4; break;
5891 case 2: offset
= -4; break;
5892 case 3: offset
= 0; break;
5896 tcg_gen_addi_i32(addr
, addr
, offset
);
5897 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5898 store_reg(s
, 13, addr
);
5900 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5906 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5912 rn
= (insn
>> 16) & 0xf;
5913 addr
= load_reg(s
, rn
);
5914 i
= (insn
>> 23) & 3;
5916 case 0: offset
= -4; break; /* DA */
5917 case 1: offset
= 0; break; /* IA */
5918 case 2: offset
= -8; break; /* DB */
5919 case 3: offset
= 4; break; /* IB */
5923 tcg_gen_addi_i32(addr
, addr
, offset
);
5924 /* Load PC into tmp and CPSR into tmp2. */
5925 tmp
= gen_ld32(addr
, 0);
5926 tcg_gen_addi_i32(addr
, addr
, 4);
5927 tmp2
= gen_ld32(addr
, 0);
5928 if (insn
& (1 << 21)) {
5929 /* Base writeback. */
5931 case 0: offset
= -8; break;
5932 case 1: offset
= 4; break;
5933 case 2: offset
= -4; break;
5934 case 3: offset
= 0; break;
5938 tcg_gen_addi_i32(addr
, addr
, offset
);
5939 store_reg(s
, rn
, addr
);
5943 gen_rfe(s
, tmp
, tmp2
);
5945 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5946 /* branch link and change to thumb (blx <offset>) */
5949 val
= (uint32_t)s
->pc
;
5951 tcg_gen_movi_i32(tmp
, val
);
5952 store_reg(s
, 14, tmp
);
5953 /* Sign-extend the 24-bit offset */
5954 offset
= (((int32_t)insn
) << 8) >> 8;
5955 /* offset * 4 + bit24 * 2 + (thumb bit) */
5956 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5957 /* pipeline offset */
5961 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5962 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5963 /* iWMMXt register transfer. */
5964 if (env
->cp15
.c15_cpar
& (1 << 1))
5965 if (!disas_iwmmxt_insn(env
, s
, insn
))
5968 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5969 /* Coprocessor double register transfer. */
5970 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5971 /* Additional coprocessor register transfer. */
5972 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5975 /* cps (privileged) */
5979 if (insn
& (1 << 19)) {
5980 if (insn
& (1 << 8))
5982 if (insn
& (1 << 7))
5984 if (insn
& (1 << 6))
5986 if (insn
& (1 << 18))
5989 if (insn
& (1 << 17)) {
5991 val
|= (insn
& 0x1f);
5994 gen_set_psr_im(s
, mask
, 0, val
);
6001 /* if not always execute, we generate a conditional jump to
6003 s
->condlabel
= gen_new_label();
6004 gen_test_cc(cond
^ 1, s
->condlabel
);
6007 if ((insn
& 0x0f900000) == 0x03000000) {
6008 if ((insn
& (1 << 21)) == 0) {
6010 rd
= (insn
>> 12) & 0xf;
6011 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6012 if ((insn
& (1 << 22)) == 0) {
6015 tcg_gen_movi_i32(tmp
, val
);
6018 tmp
= load_reg(s
, rd
);
6019 tcg_gen_ext16u_i32(tmp
, tmp
);
6020 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6022 store_reg(s
, rd
, tmp
);
6024 if (((insn
>> 12) & 0xf) != 0xf)
6026 if (((insn
>> 16) & 0xf) == 0) {
6027 gen_nop_hint(s
, insn
& 0xff);
6029 /* CPSR = immediate */
6031 shift
= ((insn
>> 8) & 0xf) * 2;
6033 val
= (val
>> shift
) | (val
<< (32 - shift
));
6034 i
= ((insn
& (1 << 22)) != 0);
6035 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6039 } else if ((insn
& 0x0f900000) == 0x01000000
6040 && (insn
& 0x00000090) != 0x00000090) {
6041 /* miscellaneous instructions */
6042 op1
= (insn
>> 21) & 3;
6043 sh
= (insn
>> 4) & 0xf;
6046 case 0x0: /* move program status register */
6049 tmp
= load_reg(s
, rm
);
6050 i
= ((op1
& 2) != 0);
6051 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6055 rd
= (insn
>> 12) & 0xf;
6059 tmp
= load_cpu_field(spsr
);
6062 gen_helper_cpsr_read(tmp
);
6064 store_reg(s
, rd
, tmp
);
6069 /* branch/exchange thumb (bx). */
6070 tmp
= load_reg(s
, rm
);
6072 } else if (op1
== 3) {
6074 rd
= (insn
>> 12) & 0xf;
6075 tmp
= load_reg(s
, rm
);
6076 gen_helper_clz(tmp
, tmp
);
6077 store_reg(s
, rd
, tmp
);
6085 /* Trivial implementation equivalent to bx. */
6086 tmp
= load_reg(s
, rm
);
6096 /* branch link/exchange thumb (blx) */
6097 tmp
= load_reg(s
, rm
);
6099 tcg_gen_movi_i32(tmp2
, s
->pc
);
6100 store_reg(s
, 14, tmp2
);
6103 case 0x5: /* saturating add/subtract */
6104 rd
= (insn
>> 12) & 0xf;
6105 rn
= (insn
>> 16) & 0xf;
6106 tmp
= load_reg(s
, rm
);
6107 tmp2
= load_reg(s
, rn
);
6109 gen_helper_double_saturate(tmp2
, tmp2
);
6111 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6113 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6115 store_reg(s
, rd
, tmp
);
6118 gen_set_condexec(s
);
6119 gen_set_pc_im(s
->pc
- 4);
6120 gen_exception(EXCP_BKPT
);
6121 s
->is_jmp
= DISAS_JUMP
;
6123 case 0x8: /* signed multiply */
6127 rs
= (insn
>> 8) & 0xf;
6128 rn
= (insn
>> 12) & 0xf;
6129 rd
= (insn
>> 16) & 0xf;
6131 /* (32 * 16) >> 16 */
6132 tmp
= load_reg(s
, rm
);
6133 tmp2
= load_reg(s
, rs
);
6135 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6138 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6139 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6141 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6142 if ((sh
& 2) == 0) {
6143 tmp2
= load_reg(s
, rn
);
6144 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6147 store_reg(s
, rd
, tmp
);
6150 tmp
= load_reg(s
, rm
);
6151 tmp2
= load_reg(s
, rs
);
6152 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6155 tmp64
= tcg_temp_new_i64();
6156 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6158 gen_addq(s
, tmp64
, rn
, rd
);
6159 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6162 tmp2
= load_reg(s
, rn
);
6163 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6166 store_reg(s
, rd
, tmp
);
6173 } else if (((insn
& 0x0e000000) == 0 &&
6174 (insn
& 0x00000090) != 0x90) ||
6175 ((insn
& 0x0e000000) == (1 << 25))) {
6176 int set_cc
, logic_cc
, shiftop
;
6178 op1
= (insn
>> 21) & 0xf;
6179 set_cc
= (insn
>> 20) & 1;
6180 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6182 /* data processing instruction */
6183 if (insn
& (1 << 25)) {
6184 /* immediate operand */
6186 shift
= ((insn
>> 8) & 0xf) * 2;
6188 val
= (val
>> shift
) | (val
<< (32 - shift
));
6191 tcg_gen_movi_i32(tmp2
, val
);
6192 if (logic_cc
&& shift
) {
6193 gen_set_CF_bit31(tmp2
);
6198 tmp2
= load_reg(s
, rm
);
6199 shiftop
= (insn
>> 5) & 3;
6200 if (!(insn
& (1 << 4))) {
6201 shift
= (insn
>> 7) & 0x1f;
6202 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6204 rs
= (insn
>> 8) & 0xf;
6205 tmp
= load_reg(s
, rs
);
6206 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6209 if (op1
!= 0x0f && op1
!= 0x0d) {
6210 rn
= (insn
>> 16) & 0xf;
6211 tmp
= load_reg(s
, rn
);
6215 rd
= (insn
>> 12) & 0xf;
6218 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6222 store_reg_bx(env
, s
, rd
, tmp
);
6225 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6229 store_reg_bx(env
, s
, rd
, tmp
);
6232 if (set_cc
&& rd
== 15) {
6233 /* SUBS r15, ... is used for exception return. */
6237 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6238 gen_exception_return(s
, tmp
);
6241 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6243 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6245 store_reg_bx(env
, s
, rd
, tmp
);
6250 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6252 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6254 store_reg_bx(env
, s
, rd
, tmp
);
6258 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6260 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6262 store_reg_bx(env
, s
, rd
, tmp
);
6266 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6268 gen_add_carry(tmp
, tmp
, tmp2
);
6270 store_reg_bx(env
, s
, rd
, tmp
);
6274 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6276 gen_sub_carry(tmp
, tmp
, tmp2
);
6278 store_reg_bx(env
, s
, rd
, tmp
);
6282 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6284 gen_sub_carry(tmp
, tmp2
, tmp
);
6286 store_reg_bx(env
, s
, rd
, tmp
);
6290 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6297 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6304 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6310 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6315 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6319 store_reg_bx(env
, s
, rd
, tmp
);
6322 if (logic_cc
&& rd
== 15) {
6323 /* MOVS r15, ... is used for exception return. */
6327 gen_exception_return(s
, tmp2
);
6332 store_reg_bx(env
, s
, rd
, tmp2
);
6336 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6340 store_reg_bx(env
, s
, rd
, tmp
);
6344 tcg_gen_not_i32(tmp2
, tmp2
);
6348 store_reg_bx(env
, s
, rd
, tmp2
);
6351 if (op1
!= 0x0f && op1
!= 0x0d) {
6355 /* other instructions */
6356 op1
= (insn
>> 24) & 0xf;
6360 /* multiplies, extra load/stores */
6361 sh
= (insn
>> 5) & 3;
6364 rd
= (insn
>> 16) & 0xf;
6365 rn
= (insn
>> 12) & 0xf;
6366 rs
= (insn
>> 8) & 0xf;
6368 op1
= (insn
>> 20) & 0xf;
6370 case 0: case 1: case 2: case 3: case 6:
6372 tmp
= load_reg(s
, rs
);
6373 tmp2
= load_reg(s
, rm
);
6374 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6376 if (insn
& (1 << 22)) {
6377 /* Subtract (mls) */
6379 tmp2
= load_reg(s
, rn
);
6380 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6382 } else if (insn
& (1 << 21)) {
6384 tmp2
= load_reg(s
, rn
);
6385 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6388 if (insn
& (1 << 20))
6390 store_reg(s
, rd
, tmp
);
6394 tmp
= load_reg(s
, rs
);
6395 tmp2
= load_reg(s
, rm
);
6396 if (insn
& (1 << 22))
6397 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6399 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6400 if (insn
& (1 << 21)) /* mult accumulate */
6401 gen_addq(s
, tmp64
, rn
, rd
);
6402 if (!(insn
& (1 << 23))) { /* double accumulate */
6404 gen_addq_lo(s
, tmp64
, rn
);
6405 gen_addq_lo(s
, tmp64
, rd
);
6407 if (insn
& (1 << 20))
6408 gen_logicq_cc(tmp64
);
6409 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6413 rn
= (insn
>> 16) & 0xf;
6414 rd
= (insn
>> 12) & 0xf;
6415 if (insn
& (1 << 23)) {
6416 /* load/store exclusive */
6417 op1
= (insn
>> 21) & 0x3;
6422 addr
= tcg_temp_local_new_i32();
6423 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
6424 if (insn
& (1 << 20)) {
6425 gen_helper_mark_exclusive(cpu_env
, addr
);
6428 tmp
= gen_ld32(addr
, IS_USER(s
));
6430 case 1: /* ldrexd */
6431 tmp
= gen_ld32(addr
, IS_USER(s
));
6432 store_reg(s
, rd
, tmp
);
6433 tcg_gen_addi_i32(addr
, addr
, 4);
6434 tmp
= gen_ld32(addr
, IS_USER(s
));
6437 case 2: /* ldrexb */
6438 tmp
= gen_ld8u(addr
, IS_USER(s
));
6440 case 3: /* ldrexh */
6441 tmp
= gen_ld16u(addr
, IS_USER(s
));
6446 store_reg(s
, rd
, tmp
);
6448 int label
= gen_new_label();
6450 tmp2
= tcg_temp_local_new_i32();
6451 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6452 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6453 tmp
= load_reg(s
,rm
);
6456 gen_st32(tmp
, addr
, IS_USER(s
));
6458 case 1: /* strexd */
6459 gen_st32(tmp
, addr
, IS_USER(s
));
6460 tcg_gen_addi_i32(addr
, addr
, 4);
6461 tmp
= load_reg(s
, rm
+ 1);
6462 gen_st32(tmp
, addr
, IS_USER(s
));
6464 case 2: /* strexb */
6465 gen_st8(tmp
, addr
, IS_USER(s
));
6467 case 3: /* strexh */
6468 gen_st16(tmp
, addr
, IS_USER(s
));
6473 gen_set_label(label
);
6474 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6475 tcg_temp_free(tmp2
);
6477 tcg_temp_free(addr
);
6479 /* SWP instruction */
6482 /* ??? This is not really atomic. However we know
6483 we never have multiple CPUs running in parallel,
6484 so it is good enough. */
6485 addr
= load_reg(s
, rn
);
6486 tmp
= load_reg(s
, rm
);
6487 if (insn
& (1 << 22)) {
6488 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6489 gen_st8(tmp
, addr
, IS_USER(s
));
6491 tmp2
= gen_ld32(addr
, IS_USER(s
));
6492 gen_st32(tmp
, addr
, IS_USER(s
));
6495 store_reg(s
, rd
, tmp2
);
6501 /* Misc load/store */
6502 rn
= (insn
>> 16) & 0xf;
6503 rd
= (insn
>> 12) & 0xf;
6504 addr
= load_reg(s
, rn
);
6505 if (insn
& (1 << 24))
6506 gen_add_datah_offset(s
, insn
, 0, addr
);
6508 if (insn
& (1 << 20)) {
6512 tmp
= gen_ld16u(addr
, IS_USER(s
));
6515 tmp
= gen_ld8s(addr
, IS_USER(s
));
6519 tmp
= gen_ld16s(addr
, IS_USER(s
));
6523 } else if (sh
& 2) {
6527 tmp
= load_reg(s
, rd
);
6528 gen_st32(tmp
, addr
, IS_USER(s
));
6529 tcg_gen_addi_i32(addr
, addr
, 4);
6530 tmp
= load_reg(s
, rd
+ 1);
6531 gen_st32(tmp
, addr
, IS_USER(s
));
6535 tmp
= gen_ld32(addr
, IS_USER(s
));
6536 store_reg(s
, rd
, tmp
);
6537 tcg_gen_addi_i32(addr
, addr
, 4);
6538 tmp
= gen_ld32(addr
, IS_USER(s
));
6542 address_offset
= -4;
6545 tmp
= load_reg(s
, rd
);
6546 gen_st16(tmp
, addr
, IS_USER(s
));
6549 /* Perform base writeback before the loaded value to
6550 ensure correct behavior with overlapping index registers.
6551 ldrd with base writeback is is undefined if the
6552 destination and index registers overlap. */
6553 if (!(insn
& (1 << 24))) {
6554 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6555 store_reg(s
, rn
, addr
);
6556 } else if (insn
& (1 << 21)) {
6558 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6559 store_reg(s
, rn
, addr
);
6564 /* Complete the load. */
6565 store_reg(s
, rd
, tmp
);
6574 if (insn
& (1 << 4)) {
6576 /* Armv6 Media instructions. */
6578 rn
= (insn
>> 16) & 0xf;
6579 rd
= (insn
>> 12) & 0xf;
6580 rs
= (insn
>> 8) & 0xf;
6581 switch ((insn
>> 23) & 3) {
6582 case 0: /* Parallel add/subtract. */
6583 op1
= (insn
>> 20) & 7;
6584 tmp
= load_reg(s
, rn
);
6585 tmp2
= load_reg(s
, rm
);
6586 sh
= (insn
>> 5) & 7;
6587 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6589 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6591 store_reg(s
, rd
, tmp
);
6594 if ((insn
& 0x00700020) == 0) {
6595 /* Halfword pack. */
6596 tmp
= load_reg(s
, rn
);
6597 tmp2
= load_reg(s
, rm
);
6598 shift
= (insn
>> 7) & 0x1f;
6599 if (insn
& (1 << 6)) {
6603 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6604 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6605 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6609 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6610 tcg_gen_ext16u_i32(tmp
, tmp
);
6611 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6613 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6615 store_reg(s
, rd
, tmp
);
6616 } else if ((insn
& 0x00200020) == 0x00200000) {
6618 tmp
= load_reg(s
, rm
);
6619 shift
= (insn
>> 7) & 0x1f;
6620 if (insn
& (1 << 6)) {
6623 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6625 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6627 sh
= (insn
>> 16) & 0x1f;
6629 if (insn
& (1 << 22))
6630 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6632 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6634 store_reg(s
, rd
, tmp
);
6635 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6637 tmp
= load_reg(s
, rm
);
6638 sh
= (insn
>> 16) & 0x1f;
6640 if (insn
& (1 << 22))
6641 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6643 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6645 store_reg(s
, rd
, tmp
);
6646 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6648 tmp
= load_reg(s
, rn
);
6649 tmp2
= load_reg(s
, rm
);
6651 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6652 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6655 store_reg(s
, rd
, tmp
);
6656 } else if ((insn
& 0x000003e0) == 0x00000060) {
6657 tmp
= load_reg(s
, rm
);
6658 shift
= (insn
>> 10) & 3;
6659 /* ??? In many cases it's not neccessary to do a
6660 rotate, a shift is sufficient. */
6662 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6663 op1
= (insn
>> 20) & 7;
6665 case 0: gen_sxtb16(tmp
); break;
6666 case 2: gen_sxtb(tmp
); break;
6667 case 3: gen_sxth(tmp
); break;
6668 case 4: gen_uxtb16(tmp
); break;
6669 case 6: gen_uxtb(tmp
); break;
6670 case 7: gen_uxth(tmp
); break;
6671 default: goto illegal_op
;
6674 tmp2
= load_reg(s
, rn
);
6675 if ((op1
& 3) == 0) {
6676 gen_add16(tmp
, tmp2
);
6678 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6682 store_reg(s
, rd
, tmp
);
6683 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6685 tmp
= load_reg(s
, rm
);
6686 if (insn
& (1 << 22)) {
6687 if (insn
& (1 << 7)) {
6691 gen_helper_rbit(tmp
, tmp
);
6694 if (insn
& (1 << 7))
6697 tcg_gen_bswap32_i32(tmp
, tmp
);
6699 store_reg(s
, rd
, tmp
);
6704 case 2: /* Multiplies (Type 3). */
6705 tmp
= load_reg(s
, rm
);
6706 tmp2
= load_reg(s
, rs
);
6707 if (insn
& (1 << 20)) {
6708 /* Signed multiply most significant [accumulate]. */
6709 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6710 if (insn
& (1 << 5))
6711 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6712 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6714 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6716 tmp2
= load_reg(s
, rd
);
6717 if (insn
& (1 << 6)) {
6718 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6720 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6724 store_reg(s
, rn
, tmp
);
6726 if (insn
& (1 << 5))
6727 gen_swap_half(tmp2
);
6728 gen_smul_dual(tmp
, tmp2
);
6729 /* This addition cannot overflow. */
6730 if (insn
& (1 << 6)) {
6731 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6733 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6736 if (insn
& (1 << 22)) {
6737 /* smlald, smlsld */
6738 tmp64
= tcg_temp_new_i64();
6739 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6741 gen_addq(s
, tmp64
, rd
, rn
);
6742 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6744 /* smuad, smusd, smlad, smlsd */
6747 tmp2
= load_reg(s
, rd
);
6748 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6751 store_reg(s
, rn
, tmp
);
6756 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6758 case 0: /* Unsigned sum of absolute differences. */
6760 tmp
= load_reg(s
, rm
);
6761 tmp2
= load_reg(s
, rs
);
6762 gen_helper_usad8(tmp
, tmp
, tmp2
);
6765 tmp2
= load_reg(s
, rd
);
6766 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6769 store_reg(s
, rn
, tmp
);
6771 case 0x20: case 0x24: case 0x28: case 0x2c:
6772 /* Bitfield insert/clear. */
6774 shift
= (insn
>> 7) & 0x1f;
6775 i
= (insn
>> 16) & 0x1f;
6779 tcg_gen_movi_i32(tmp
, 0);
6781 tmp
= load_reg(s
, rm
);
6784 tmp2
= load_reg(s
, rd
);
6785 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6788 store_reg(s
, rd
, tmp
);
6790 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6791 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6793 tmp
= load_reg(s
, rm
);
6794 shift
= (insn
>> 7) & 0x1f;
6795 i
= ((insn
>> 16) & 0x1f) + 1;
6800 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6802 gen_sbfx(tmp
, shift
, i
);
6805 store_reg(s
, rd
, tmp
);
6815 /* Check for undefined extension instructions
6816 * per the ARM Bible IE:
6817 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6819 sh
= (0xf << 20) | (0xf << 4);
6820 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6824 /* load/store byte/word */
6825 rn
= (insn
>> 16) & 0xf;
6826 rd
= (insn
>> 12) & 0xf;
6827 tmp2
= load_reg(s
, rn
);
6828 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6829 if (insn
& (1 << 24))
6830 gen_add_data_offset(s
, insn
, tmp2
);
6831 if (insn
& (1 << 20)) {
6833 if (insn
& (1 << 22)) {
6834 tmp
= gen_ld8u(tmp2
, i
);
6836 tmp
= gen_ld32(tmp2
, i
);
6840 tmp
= load_reg(s
, rd
);
6841 if (insn
& (1 << 22))
6842 gen_st8(tmp
, tmp2
, i
);
6844 gen_st32(tmp
, tmp2
, i
);
6846 if (!(insn
& (1 << 24))) {
6847 gen_add_data_offset(s
, insn
, tmp2
);
6848 store_reg(s
, rn
, tmp2
);
6849 } else if (insn
& (1 << 21)) {
6850 store_reg(s
, rn
, tmp2
);
6854 if (insn
& (1 << 20)) {
6855 /* Complete the load. */
6859 store_reg(s
, rd
, tmp
);
6865 int j
, n
, user
, loaded_base
;
6867 /* load/store multiple words */
6868 /* XXX: store correct base if write back */
6870 if (insn
& (1 << 22)) {
6872 goto illegal_op
; /* only usable in supervisor mode */
6874 if ((insn
& (1 << 15)) == 0)
6877 rn
= (insn
>> 16) & 0xf;
6878 addr
= load_reg(s
, rn
);
6880 /* compute total size */
6882 TCGV_UNUSED(loaded_var
);
6885 if (insn
& (1 << i
))
6888 /* XXX: test invalid n == 0 case ? */
6889 if (insn
& (1 << 23)) {
6890 if (insn
& (1 << 24)) {
6892 tcg_gen_addi_i32(addr
, addr
, 4);
6894 /* post increment */
6897 if (insn
& (1 << 24)) {
6899 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6901 /* post decrement */
6903 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6908 if (insn
& (1 << i
)) {
6909 if (insn
& (1 << 20)) {
6911 tmp
= gen_ld32(addr
, IS_USER(s
));
6915 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6917 } else if (i
== rn
) {
6921 store_reg(s
, i
, tmp
);
6926 /* special case: r15 = PC + 8 */
6927 val
= (long)s
->pc
+ 4;
6929 tcg_gen_movi_i32(tmp
, val
);
6932 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6934 tmp
= load_reg(s
, i
);
6936 gen_st32(tmp
, addr
, IS_USER(s
));
6939 /* no need to add after the last transfer */
6941 tcg_gen_addi_i32(addr
, addr
, 4);
6944 if (insn
& (1 << 21)) {
6946 if (insn
& (1 << 23)) {
6947 if (insn
& (1 << 24)) {
6950 /* post increment */
6951 tcg_gen_addi_i32(addr
, addr
, 4);
6954 if (insn
& (1 << 24)) {
6957 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6959 /* post decrement */
6960 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6963 store_reg(s
, rn
, addr
);
6968 store_reg(s
, rn
, loaded_var
);
6970 if ((insn
& (1 << 22)) && !user
) {
6971 /* Restore CPSR from SPSR. */
6972 tmp
= load_cpu_field(spsr
);
6973 gen_set_cpsr(tmp
, 0xffffffff);
6975 s
->is_jmp
= DISAS_UPDATE
;
6984 /* branch (and link) */
6985 val
= (int32_t)s
->pc
;
6986 if (insn
& (1 << 24)) {
6988 tcg_gen_movi_i32(tmp
, val
);
6989 store_reg(s
, 14, tmp
);
6991 offset
= (((int32_t)insn
<< 8) >> 8);
6992 val
+= (offset
<< 2) + 4;
7000 if (disas_coproc_insn(env
, s
, insn
))
7005 gen_set_pc_im(s
->pc
);
7006 s
->is_jmp
= DISAS_SWI
;
7010 gen_set_condexec(s
);
7011 gen_set_pc_im(s
->pc
- 4);
7012 gen_exception(EXCP_UDEF
);
7013 s
->is_jmp
= DISAS_JUMP
;
7019 /* Return true if this is a Thumb-2 logical op. */
7021 thumb2_logic_op(int op
)
7026 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7027 then set condition code flags based on the result of the operation.
7028 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7029 to the high bit of T1.
7030 Returns zero if the opcode is valid. */
7033 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7040 tcg_gen_and_i32(t0
, t0
, t1
);
7044 tcg_gen_bic_i32(t0
, t0
, t1
);
7048 tcg_gen_or_i32(t0
, t0
, t1
);
7052 tcg_gen_not_i32(t1
, t1
);
7053 tcg_gen_or_i32(t0
, t0
, t1
);
7057 tcg_gen_xor_i32(t0
, t0
, t1
);
7062 gen_helper_add_cc(t0
, t0
, t1
);
7064 tcg_gen_add_i32(t0
, t0
, t1
);
7068 gen_helper_adc_cc(t0
, t0
, t1
);
7074 gen_helper_sbc_cc(t0
, t0
, t1
);
7076 gen_sub_carry(t0
, t0
, t1
);
7080 gen_helper_sub_cc(t0
, t0
, t1
);
7082 tcg_gen_sub_i32(t0
, t0
, t1
);
7086 gen_helper_sub_cc(t0
, t1
, t0
);
7088 tcg_gen_sub_i32(t0
, t1
, t0
);
7090 default: /* 5, 6, 7, 9, 12, 15. */
7096 gen_set_CF_bit31(t1
);
7101 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7103 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7105 uint32_t insn
, imm
, shift
, offset
;
7106 uint32_t rd
, rn
, rm
, rs
;
7117 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7118 || arm_feature (env
, ARM_FEATURE_M
))) {
7119 /* Thumb-1 cores may need to treat bl and blx as a pair of
7120 16-bit instructions to get correct prefetch abort behavior. */
7122 if ((insn
& (1 << 12)) == 0) {
7123 /* Second half of blx. */
7124 offset
= ((insn
& 0x7ff) << 1);
7125 tmp
= load_reg(s
, 14);
7126 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7127 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7130 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7131 store_reg(s
, 14, tmp2
);
7135 if (insn
& (1 << 11)) {
7136 /* Second half of bl. */
7137 offset
= ((insn
& 0x7ff) << 1) | 1;
7138 tmp
= load_reg(s
, 14);
7139 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7142 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7143 store_reg(s
, 14, tmp2
);
7147 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7148 /* Instruction spans a page boundary. Implement it as two
7149 16-bit instructions in case the second half causes an
7151 offset
= ((int32_t)insn
<< 21) >> 9;
7152 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7155 /* Fall through to 32-bit decode. */
7158 insn
= lduw_code(s
->pc
);
7160 insn
|= (uint32_t)insn_hw1
<< 16;
7162 if ((insn
& 0xf800e800) != 0xf000e800) {
7166 rn
= (insn
>> 16) & 0xf;
7167 rs
= (insn
>> 12) & 0xf;
7168 rd
= (insn
>> 8) & 0xf;
7170 switch ((insn
>> 25) & 0xf) {
7171 case 0: case 1: case 2: case 3:
7172 /* 16-bit instructions. Should never happen. */
7175 if (insn
& (1 << 22)) {
7176 /* Other load/store, table branch. */
7177 if (insn
& 0x01200000) {
7178 /* Load/store doubleword. */
7181 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7183 addr
= load_reg(s
, rn
);
7185 offset
= (insn
& 0xff) * 4;
7186 if ((insn
& (1 << 23)) == 0)
7188 if (insn
& (1 << 24)) {
7189 tcg_gen_addi_i32(addr
, addr
, offset
);
7192 if (insn
& (1 << 20)) {
7194 tmp
= gen_ld32(addr
, IS_USER(s
));
7195 store_reg(s
, rs
, tmp
);
7196 tcg_gen_addi_i32(addr
, addr
, 4);
7197 tmp
= gen_ld32(addr
, IS_USER(s
));
7198 store_reg(s
, rd
, tmp
);
7201 tmp
= load_reg(s
, rs
);
7202 gen_st32(tmp
, addr
, IS_USER(s
));
7203 tcg_gen_addi_i32(addr
, addr
, 4);
7204 tmp
= load_reg(s
, rd
);
7205 gen_st32(tmp
, addr
, IS_USER(s
));
7207 if (insn
& (1 << 21)) {
7208 /* Base writeback. */
7211 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7212 store_reg(s
, rn
, addr
);
7216 } else if ((insn
& (1 << 23)) == 0) {
7217 /* Load/store exclusive word. */
7218 addr
= tcg_temp_local_new();
7219 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7220 if (insn
& (1 << 20)) {
7221 gen_helper_mark_exclusive(cpu_env
, addr
);
7222 tmp
= gen_ld32(addr
, IS_USER(s
));
7223 store_reg(s
, rd
, tmp
);
7225 int label
= gen_new_label();
7226 tmp2
= tcg_temp_local_new();
7227 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7228 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7229 tmp
= load_reg(s
, rs
);
7230 gen_st32(tmp
, addr
, IS_USER(s
));
7231 gen_set_label(label
);
7232 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7233 tcg_temp_free(tmp2
);
7235 tcg_temp_free(addr
);
7236 } else if ((insn
& (1 << 6)) == 0) {
7240 tcg_gen_movi_i32(addr
, s
->pc
);
7242 addr
= load_reg(s
, rn
);
7244 tmp
= load_reg(s
, rm
);
7245 tcg_gen_add_i32(addr
, addr
, tmp
);
7246 if (insn
& (1 << 4)) {
7248 tcg_gen_add_i32(addr
, addr
, tmp
);
7250 tmp
= gen_ld16u(addr
, IS_USER(s
));
7253 tmp
= gen_ld8u(addr
, IS_USER(s
));
7256 tcg_gen_shli_i32(tmp
, tmp
, 1);
7257 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7258 store_reg(s
, 15, tmp
);
7260 /* Load/store exclusive byte/halfword/doubleword. */
7261 /* ??? These are not really atomic. However we know
7262 we never have multiple CPUs running in parallel,
7263 so it is good enough. */
7264 op
= (insn
>> 4) & 0x3;
7265 addr
= tcg_temp_local_new();
7266 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7267 if (insn
& (1 << 20)) {
7268 gen_helper_mark_exclusive(cpu_env
, addr
);
7271 tmp
= gen_ld8u(addr
, IS_USER(s
));
7274 tmp
= gen_ld16u(addr
, IS_USER(s
));
7277 tmp
= gen_ld32(addr
, IS_USER(s
));
7278 tcg_gen_addi_i32(addr
, addr
, 4);
7279 tmp2
= gen_ld32(addr
, IS_USER(s
));
7280 store_reg(s
, rd
, tmp2
);
7285 store_reg(s
, rs
, tmp
);
7287 int label
= gen_new_label();
7288 tmp2
= tcg_temp_local_new();
7289 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7290 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7291 tmp
= load_reg(s
, rs
);
7294 gen_st8(tmp
, addr
, IS_USER(s
));
7297 gen_st16(tmp
, addr
, IS_USER(s
));
7300 gen_st32(tmp
, addr
, IS_USER(s
));
7301 tcg_gen_addi_i32(addr
, addr
, 4);
7302 tmp
= load_reg(s
, rd
);
7303 gen_st32(tmp
, addr
, IS_USER(s
));
7308 gen_set_label(label
);
7309 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7310 tcg_temp_free(tmp2
);
7312 tcg_temp_free(addr
);
7315 /* Load/store multiple, RFE, SRS. */
7316 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7317 /* Not available in user mode. */
7320 if (insn
& (1 << 20)) {
7322 addr
= load_reg(s
, rn
);
7323 if ((insn
& (1 << 24)) == 0)
7324 tcg_gen_addi_i32(addr
, addr
, -8);
7325 /* Load PC into tmp and CPSR into tmp2. */
7326 tmp
= gen_ld32(addr
, 0);
7327 tcg_gen_addi_i32(addr
, addr
, 4);
7328 tmp2
= gen_ld32(addr
, 0);
7329 if (insn
& (1 << 21)) {
7330 /* Base writeback. */
7331 if (insn
& (1 << 24)) {
7332 tcg_gen_addi_i32(addr
, addr
, 4);
7334 tcg_gen_addi_i32(addr
, addr
, -4);
7336 store_reg(s
, rn
, addr
);
7340 gen_rfe(s
, tmp
, tmp2
);
7344 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7345 addr
= load_reg(s
, 13);
7348 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7350 if ((insn
& (1 << 24)) == 0) {
7351 tcg_gen_addi_i32(addr
, addr
, -8);
7353 tmp
= load_reg(s
, 14);
7354 gen_st32(tmp
, addr
, 0);
7355 tcg_gen_addi_i32(addr
, addr
, 4);
7357 gen_helper_cpsr_read(tmp
);
7358 gen_st32(tmp
, addr
, 0);
7359 if (insn
& (1 << 21)) {
7360 if ((insn
& (1 << 24)) == 0) {
7361 tcg_gen_addi_i32(addr
, addr
, -4);
7363 tcg_gen_addi_i32(addr
, addr
, 4);
7365 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7366 store_reg(s
, 13, addr
);
7368 gen_helper_set_r13_banked(cpu_env
,
7369 tcg_const_i32(op
), addr
);
7377 /* Load/store multiple. */
7378 addr
= load_reg(s
, rn
);
7380 for (i
= 0; i
< 16; i
++) {
7381 if (insn
& (1 << i
))
7384 if (insn
& (1 << 24)) {
7385 tcg_gen_addi_i32(addr
, addr
, -offset
);
7388 for (i
= 0; i
< 16; i
++) {
7389 if ((insn
& (1 << i
)) == 0)
7391 if (insn
& (1 << 20)) {
7393 tmp
= gen_ld32(addr
, IS_USER(s
));
7397 store_reg(s
, i
, tmp
);
7401 tmp
= load_reg(s
, i
);
7402 gen_st32(tmp
, addr
, IS_USER(s
));
7404 tcg_gen_addi_i32(addr
, addr
, 4);
7406 if (insn
& (1 << 21)) {
7407 /* Base register writeback. */
7408 if (insn
& (1 << 24)) {
7409 tcg_gen_addi_i32(addr
, addr
, -offset
);
7411 /* Fault if writeback register is in register list. */
7412 if (insn
& (1 << rn
))
7414 store_reg(s
, rn
, addr
);
7421 case 5: /* Data processing register constant shift. */
7424 tcg_gen_movi_i32(tmp
, 0);
7426 tmp
= load_reg(s
, rn
);
7428 tmp2
= load_reg(s
, rm
);
7429 op
= (insn
>> 21) & 0xf;
7430 shiftop
= (insn
>> 4) & 3;
7431 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7432 conds
= (insn
& (1 << 20)) != 0;
7433 logic_cc
= (conds
&& thumb2_logic_op(op
));
7434 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7435 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7439 store_reg(s
, rd
, tmp
);
7444 case 13: /* Misc data processing. */
7445 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7446 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7449 case 0: /* Register controlled shift. */
7450 tmp
= load_reg(s
, rn
);
7451 tmp2
= load_reg(s
, rm
);
7452 if ((insn
& 0x70) != 0)
7454 op
= (insn
>> 21) & 3;
7455 logic_cc
= (insn
& (1 << 20)) != 0;
7456 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7459 store_reg_bx(env
, s
, rd
, tmp
);
7461 case 1: /* Sign/zero extend. */
7462 tmp
= load_reg(s
, rm
);
7463 shift
= (insn
>> 4) & 3;
7464 /* ??? In many cases it's not neccessary to do a
7465 rotate, a shift is sufficient. */
7467 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7468 op
= (insn
>> 20) & 7;
7470 case 0: gen_sxth(tmp
); break;
7471 case 1: gen_uxth(tmp
); break;
7472 case 2: gen_sxtb16(tmp
); break;
7473 case 3: gen_uxtb16(tmp
); break;
7474 case 4: gen_sxtb(tmp
); break;
7475 case 5: gen_uxtb(tmp
); break;
7476 default: goto illegal_op
;
7479 tmp2
= load_reg(s
, rn
);
7480 if ((op
>> 1) == 1) {
7481 gen_add16(tmp
, tmp2
);
7483 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7487 store_reg(s
, rd
, tmp
);
7489 case 2: /* SIMD add/subtract. */
7490 op
= (insn
>> 20) & 7;
7491 shift
= (insn
>> 4) & 7;
7492 if ((op
& 3) == 3 || (shift
& 3) == 3)
7494 tmp
= load_reg(s
, rn
);
7495 tmp2
= load_reg(s
, rm
);
7496 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7498 store_reg(s
, rd
, tmp
);
7500 case 3: /* Other data processing. */
7501 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7503 /* Saturating add/subtract. */
7504 tmp
= load_reg(s
, rn
);
7505 tmp2
= load_reg(s
, rm
);
7507 gen_helper_double_saturate(tmp
, tmp
);
7509 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7511 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7514 tmp
= load_reg(s
, rn
);
7516 case 0x0a: /* rbit */
7517 gen_helper_rbit(tmp
, tmp
);
7519 case 0x08: /* rev */
7520 tcg_gen_bswap32_i32(tmp
, tmp
);
7522 case 0x09: /* rev16 */
7525 case 0x0b: /* revsh */
7528 case 0x10: /* sel */
7529 tmp2
= load_reg(s
, rm
);
7531 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7532 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7536 case 0x18: /* clz */
7537 gen_helper_clz(tmp
, tmp
);
7543 store_reg(s
, rd
, tmp
);
7545 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7546 op
= (insn
>> 4) & 0xf;
7547 tmp
= load_reg(s
, rn
);
7548 tmp2
= load_reg(s
, rm
);
7549 switch ((insn
>> 20) & 7) {
7550 case 0: /* 32 x 32 -> 32 */
7551 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7554 tmp2
= load_reg(s
, rs
);
7556 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7558 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7562 case 1: /* 16 x 16 -> 32 */
7563 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7566 tmp2
= load_reg(s
, rs
);
7567 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7571 case 2: /* Dual multiply add. */
7572 case 4: /* Dual multiply subtract. */
7574 gen_swap_half(tmp2
);
7575 gen_smul_dual(tmp
, tmp2
);
7576 /* This addition cannot overflow. */
7577 if (insn
& (1 << 22)) {
7578 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7580 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7585 tmp2
= load_reg(s
, rs
);
7586 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7590 case 3: /* 32 * 16 -> 32msb */
7592 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7595 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7596 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7598 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7601 tmp2
= load_reg(s
, rs
);
7602 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7606 case 5: case 6: /* 32 * 32 -> 32msb */
7607 gen_imull(tmp
, tmp2
);
7608 if (insn
& (1 << 5)) {
7609 gen_roundqd(tmp
, tmp2
);
7616 tmp2
= load_reg(s
, rs
);
7617 if (insn
& (1 << 21)) {
7618 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7620 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7625 case 7: /* Unsigned sum of absolute differences. */
7626 gen_helper_usad8(tmp
, tmp
, tmp2
);
7629 tmp2
= load_reg(s
, rs
);
7630 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7635 store_reg(s
, rd
, tmp
);
7637 case 6: case 7: /* 64-bit multiply, Divide. */
7638 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7639 tmp
= load_reg(s
, rn
);
7640 tmp2
= load_reg(s
, rm
);
7641 if ((op
& 0x50) == 0x10) {
7643 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7646 gen_helper_udiv(tmp
, tmp
, tmp2
);
7648 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7650 store_reg(s
, rd
, tmp
);
7651 } else if ((op
& 0xe) == 0xc) {
7652 /* Dual multiply accumulate long. */
7654 gen_swap_half(tmp2
);
7655 gen_smul_dual(tmp
, tmp2
);
7657 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7659 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7663 tmp64
= tcg_temp_new_i64();
7664 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7666 gen_addq(s
, tmp64
, rs
, rd
);
7667 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7670 /* Unsigned 64-bit multiply */
7671 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7675 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7677 tmp64
= tcg_temp_new_i64();
7678 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7681 /* Signed 64-bit multiply */
7682 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7687 gen_addq_lo(s
, tmp64
, rs
);
7688 gen_addq_lo(s
, tmp64
, rd
);
7689 } else if (op
& 0x40) {
7690 /* 64-bit accumulate. */
7691 gen_addq(s
, tmp64
, rs
, rd
);
7693 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7698 case 6: case 7: case 14: case 15:
7700 if (((insn
>> 24) & 3) == 3) {
7701 /* Translate into the equivalent ARM encoding. */
7702 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7703 if (disas_neon_data_insn(env
, s
, insn
))
7706 if (insn
& (1 << 28))
7708 if (disas_coproc_insn (env
, s
, insn
))
7712 case 8: case 9: case 10: case 11:
7713 if (insn
& (1 << 15)) {
7714 /* Branches, misc control. */
7715 if (insn
& 0x5000) {
7716 /* Unconditional branch. */
7717 /* signextend(hw1[10:0]) -> offset[:12]. */
7718 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7719 /* hw1[10:0] -> offset[11:1]. */
7720 offset
|= (insn
& 0x7ff) << 1;
7721 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7722 offset[24:22] already have the same value because of the
7723 sign extension above. */
7724 offset
^= ((~insn
) & (1 << 13)) << 10;
7725 offset
^= ((~insn
) & (1 << 11)) << 11;
7727 if (insn
& (1 << 14)) {
7728 /* Branch and link. */
7729 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7733 if (insn
& (1 << 12)) {
7738 offset
&= ~(uint32_t)2;
7739 gen_bx_im(s
, offset
);
7741 } else if (((insn
>> 23) & 7) == 7) {
7743 if (insn
& (1 << 13))
7746 if (insn
& (1 << 26)) {
7747 /* Secure monitor call (v6Z) */
7748 goto illegal_op
; /* not implemented. */
7750 op
= (insn
>> 20) & 7;
7752 case 0: /* msr cpsr. */
7754 tmp
= load_reg(s
, rn
);
7755 addr
= tcg_const_i32(insn
& 0xff);
7756 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7761 case 1: /* msr spsr. */
7764 tmp
= load_reg(s
, rn
);
7766 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7770 case 2: /* cps, nop-hint. */
7771 if (((insn
>> 8) & 7) == 0) {
7772 gen_nop_hint(s
, insn
& 0xff);
7774 /* Implemented as NOP in user mode. */
7779 if (insn
& (1 << 10)) {
7780 if (insn
& (1 << 7))
7782 if (insn
& (1 << 6))
7784 if (insn
& (1 << 5))
7786 if (insn
& (1 << 9))
7787 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7789 if (insn
& (1 << 8)) {
7791 imm
|= (insn
& 0x1f);
7794 gen_set_psr_im(s
, offset
, 0, imm
);
7797 case 3: /* Special control operations. */
7798 op
= (insn
>> 4) & 0xf;
7801 gen_helper_clrex(cpu_env
);
7806 /* These execute as NOPs. */
7814 /* Trivial implementation equivalent to bx. */
7815 tmp
= load_reg(s
, rn
);
7818 case 5: /* Exception return. */
7819 /* Unpredictable in user mode. */
7821 case 6: /* mrs cpsr. */
7824 addr
= tcg_const_i32(insn
& 0xff);
7825 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7827 gen_helper_cpsr_read(tmp
);
7829 store_reg(s
, rd
, tmp
);
7831 case 7: /* mrs spsr. */
7832 /* Not accessible in user mode. */
7833 if (IS_USER(s
) || IS_M(env
))
7835 tmp
= load_cpu_field(spsr
);
7836 store_reg(s
, rd
, tmp
);
7841 /* Conditional branch. */
7842 op
= (insn
>> 22) & 0xf;
7843 /* Generate a conditional jump to next instruction. */
7844 s
->condlabel
= gen_new_label();
7845 gen_test_cc(op
^ 1, s
->condlabel
);
7848 /* offset[11:1] = insn[10:0] */
7849 offset
= (insn
& 0x7ff) << 1;
7850 /* offset[17:12] = insn[21:16]. */
7851 offset
|= (insn
& 0x003f0000) >> 4;
7852 /* offset[31:20] = insn[26]. */
7853 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7854 /* offset[18] = insn[13]. */
7855 offset
|= (insn
& (1 << 13)) << 5;
7856 /* offset[19] = insn[11]. */
7857 offset
|= (insn
& (1 << 11)) << 8;
7859 /* jump to the offset */
7860 gen_jmp(s
, s
->pc
+ offset
);
7863 /* Data processing immediate. */
7864 if (insn
& (1 << 25)) {
7865 if (insn
& (1 << 24)) {
7866 if (insn
& (1 << 20))
7868 /* Bitfield/Saturate. */
7869 op
= (insn
>> 21) & 7;
7871 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7874 tcg_gen_movi_i32(tmp
, 0);
7876 tmp
= load_reg(s
, rn
);
7879 case 2: /* Signed bitfield extract. */
7881 if (shift
+ imm
> 32)
7884 gen_sbfx(tmp
, shift
, imm
);
7886 case 6: /* Unsigned bitfield extract. */
7888 if (shift
+ imm
> 32)
7891 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7893 case 3: /* Bitfield insert/clear. */
7896 imm
= imm
+ 1 - shift
;
7898 tmp2
= load_reg(s
, rd
);
7899 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7905 default: /* Saturate. */
7908 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7910 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7912 tmp2
= tcg_const_i32(imm
);
7915 if ((op
& 1) && shift
== 0)
7916 gen_helper_usat16(tmp
, tmp
, tmp2
);
7918 gen_helper_usat(tmp
, tmp
, tmp2
);
7921 if ((op
& 1) && shift
== 0)
7922 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7924 gen_helper_ssat(tmp
, tmp
, tmp2
);
7928 store_reg(s
, rd
, tmp
);
7930 imm
= ((insn
& 0x04000000) >> 15)
7931 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7932 if (insn
& (1 << 22)) {
7933 /* 16-bit immediate. */
7934 imm
|= (insn
>> 4) & 0xf000;
7935 if (insn
& (1 << 23)) {
7937 tmp
= load_reg(s
, rd
);
7938 tcg_gen_ext16u_i32(tmp
, tmp
);
7939 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7943 tcg_gen_movi_i32(tmp
, imm
);
7946 /* Add/sub 12-bit immediate. */
7948 offset
= s
->pc
& ~(uint32_t)3;
7949 if (insn
& (1 << 23))
7954 tcg_gen_movi_i32(tmp
, offset
);
7956 tmp
= load_reg(s
, rn
);
7957 if (insn
& (1 << 23))
7958 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7960 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7963 store_reg(s
, rd
, tmp
);
7966 int shifter_out
= 0;
7967 /* modified 12-bit immediate. */
7968 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7969 imm
= (insn
& 0xff);
7972 /* Nothing to do. */
7974 case 1: /* 00XY00XY */
7977 case 2: /* XY00XY00 */
7981 case 3: /* XYXYXYXY */
7985 default: /* Rotated constant. */
7986 shift
= (shift
<< 1) | (imm
>> 7);
7988 imm
= imm
<< (32 - shift
);
7993 tcg_gen_movi_i32(tmp2
, imm
);
7994 rn
= (insn
>> 16) & 0xf;
7997 tcg_gen_movi_i32(tmp
, 0);
7999 tmp
= load_reg(s
, rn
);
8001 op
= (insn
>> 21) & 0xf;
8002 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8003 shifter_out
, tmp
, tmp2
))
8006 rd
= (insn
>> 8) & 0xf;
8008 store_reg(s
, rd
, tmp
);
8015 case 12: /* Load/store single data item. */
8020 if ((insn
& 0x01100000) == 0x01000000) {
8021 if (disas_neon_ls_insn(env
, s
, insn
))
8029 /* s->pc has already been incremented by 4. */
8030 imm
= s
->pc
& 0xfffffffc;
8031 if (insn
& (1 << 23))
8032 imm
+= insn
& 0xfff;
8034 imm
-= insn
& 0xfff;
8035 tcg_gen_movi_i32(addr
, imm
);
8037 addr
= load_reg(s
, rn
);
8038 if (insn
& (1 << 23)) {
8039 /* Positive offset. */
8041 tcg_gen_addi_i32(addr
, addr
, imm
);
8043 op
= (insn
>> 8) & 7;
8046 case 0: case 8: /* Shifted Register. */
8047 shift
= (insn
>> 4) & 0xf;
8050 tmp
= load_reg(s
, rm
);
8052 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8053 tcg_gen_add_i32(addr
, addr
, tmp
);
8056 case 4: /* Negative offset. */
8057 tcg_gen_addi_i32(addr
, addr
, -imm
);
8059 case 6: /* User privilege. */
8060 tcg_gen_addi_i32(addr
, addr
, imm
);
8063 case 1: /* Post-decrement. */
8066 case 3: /* Post-increment. */
8070 case 5: /* Pre-decrement. */
8073 case 7: /* Pre-increment. */
8074 tcg_gen_addi_i32(addr
, addr
, imm
);
8082 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8083 if (insn
& (1 << 20)) {
8085 if (rs
== 15 && op
!= 2) {
8088 /* Memory hint. Implemented as NOP. */
8091 case 0: tmp
= gen_ld8u(addr
, user
); break;
8092 case 4: tmp
= gen_ld8s(addr
, user
); break;
8093 case 1: tmp
= gen_ld16u(addr
, user
); break;
8094 case 5: tmp
= gen_ld16s(addr
, user
); break;
8095 case 2: tmp
= gen_ld32(addr
, user
); break;
8096 default: goto illegal_op
;
8101 store_reg(s
, rs
, tmp
);
8108 tmp
= load_reg(s
, rs
);
8110 case 0: gen_st8(tmp
, addr
, user
); break;
8111 case 1: gen_st16(tmp
, addr
, user
); break;
8112 case 2: gen_st32(tmp
, addr
, user
); break;
8113 default: goto illegal_op
;
8117 tcg_gen_addi_i32(addr
, addr
, imm
);
8119 store_reg(s
, rn
, addr
);
8133 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8135 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8142 if (s
->condexec_mask
) {
8143 cond
= s
->condexec_cond
;
8144 s
->condlabel
= gen_new_label();
8145 gen_test_cc(cond
^ 1, s
->condlabel
);
8149 insn
= lduw_code(s
->pc
);
8152 switch (insn
>> 12) {
8156 op
= (insn
>> 11) & 3;
8159 rn
= (insn
>> 3) & 7;
8160 tmp
= load_reg(s
, rn
);
8161 if (insn
& (1 << 10)) {
8164 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8167 rm
= (insn
>> 6) & 7;
8168 tmp2
= load_reg(s
, rm
);
8170 if (insn
& (1 << 9)) {
8171 if (s
->condexec_mask
)
8172 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8174 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8176 if (s
->condexec_mask
)
8177 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8179 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8182 store_reg(s
, rd
, tmp
);
8184 /* shift immediate */
8185 rm
= (insn
>> 3) & 7;
8186 shift
= (insn
>> 6) & 0x1f;
8187 tmp
= load_reg(s
, rm
);
8188 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8189 if (!s
->condexec_mask
)
8191 store_reg(s
, rd
, tmp
);
8195 /* arithmetic large immediate */
8196 op
= (insn
>> 11) & 3;
8197 rd
= (insn
>> 8) & 0x7;
8198 if (op
== 0) { /* mov */
8200 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8201 if (!s
->condexec_mask
)
8203 store_reg(s
, rd
, tmp
);
8205 tmp
= load_reg(s
, rd
);
8207 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8210 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8215 if (s
->condexec_mask
)
8216 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8218 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8220 store_reg(s
, rd
, tmp
);
8223 if (s
->condexec_mask
)
8224 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8226 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8228 store_reg(s
, rd
, tmp
);
8234 if (insn
& (1 << 11)) {
8235 rd
= (insn
>> 8) & 7;
8236 /* load pc-relative. Bit 1 of PC is ignored. */
8237 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8238 val
&= ~(uint32_t)2;
8240 tcg_gen_movi_i32(addr
, val
);
8241 tmp
= gen_ld32(addr
, IS_USER(s
));
8243 store_reg(s
, rd
, tmp
);
8246 if (insn
& (1 << 10)) {
8247 /* data processing extended or blx */
8248 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8249 rm
= (insn
>> 3) & 0xf;
8250 op
= (insn
>> 8) & 3;
8253 tmp
= load_reg(s
, rd
);
8254 tmp2
= load_reg(s
, rm
);
8255 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8257 store_reg(s
, rd
, tmp
);
8260 tmp
= load_reg(s
, rd
);
8261 tmp2
= load_reg(s
, rm
);
8262 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8266 case 2: /* mov/cpy */
8267 tmp
= load_reg(s
, rm
);
8268 store_reg(s
, rd
, tmp
);
8270 case 3:/* branch [and link] exchange thumb register */
8271 tmp
= load_reg(s
, rm
);
8272 if (insn
& (1 << 7)) {
8273 val
= (uint32_t)s
->pc
| 1;
8275 tcg_gen_movi_i32(tmp2
, val
);
8276 store_reg(s
, 14, tmp2
);
8284 /* data processing register */
8286 rm
= (insn
>> 3) & 7;
8287 op
= (insn
>> 6) & 0xf;
8288 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8289 /* the shift/rotate ops want the operands backwards */
8298 if (op
== 9) { /* neg */
8300 tcg_gen_movi_i32(tmp
, 0);
8301 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8302 tmp
= load_reg(s
, rd
);
8307 tmp2
= load_reg(s
, rm
);
8310 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8311 if (!s
->condexec_mask
)
8315 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8316 if (!s
->condexec_mask
)
8320 if (s
->condexec_mask
) {
8321 gen_helper_shl(tmp2
, tmp2
, tmp
);
8323 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8328 if (s
->condexec_mask
) {
8329 gen_helper_shr(tmp2
, tmp2
, tmp
);
8331 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8336 if (s
->condexec_mask
) {
8337 gen_helper_sar(tmp2
, tmp2
, tmp
);
8339 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8344 if (s
->condexec_mask
)
8347 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8350 if (s
->condexec_mask
)
8351 gen_sub_carry(tmp
, tmp
, tmp2
);
8353 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8356 if (s
->condexec_mask
) {
8357 gen_helper_ror(tmp2
, tmp2
, tmp
);
8359 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8364 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8369 if (s
->condexec_mask
)
8370 tcg_gen_neg_i32(tmp
, tmp2
);
8372 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8375 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8379 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8383 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8384 if (!s
->condexec_mask
)
8388 gen_mull(tmp
, tmp2
);
8389 if (!s
->condexec_mask
)
8393 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8394 if (!s
->condexec_mask
)
8398 tcg_gen_not_i32(tmp2
, tmp2
);
8399 if (!s
->condexec_mask
)
8407 store_reg(s
, rm
, tmp2
);
8411 store_reg(s
, rd
, tmp
);
8421 /* load/store register offset. */
8423 rn
= (insn
>> 3) & 7;
8424 rm
= (insn
>> 6) & 7;
8425 op
= (insn
>> 9) & 7;
8426 addr
= load_reg(s
, rn
);
8427 tmp
= load_reg(s
, rm
);
8428 tcg_gen_add_i32(addr
, addr
, tmp
);
8431 if (op
< 3) /* store */
8432 tmp
= load_reg(s
, rd
);
8436 gen_st32(tmp
, addr
, IS_USER(s
));
8439 gen_st16(tmp
, addr
, IS_USER(s
));
8442 gen_st8(tmp
, addr
, IS_USER(s
));
8445 tmp
= gen_ld8s(addr
, IS_USER(s
));
8448 tmp
= gen_ld32(addr
, IS_USER(s
));
8451 tmp
= gen_ld16u(addr
, IS_USER(s
));
8454 tmp
= gen_ld8u(addr
, IS_USER(s
));
8457 tmp
= gen_ld16s(addr
, IS_USER(s
));
8460 if (op
>= 3) /* load */
8461 store_reg(s
, rd
, tmp
);
8466 /* load/store word immediate offset */
8468 rn
= (insn
>> 3) & 7;
8469 addr
= load_reg(s
, rn
);
8470 val
= (insn
>> 4) & 0x7c;
8471 tcg_gen_addi_i32(addr
, addr
, val
);
8473 if (insn
& (1 << 11)) {
8475 tmp
= gen_ld32(addr
, IS_USER(s
));
8476 store_reg(s
, rd
, tmp
);
8479 tmp
= load_reg(s
, rd
);
8480 gen_st32(tmp
, addr
, IS_USER(s
));
8486 /* load/store byte immediate offset */
8488 rn
= (insn
>> 3) & 7;
8489 addr
= load_reg(s
, rn
);
8490 val
= (insn
>> 6) & 0x1f;
8491 tcg_gen_addi_i32(addr
, addr
, val
);
8493 if (insn
& (1 << 11)) {
8495 tmp
= gen_ld8u(addr
, IS_USER(s
));
8496 store_reg(s
, rd
, tmp
);
8499 tmp
= load_reg(s
, rd
);
8500 gen_st8(tmp
, addr
, IS_USER(s
));
8506 /* load/store halfword immediate offset */
8508 rn
= (insn
>> 3) & 7;
8509 addr
= load_reg(s
, rn
);
8510 val
= (insn
>> 5) & 0x3e;
8511 tcg_gen_addi_i32(addr
, addr
, val
);
8513 if (insn
& (1 << 11)) {
8515 tmp
= gen_ld16u(addr
, IS_USER(s
));
8516 store_reg(s
, rd
, tmp
);
8519 tmp
= load_reg(s
, rd
);
8520 gen_st16(tmp
, addr
, IS_USER(s
));
8526 /* load/store from stack */
8527 rd
= (insn
>> 8) & 7;
8528 addr
= load_reg(s
, 13);
8529 val
= (insn
& 0xff) * 4;
8530 tcg_gen_addi_i32(addr
, addr
, val
);
8532 if (insn
& (1 << 11)) {
8534 tmp
= gen_ld32(addr
, IS_USER(s
));
8535 store_reg(s
, rd
, tmp
);
8538 tmp
= load_reg(s
, rd
);
8539 gen_st32(tmp
, addr
, IS_USER(s
));
8545 /* add to high reg */
8546 rd
= (insn
>> 8) & 7;
8547 if (insn
& (1 << 11)) {
8549 tmp
= load_reg(s
, 13);
8551 /* PC. bit 1 is ignored. */
8553 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8555 val
= (insn
& 0xff) * 4;
8556 tcg_gen_addi_i32(tmp
, tmp
, val
);
8557 store_reg(s
, rd
, tmp
);
8562 op
= (insn
>> 8) & 0xf;
8565 /* adjust stack pointer */
8566 tmp
= load_reg(s
, 13);
8567 val
= (insn
& 0x7f) * 4;
8568 if (insn
& (1 << 7))
8569 val
= -(int32_t)val
;
8570 tcg_gen_addi_i32(tmp
, tmp
, val
);
8571 store_reg(s
, 13, tmp
);
8574 case 2: /* sign/zero extend. */
8577 rm
= (insn
>> 3) & 7;
8578 tmp
= load_reg(s
, rm
);
8579 switch ((insn
>> 6) & 3) {
8580 case 0: gen_sxth(tmp
); break;
8581 case 1: gen_sxtb(tmp
); break;
8582 case 2: gen_uxth(tmp
); break;
8583 case 3: gen_uxtb(tmp
); break;
8585 store_reg(s
, rd
, tmp
);
8587 case 4: case 5: case 0xc: case 0xd:
8589 addr
= load_reg(s
, 13);
8590 if (insn
& (1 << 8))
8594 for (i
= 0; i
< 8; i
++) {
8595 if (insn
& (1 << i
))
8598 if ((insn
& (1 << 11)) == 0) {
8599 tcg_gen_addi_i32(addr
, addr
, -offset
);
8601 for (i
= 0; i
< 8; i
++) {
8602 if (insn
& (1 << i
)) {
8603 if (insn
& (1 << 11)) {
8605 tmp
= gen_ld32(addr
, IS_USER(s
));
8606 store_reg(s
, i
, tmp
);
8609 tmp
= load_reg(s
, i
);
8610 gen_st32(tmp
, addr
, IS_USER(s
));
8612 /* advance to the next address. */
8613 tcg_gen_addi_i32(addr
, addr
, 4);
8617 if (insn
& (1 << 8)) {
8618 if (insn
& (1 << 11)) {
8620 tmp
= gen_ld32(addr
, IS_USER(s
));
8621 /* don't set the pc until the rest of the instruction
8625 tmp
= load_reg(s
, 14);
8626 gen_st32(tmp
, addr
, IS_USER(s
));
8628 tcg_gen_addi_i32(addr
, addr
, 4);
8630 if ((insn
& (1 << 11)) == 0) {
8631 tcg_gen_addi_i32(addr
, addr
, -offset
);
8633 /* write back the new stack pointer */
8634 store_reg(s
, 13, addr
);
8635 /* set the new PC value */
8636 if ((insn
& 0x0900) == 0x0900)
8640 case 1: case 3: case 9: case 11: /* czb */
8642 tmp
= load_reg(s
, rm
);
8643 s
->condlabel
= gen_new_label();
8645 if (insn
& (1 << 11))
8646 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8648 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8650 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8651 val
= (uint32_t)s
->pc
+ 2;
8656 case 15: /* IT, nop-hint. */
8657 if ((insn
& 0xf) == 0) {
8658 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8662 s
->condexec_cond
= (insn
>> 4) & 0xe;
8663 s
->condexec_mask
= insn
& 0x1f;
8664 /* No actual code generated for this insn, just setup state. */
8667 case 0xe: /* bkpt */
8668 gen_set_condexec(s
);
8669 gen_set_pc_im(s
->pc
- 2);
8670 gen_exception(EXCP_BKPT
);
8671 s
->is_jmp
= DISAS_JUMP
;
8676 rn
= (insn
>> 3) & 0x7;
8678 tmp
= load_reg(s
, rn
);
8679 switch ((insn
>> 6) & 3) {
8680 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8681 case 1: gen_rev16(tmp
); break;
8682 case 3: gen_revsh(tmp
); break;
8683 default: goto illegal_op
;
8685 store_reg(s
, rd
, tmp
);
8693 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8696 addr
= tcg_const_i32(16);
8697 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8701 addr
= tcg_const_i32(17);
8702 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8706 if (insn
& (1 << 4))
8707 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8710 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8720 /* load/store multiple */
8721 rn
= (insn
>> 8) & 0x7;
8722 addr
= load_reg(s
, rn
);
8723 for (i
= 0; i
< 8; i
++) {
8724 if (insn
& (1 << i
)) {
8725 if (insn
& (1 << 11)) {
8727 tmp
= gen_ld32(addr
, IS_USER(s
));
8728 store_reg(s
, i
, tmp
);
8731 tmp
= load_reg(s
, i
);
8732 gen_st32(tmp
, addr
, IS_USER(s
));
8734 /* advance to the next address */
8735 tcg_gen_addi_i32(addr
, addr
, 4);
8738 /* Base register writeback. */
8739 if ((insn
& (1 << rn
)) == 0) {
8740 store_reg(s
, rn
, addr
);
8747 /* conditional branch or swi */
8748 cond
= (insn
>> 8) & 0xf;
8754 gen_set_condexec(s
);
8755 gen_set_pc_im(s
->pc
);
8756 s
->is_jmp
= DISAS_SWI
;
8759 /* generate a conditional jump to next instruction */
8760 s
->condlabel
= gen_new_label();
8761 gen_test_cc(cond
^ 1, s
->condlabel
);
8764 /* jump to the offset */
8765 val
= (uint32_t)s
->pc
+ 2;
8766 offset
= ((int32_t)insn
<< 24) >> 24;
8772 if (insn
& (1 << 11)) {
8773 if (disas_thumb2_insn(env
, s
, insn
))
8777 /* unconditional branch */
8778 val
= (uint32_t)s
->pc
;
8779 offset
= ((int32_t)insn
<< 21) >> 21;
8780 val
+= (offset
<< 1) + 2;
8785 if (disas_thumb2_insn(env
, s
, insn
))
8791 gen_set_condexec(s
);
8792 gen_set_pc_im(s
->pc
- 4);
8793 gen_exception(EXCP_UDEF
);
8794 s
->is_jmp
= DISAS_JUMP
;
8798 gen_set_condexec(s
);
8799 gen_set_pc_im(s
->pc
- 2);
8800 gen_exception(EXCP_UDEF
);
8801 s
->is_jmp
= DISAS_JUMP
;
8804 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8805 basic block 'tb'. If search_pc is TRUE, also generate PC
8806 information for each intermediate instruction. */
8807 static inline void gen_intermediate_code_internal(CPUState
*env
,
8808 TranslationBlock
*tb
,
8811 DisasContext dc1
, *dc
= &dc1
;
8813 uint16_t *gen_opc_end
;
8815 target_ulong pc_start
;
8816 uint32_t next_page_start
;
8820 /* generate intermediate code */
8827 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8829 dc
->is_jmp
= DISAS_NEXT
;
8831 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8833 dc
->thumb
= env
->thumb
;
8834 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8835 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8836 #if !defined(CONFIG_USER_ONLY)
8838 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8840 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8843 cpu_F0s
= tcg_temp_new_i32();
8844 cpu_F1s
= tcg_temp_new_i32();
8845 cpu_F0d
= tcg_temp_new_i64();
8846 cpu_F1d
= tcg_temp_new_i64();
8849 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8850 cpu_M0
= tcg_temp_new_i64();
8851 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8854 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8856 max_insns
= CF_COUNT_MASK
;
8859 /* Reset the conditional execution bits immediately. This avoids
8860 complications trying to do it at the end of the block. */
8861 if (env
->condexec_bits
)
8863 TCGv tmp
= new_tmp();
8864 tcg_gen_movi_i32(tmp
, 0);
8865 store_cpu_field(tmp
, condexec_bits
);
8868 #ifdef CONFIG_USER_ONLY
8869 /* Intercept jump to the magic kernel page. */
8870 if (dc
->pc
>= 0xffff0000) {
8871 /* We always get here via a jump, so know we are not in a
8872 conditional execution block. */
8873 gen_exception(EXCP_KERNEL_TRAP
);
8874 dc
->is_jmp
= DISAS_UPDATE
;
8878 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8879 /* We always get here via a jump, so know we are not in a
8880 conditional execution block. */
8881 gen_exception(EXCP_EXCEPTION_EXIT
);
8882 dc
->is_jmp
= DISAS_UPDATE
;
8887 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8888 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8889 if (bp
->pc
== dc
->pc
) {
8890 gen_set_condexec(dc
);
8891 gen_set_pc_im(dc
->pc
);
8892 gen_exception(EXCP_DEBUG
);
8893 dc
->is_jmp
= DISAS_JUMP
;
8894 /* Advance PC so that clearing the breakpoint will
8895 invalidate this TB. */
8897 goto done_generating
;
8903 j
= gen_opc_ptr
- gen_opc_buf
;
8907 gen_opc_instr_start
[lj
++] = 0;
8909 gen_opc_pc
[lj
] = dc
->pc
;
8910 gen_opc_instr_start
[lj
] = 1;
8911 gen_opc_icount
[lj
] = num_insns
;
8914 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8918 disas_thumb_insn(env
, dc
);
8919 if (dc
->condexec_mask
) {
8920 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8921 | ((dc
->condexec_mask
>> 4) & 1);
8922 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8923 if (dc
->condexec_mask
== 0) {
8924 dc
->condexec_cond
= 0;
8928 disas_arm_insn(env
, dc
);
8931 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8935 if (dc
->condjmp
&& !dc
->is_jmp
) {
8936 gen_set_label(dc
->condlabel
);
8939 /* Translation stops when a conditional branch is encountered.
8940 * Otherwise the subsequent code could get translated several times.
8941 * Also stop translation when a page boundary is reached. This
8942 * ensures prefetch aborts occur at the right place. */
8944 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8945 !env
->singlestep_enabled
&&
8947 dc
->pc
< next_page_start
&&
8948 num_insns
< max_insns
);
8950 if (tb
->cflags
& CF_LAST_IO
) {
8952 /* FIXME: This can theoretically happen with self-modifying
8954 cpu_abort(env
, "IO on conditional branch instruction");
8959 /* At this stage dc->condjmp will only be set when the skipped
8960 instruction was a conditional branch or trap, and the PC has
8961 already been written. */
8962 if (unlikely(env
->singlestep_enabled
)) {
8963 /* Make sure the pc is updated, and raise a debug exception. */
8965 gen_set_condexec(dc
);
8966 if (dc
->is_jmp
== DISAS_SWI
) {
8967 gen_exception(EXCP_SWI
);
8969 gen_exception(EXCP_DEBUG
);
8971 gen_set_label(dc
->condlabel
);
8973 if (dc
->condjmp
|| !dc
->is_jmp
) {
8974 gen_set_pc_im(dc
->pc
);
8977 gen_set_condexec(dc
);
8978 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8979 gen_exception(EXCP_SWI
);
8981 /* FIXME: Single stepping a WFI insn will not halt
8983 gen_exception(EXCP_DEBUG
);
8986 /* While branches must always occur at the end of an IT block,
8987 there are a few other things that can cause us to terminate
8988 the TB in the middel of an IT block:
8989 - Exception generating instructions (bkpt, swi, undefined).
8991 - Hardware watchpoints.
8992 Hardware breakpoints have already been handled and skip this code.
8994 gen_set_condexec(dc
);
8995 switch(dc
->is_jmp
) {
8997 gen_goto_tb(dc
, 1, dc
->pc
);
9002 /* indicate that the hash table must be used to find the next TB */
9006 /* nothing more to generate */
9012 gen_exception(EXCP_SWI
);
9016 gen_set_label(dc
->condlabel
);
9017 gen_set_condexec(dc
);
9018 gen_goto_tb(dc
, 1, dc
->pc
);
9024 gen_icount_end(tb
, num_insns
);
9025 *gen_opc_ptr
= INDEX_op_end
;
9028 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9029 qemu_log("----------------\n");
9030 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9031 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9036 j
= gen_opc_ptr
- gen_opc_buf
;
9039 gen_opc_instr_start
[lj
++] = 0;
9041 tb
->size
= dc
->pc
- pc_start
;
9042 tb
->icount
= num_insns
;
9046 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9048 gen_intermediate_code_internal(env
, tb
, 0);
9051 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9053 gen_intermediate_code_internal(env
, tb
, 1);
9056 static const char *cpu_mode_names
[16] = {
9057 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9058 "???", "???", "???", "und", "???", "???", "???", "sys"
9061 void cpu_dump_state(CPUState
*env
, FILE *f
,
9062 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9072 /* ??? This assumes float64 and double have the same layout.
9073 Oh well, it's only debug dumps. */
9082 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9084 cpu_fprintf(f
, "\n");
9086 cpu_fprintf(f
, " ");
9088 psr
= cpsr_read(env
);
9089 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9091 psr
& (1 << 31) ? 'N' : '-',
9092 psr
& (1 << 30) ? 'Z' : '-',
9093 psr
& (1 << 29) ? 'C' : '-',
9094 psr
& (1 << 28) ? 'V' : '-',
9095 psr
& CPSR_T
? 'T' : 'A',
9096 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9099 for (i
= 0; i
< 16; i
++) {
9100 d
.d
= env
->vfp
.regs
[i
];
9104 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9105 i
* 2, (int)s0
.i
, s0
.s
,
9106 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9107 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9110 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9114 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9115 unsigned long searched_pc
, int pc_pos
, void *puc
)
9117 env
->regs
[15] = gen_opc_pc
[pc_pos
];