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];
79 static TCGv_i32 cpu_exclusive_addr
;
80 static TCGv_i32 cpu_exclusive_val
;
81 static TCGv_i32 cpu_exclusive_high
;
82 #ifdef CONFIG_USER_ONLY
83 static TCGv_i32 cpu_exclusive_test
;
84 static TCGv_i32 cpu_exclusive_info
;
87 /* FIXME: These should be removed. */
88 static TCGv cpu_F0s
, cpu_F1s
;
89 static TCGv_i64 cpu_F0d
, cpu_F1d
;
91 #include "gen-icount.h"
93 static const char *regnames
[] =
94 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
95 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
97 /* initialize TCG globals. */
98 void arm_translate_init(void)
102 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
104 for (i
= 0; i
< 16; i
++) {
105 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
106 offsetof(CPUState
, regs
[i
]),
109 cpu_exclusive_addr
= tcg_global_mem_new_i32(TCG_AREG0
,
110 offsetof(CPUState
, exclusive_addr
), "exclusive_addr");
111 cpu_exclusive_val
= tcg_global_mem_new_i32(TCG_AREG0
,
112 offsetof(CPUState
, exclusive_val
), "exclusive_val");
113 cpu_exclusive_high
= tcg_global_mem_new_i32(TCG_AREG0
,
114 offsetof(CPUState
, exclusive_high
), "exclusive_high");
115 #ifdef CONFIG_USER_ONLY
116 cpu_exclusive_test
= tcg_global_mem_new_i32(TCG_AREG0
,
117 offsetof(CPUState
, exclusive_test
), "exclusive_test");
118 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
119 offsetof(CPUState
, exclusive_info
), "exclusive_info");
126 static int num_temps
;
128 /* Allocate a temporary variable. */
129 static TCGv_i32
new_tmp(void)
132 return tcg_temp_new_i32();
135 /* Release a temporary variable. */
136 static void dead_tmp(TCGv tmp
)
142 static inline TCGv
load_cpu_offset(int offset
)
144 TCGv tmp
= new_tmp();
145 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
149 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
151 static inline void store_cpu_offset(TCGv var
, int offset
)
153 tcg_gen_st_i32(var
, cpu_env
, offset
);
157 #define store_cpu_field(var, name) \
158 store_cpu_offset(var, offsetof(CPUState, name))
160 /* Set a variable to the value of a CPU register. */
161 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
165 /* normaly, since we updated PC, we need only to add one insn */
167 addr
= (long)s
->pc
+ 2;
169 addr
= (long)s
->pc
+ 4;
170 tcg_gen_movi_i32(var
, addr
);
172 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
176 /* Create a new temporary and set it to the value of a CPU register. */
177 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
179 TCGv tmp
= new_tmp();
180 load_reg_var(s
, tmp
, reg
);
184 /* Set a CPU register. The source must be a temporary and will be
186 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
189 tcg_gen_andi_i32(var
, var
, ~1);
190 s
->is_jmp
= DISAS_JUMP
;
192 tcg_gen_mov_i32(cpu_R
[reg
], var
);
196 /* Value extensions. */
197 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
198 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
199 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
200 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
202 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
203 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
206 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
208 TCGv tmp_mask
= tcg_const_i32(mask
);
209 gen_helper_cpsr_write(var
, tmp_mask
);
210 tcg_temp_free_i32(tmp_mask
);
212 /* Set NZCV flags from the high 4 bits of var. */
213 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
215 static void gen_exception(int excp
)
217 TCGv tmp
= new_tmp();
218 tcg_gen_movi_i32(tmp
, excp
);
219 gen_helper_exception(tmp
);
223 static void gen_smul_dual(TCGv a
, TCGv b
)
225 TCGv tmp1
= new_tmp();
226 TCGv tmp2
= new_tmp();
227 tcg_gen_ext16s_i32(tmp1
, a
);
228 tcg_gen_ext16s_i32(tmp2
, b
);
229 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
231 tcg_gen_sari_i32(a
, a
, 16);
232 tcg_gen_sari_i32(b
, b
, 16);
233 tcg_gen_mul_i32(b
, b
, a
);
234 tcg_gen_mov_i32(a
, tmp1
);
238 /* Byteswap each halfword. */
239 static void gen_rev16(TCGv var
)
241 TCGv tmp
= new_tmp();
242 tcg_gen_shri_i32(tmp
, var
, 8);
243 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
244 tcg_gen_shli_i32(var
, var
, 8);
245 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
246 tcg_gen_or_i32(var
, var
, tmp
);
250 /* Byteswap low halfword and sign extend. */
251 static void gen_revsh(TCGv var
)
253 tcg_gen_ext16u_i32(var
, var
);
254 tcg_gen_bswap16_i32(var
, var
);
255 tcg_gen_ext16s_i32(var
, var
);
258 /* Unsigned bitfield extract. */
259 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
262 tcg_gen_shri_i32(var
, var
, shift
);
263 tcg_gen_andi_i32(var
, var
, mask
);
266 /* Signed bitfield extract. */
267 static void gen_sbfx(TCGv var
, int shift
, int width
)
272 tcg_gen_sari_i32(var
, var
, shift
);
273 if (shift
+ width
< 32) {
274 signbit
= 1u << (width
- 1);
275 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
276 tcg_gen_xori_i32(var
, var
, signbit
);
277 tcg_gen_subi_i32(var
, var
, signbit
);
281 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
282 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
284 tcg_gen_andi_i32(val
, val
, mask
);
285 tcg_gen_shli_i32(val
, val
, shift
);
286 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
287 tcg_gen_or_i32(dest
, base
, val
);
290 /* Return (b << 32) + a. Mark inputs as dead */
291 static TCGv_i64
gen_addq_msw(TCGv_i64 a
, TCGv b
)
293 TCGv_i64 tmp64
= tcg_temp_new_i64();
295 tcg_gen_extu_i32_i64(tmp64
, b
);
297 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
298 tcg_gen_add_i64(a
, tmp64
, a
);
300 tcg_temp_free_i64(tmp64
);
304 /* Return (b << 32) - a. Mark inputs as dead. */
305 static TCGv_i64
gen_subq_msw(TCGv_i64 a
, TCGv b
)
307 TCGv_i64 tmp64
= tcg_temp_new_i64();
309 tcg_gen_extu_i32_i64(tmp64
, b
);
311 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
312 tcg_gen_sub_i64(a
, tmp64
, a
);
314 tcg_temp_free_i64(tmp64
);
318 /* FIXME: Most targets have native widening multiplication.
319 It would be good to use that instead of a full wide multiply. */
320 /* 32x32->64 multiply. Marks inputs as dead. */
321 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
323 TCGv_i64 tmp1
= tcg_temp_new_i64();
324 TCGv_i64 tmp2
= tcg_temp_new_i64();
326 tcg_gen_extu_i32_i64(tmp1
, a
);
328 tcg_gen_extu_i32_i64(tmp2
, b
);
330 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
331 tcg_temp_free_i64(tmp2
);
335 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
337 TCGv_i64 tmp1
= tcg_temp_new_i64();
338 TCGv_i64 tmp2
= tcg_temp_new_i64();
340 tcg_gen_ext_i32_i64(tmp1
, a
);
342 tcg_gen_ext_i32_i64(tmp2
, b
);
344 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
345 tcg_temp_free_i64(tmp2
);
349 /* Swap low and high halfwords. */
350 static void gen_swap_half(TCGv var
)
352 TCGv tmp
= new_tmp();
353 tcg_gen_shri_i32(tmp
, var
, 16);
354 tcg_gen_shli_i32(var
, var
, 16);
355 tcg_gen_or_i32(var
, var
, tmp
);
359 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
360 tmp = (t0 ^ t1) & 0x8000;
363 t0 = (t0 + t1) ^ tmp;
366 static void gen_add16(TCGv t0
, TCGv t1
)
368 TCGv tmp
= new_tmp();
369 tcg_gen_xor_i32(tmp
, t0
, t1
);
370 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
371 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
372 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
373 tcg_gen_add_i32(t0
, t0
, t1
);
374 tcg_gen_xor_i32(t0
, t0
, tmp
);
379 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
381 /* Set CF to the top bit of var. */
382 static void gen_set_CF_bit31(TCGv var
)
384 TCGv tmp
= new_tmp();
385 tcg_gen_shri_i32(tmp
, var
, 31);
390 /* Set N and Z flags from var. */
391 static inline void gen_logic_CC(TCGv var
)
393 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
394 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
398 static void gen_adc(TCGv t0
, TCGv t1
)
401 tcg_gen_add_i32(t0
, t0
, t1
);
402 tmp
= load_cpu_field(CF
);
403 tcg_gen_add_i32(t0
, t0
, tmp
);
407 /* dest = T0 + T1 + CF. */
408 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
411 tcg_gen_add_i32(dest
, t0
, t1
);
412 tmp
= load_cpu_field(CF
);
413 tcg_gen_add_i32(dest
, dest
, tmp
);
417 /* dest = T0 - T1 + CF - 1. */
418 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
421 tcg_gen_sub_i32(dest
, t0
, t1
);
422 tmp
= load_cpu_field(CF
);
423 tcg_gen_add_i32(dest
, dest
, tmp
);
424 tcg_gen_subi_i32(dest
, dest
, 1);
428 /* FIXME: Implement this natively. */
429 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
431 static void shifter_out_im(TCGv var
, int shift
)
433 TCGv tmp
= new_tmp();
435 tcg_gen_andi_i32(tmp
, var
, 1);
437 tcg_gen_shri_i32(tmp
, var
, shift
);
439 tcg_gen_andi_i32(tmp
, tmp
, 1);
445 /* Shift by immediate. Includes special handling for shift == 0. */
446 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
452 shifter_out_im(var
, 32 - shift
);
453 tcg_gen_shli_i32(var
, var
, shift
);
459 tcg_gen_shri_i32(var
, var
, 31);
462 tcg_gen_movi_i32(var
, 0);
465 shifter_out_im(var
, shift
- 1);
466 tcg_gen_shri_i32(var
, var
, shift
);
473 shifter_out_im(var
, shift
- 1);
476 tcg_gen_sari_i32(var
, var
, shift
);
478 case 3: /* ROR/RRX */
481 shifter_out_im(var
, shift
- 1);
482 tcg_gen_rotri_i32(var
, var
, shift
); break;
484 TCGv tmp
= load_cpu_field(CF
);
486 shifter_out_im(var
, 0);
487 tcg_gen_shri_i32(var
, var
, 1);
488 tcg_gen_shli_i32(tmp
, tmp
, 31);
489 tcg_gen_or_i32(var
, var
, tmp
);
495 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
496 TCGv shift
, int flags
)
500 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
501 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
502 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
503 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
507 case 0: gen_helper_shl(var
, var
, shift
); break;
508 case 1: gen_helper_shr(var
, var
, shift
); break;
509 case 2: gen_helper_sar(var
, var
, shift
); break;
510 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
511 tcg_gen_rotr_i32(var
, var
, shift
); break;
517 #define PAS_OP(pfx) \
519 case 0: gen_pas_helper(glue(pfx,add16)); break; \
520 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
521 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
522 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
523 case 4: gen_pas_helper(glue(pfx,add8)); break; \
524 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
526 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
531 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
533 tmp
= tcg_temp_new_ptr();
534 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
536 tcg_temp_free_ptr(tmp
);
539 tmp
= tcg_temp_new_ptr();
540 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
542 tcg_temp_free_ptr(tmp
);
544 #undef gen_pas_helper
545 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
558 #undef gen_pas_helper
563 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
564 #define PAS_OP(pfx) \
566 case 0: gen_pas_helper(glue(pfx,add8)); break; \
567 case 1: gen_pas_helper(glue(pfx,add16)); break; \
568 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
569 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
570 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
571 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
573 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
578 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
580 tmp
= tcg_temp_new_ptr();
581 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
583 tcg_temp_free_ptr(tmp
);
586 tmp
= tcg_temp_new_ptr();
587 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
589 tcg_temp_free_ptr(tmp
);
591 #undef gen_pas_helper
592 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
605 #undef gen_pas_helper
610 static void gen_test_cc(int cc
, int label
)
618 tmp
= load_cpu_field(ZF
);
619 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
622 tmp
= load_cpu_field(ZF
);
623 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
626 tmp
= load_cpu_field(CF
);
627 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
630 tmp
= load_cpu_field(CF
);
631 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
634 tmp
= load_cpu_field(NF
);
635 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
638 tmp
= load_cpu_field(NF
);
639 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
642 tmp
= load_cpu_field(VF
);
643 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
646 tmp
= load_cpu_field(VF
);
647 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
649 case 8: /* hi: C && !Z */
650 inv
= gen_new_label();
651 tmp
= load_cpu_field(CF
);
652 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
654 tmp
= load_cpu_field(ZF
);
655 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
658 case 9: /* ls: !C || Z */
659 tmp
= load_cpu_field(CF
);
660 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
662 tmp
= load_cpu_field(ZF
);
663 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
665 case 10: /* ge: N == V -> N ^ V == 0 */
666 tmp
= load_cpu_field(VF
);
667 tmp2
= load_cpu_field(NF
);
668 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
670 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
672 case 11: /* lt: N != V -> N ^ V != 0 */
673 tmp
= load_cpu_field(VF
);
674 tmp2
= load_cpu_field(NF
);
675 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
677 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
679 case 12: /* gt: !Z && N == V */
680 inv
= gen_new_label();
681 tmp
= load_cpu_field(ZF
);
682 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
684 tmp
= load_cpu_field(VF
);
685 tmp2
= load_cpu_field(NF
);
686 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
688 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
691 case 13: /* le: Z || N != V */
692 tmp
= load_cpu_field(ZF
);
693 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
695 tmp
= load_cpu_field(VF
);
696 tmp2
= load_cpu_field(NF
);
697 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
699 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
702 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
708 static const uint8_t table_logic_cc
[16] = {
727 /* Set PC and Thumb state from an immediate address. */
728 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
732 s
->is_jmp
= DISAS_UPDATE
;
733 if (s
->thumb
!= (addr
& 1)) {
735 tcg_gen_movi_i32(tmp
, addr
& 1);
736 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
739 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
742 /* Set PC and Thumb state from var. var is marked as dead. */
743 static inline void gen_bx(DisasContext
*s
, TCGv var
)
745 s
->is_jmp
= DISAS_UPDATE
;
746 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
747 tcg_gen_andi_i32(var
, var
, 1);
748 store_cpu_field(var
, thumb
);
751 /* Variant of store_reg which uses branch&exchange logic when storing
752 to r15 in ARM architecture v7 and above. The source must be a temporary
753 and will be marked as dead. */
754 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
757 if (reg
== 15 && ENABLE_ARCH_7
) {
760 store_reg(s
, reg
, var
);
764 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
766 TCGv tmp
= new_tmp();
767 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
770 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
772 TCGv tmp
= new_tmp();
773 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
776 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
778 TCGv tmp
= new_tmp();
779 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
782 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
784 TCGv tmp
= new_tmp();
785 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
788 static inline TCGv
gen_ld32(TCGv addr
, int index
)
790 TCGv tmp
= new_tmp();
791 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
794 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
796 TCGv_i64 tmp
= tcg_temp_new_i64();
797 tcg_gen_qemu_ld64(tmp
, addr
, index
);
800 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
802 tcg_gen_qemu_st8(val
, addr
, index
);
805 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
807 tcg_gen_qemu_st16(val
, addr
, index
);
810 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
812 tcg_gen_qemu_st32(val
, addr
, index
);
815 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
817 tcg_gen_qemu_st64(val
, addr
, index
);
818 tcg_temp_free_i64(val
);
821 static inline void gen_set_pc_im(uint32_t val
)
823 tcg_gen_movi_i32(cpu_R
[15], val
);
826 /* Force a TB lookup after an instruction that changes the CPU state. */
827 static inline void gen_lookup_tb(DisasContext
*s
)
829 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
830 s
->is_jmp
= DISAS_UPDATE
;
833 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
836 int val
, rm
, shift
, shiftop
;
839 if (!(insn
& (1 << 25))) {
842 if (!(insn
& (1 << 23)))
845 tcg_gen_addi_i32(var
, var
, val
);
849 shift
= (insn
>> 7) & 0x1f;
850 shiftop
= (insn
>> 5) & 3;
851 offset
= load_reg(s
, rm
);
852 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
853 if (!(insn
& (1 << 23)))
854 tcg_gen_sub_i32(var
, var
, offset
);
856 tcg_gen_add_i32(var
, var
, offset
);
861 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
867 if (insn
& (1 << 22)) {
869 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
870 if (!(insn
& (1 << 23)))
874 tcg_gen_addi_i32(var
, var
, val
);
878 tcg_gen_addi_i32(var
, var
, extra
);
880 offset
= load_reg(s
, rm
);
881 if (!(insn
& (1 << 23)))
882 tcg_gen_sub_i32(var
, var
, offset
);
884 tcg_gen_add_i32(var
, var
, offset
);
889 #define VFP_OP2(name) \
890 static inline void gen_vfp_##name(int dp) \
893 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
895 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
905 static inline void gen_vfp_abs(int dp
)
908 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
910 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
913 static inline void gen_vfp_neg(int dp
)
916 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
918 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
921 static inline void gen_vfp_sqrt(int dp
)
924 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
926 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
929 static inline void gen_vfp_cmp(int dp
)
932 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
934 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
937 static inline void gen_vfp_cmpe(int dp
)
940 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
942 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
945 static inline void gen_vfp_F1_ld0(int dp
)
948 tcg_gen_movi_i64(cpu_F1d
, 0);
950 tcg_gen_movi_i32(cpu_F1s
, 0);
953 static inline void gen_vfp_uito(int dp
)
956 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
958 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
961 static inline void gen_vfp_sito(int dp
)
964 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
966 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
969 static inline void gen_vfp_toui(int dp
)
972 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
974 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
977 static inline void gen_vfp_touiz(int dp
)
980 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
982 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
985 static inline void gen_vfp_tosi(int dp
)
988 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
990 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
993 static inline void gen_vfp_tosiz(int dp
)
996 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
998 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1001 #define VFP_GEN_FIX(name) \
1002 static inline void gen_vfp_##name(int dp, int shift) \
1004 TCGv tmp_shift = tcg_const_i32(shift); \
1006 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1008 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1009 tcg_temp_free_i32(tmp_shift); \
1021 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1024 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1026 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1029 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1032 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1034 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1038 vfp_reg_offset (int dp
, int reg
)
1041 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1043 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1044 + offsetof(CPU_DoubleU
, l
.upper
);
1046 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1047 + offsetof(CPU_DoubleU
, l
.lower
);
1051 /* Return the offset of a 32-bit piece of a NEON register.
1052 zero is the least significant end of the register. */
1054 neon_reg_offset (int reg
, int n
)
1058 return vfp_reg_offset(0, sreg
);
1061 static TCGv
neon_load_reg(int reg
, int pass
)
1063 TCGv tmp
= new_tmp();
1064 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1068 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1070 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1074 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1076 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1079 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1081 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1084 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1085 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1086 #define tcg_gen_st_f32 tcg_gen_st_i32
1087 #define tcg_gen_st_f64 tcg_gen_st_i64
1089 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1092 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1094 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1097 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1100 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1102 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1105 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1108 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1110 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1113 #define ARM_CP_RW_BIT (1 << 20)
1115 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1117 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1120 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1122 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1125 static inline TCGv
iwmmxt_load_creg(int reg
)
1127 TCGv var
= new_tmp();
1128 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1132 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1134 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1138 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1140 iwmmxt_store_reg(cpu_M0
, rn
);
1143 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1145 iwmmxt_load_reg(cpu_M0
, rn
);
1148 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1150 iwmmxt_load_reg(cpu_V1
, rn
);
1151 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1154 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1156 iwmmxt_load_reg(cpu_V1
, rn
);
1157 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1160 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1162 iwmmxt_load_reg(cpu_V1
, rn
);
1163 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1166 #define IWMMXT_OP(name) \
1167 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1169 iwmmxt_load_reg(cpu_V1, rn); \
1170 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1173 #define IWMMXT_OP_ENV(name) \
1174 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1176 iwmmxt_load_reg(cpu_V1, rn); \
1177 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1180 #define IWMMXT_OP_ENV_SIZE(name) \
1181 IWMMXT_OP_ENV(name##b) \
1182 IWMMXT_OP_ENV(name##w) \
1183 IWMMXT_OP_ENV(name##l)
1185 #define IWMMXT_OP_ENV1(name) \
1186 static inline void gen_op_iwmmxt_##name##_M0(void) \
1188 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1202 IWMMXT_OP_ENV_SIZE(unpackl
)
1203 IWMMXT_OP_ENV_SIZE(unpackh
)
1205 IWMMXT_OP_ENV1(unpacklub
)
1206 IWMMXT_OP_ENV1(unpackluw
)
1207 IWMMXT_OP_ENV1(unpacklul
)
1208 IWMMXT_OP_ENV1(unpackhub
)
1209 IWMMXT_OP_ENV1(unpackhuw
)
1210 IWMMXT_OP_ENV1(unpackhul
)
1211 IWMMXT_OP_ENV1(unpacklsb
)
1212 IWMMXT_OP_ENV1(unpacklsw
)
1213 IWMMXT_OP_ENV1(unpacklsl
)
1214 IWMMXT_OP_ENV1(unpackhsb
)
1215 IWMMXT_OP_ENV1(unpackhsw
)
1216 IWMMXT_OP_ENV1(unpackhsl
)
1218 IWMMXT_OP_ENV_SIZE(cmpeq
)
1219 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1220 IWMMXT_OP_ENV_SIZE(cmpgts
)
1222 IWMMXT_OP_ENV_SIZE(mins
)
1223 IWMMXT_OP_ENV_SIZE(minu
)
1224 IWMMXT_OP_ENV_SIZE(maxs
)
1225 IWMMXT_OP_ENV_SIZE(maxu
)
1227 IWMMXT_OP_ENV_SIZE(subn
)
1228 IWMMXT_OP_ENV_SIZE(addn
)
1229 IWMMXT_OP_ENV_SIZE(subu
)
1230 IWMMXT_OP_ENV_SIZE(addu
)
1231 IWMMXT_OP_ENV_SIZE(subs
)
1232 IWMMXT_OP_ENV_SIZE(adds
)
1234 IWMMXT_OP_ENV(avgb0
)
1235 IWMMXT_OP_ENV(avgb1
)
1236 IWMMXT_OP_ENV(avgw0
)
1237 IWMMXT_OP_ENV(avgw1
)
1241 IWMMXT_OP_ENV(packuw
)
1242 IWMMXT_OP_ENV(packul
)
1243 IWMMXT_OP_ENV(packuq
)
1244 IWMMXT_OP_ENV(packsw
)
1245 IWMMXT_OP_ENV(packsl
)
1246 IWMMXT_OP_ENV(packsq
)
1248 static void gen_op_iwmmxt_set_mup(void)
1251 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1252 tcg_gen_ori_i32(tmp
, tmp
, 2);
1253 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1256 static void gen_op_iwmmxt_set_cup(void)
1259 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1260 tcg_gen_ori_i32(tmp
, tmp
, 1);
1261 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1264 static void gen_op_iwmmxt_setpsr_nz(void)
1266 TCGv tmp
= new_tmp();
1267 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1268 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1271 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1273 iwmmxt_load_reg(cpu_V1
, rn
);
1274 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1275 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1278 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1284 rd
= (insn
>> 16) & 0xf;
1285 tmp
= load_reg(s
, rd
);
1287 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1288 if (insn
& (1 << 24)) {
1290 if (insn
& (1 << 23))
1291 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1293 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1294 tcg_gen_mov_i32(dest
, tmp
);
1295 if (insn
& (1 << 21))
1296 store_reg(s
, rd
, tmp
);
1299 } else if (insn
& (1 << 21)) {
1301 tcg_gen_mov_i32(dest
, tmp
);
1302 if (insn
& (1 << 23))
1303 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1305 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1306 store_reg(s
, rd
, tmp
);
1307 } else if (!(insn
& (1 << 23)))
1312 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1314 int rd
= (insn
>> 0) & 0xf;
1317 if (insn
& (1 << 8)) {
1318 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1321 tmp
= iwmmxt_load_creg(rd
);
1325 iwmmxt_load_reg(cpu_V0
, rd
);
1326 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1328 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1329 tcg_gen_mov_i32(dest
, tmp
);
1334 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1335 (ie. an undefined instruction). */
1336 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1339 int rdhi
, rdlo
, rd0
, rd1
, i
;
1341 TCGv tmp
, tmp2
, tmp3
;
1343 if ((insn
& 0x0e000e00) == 0x0c000000) {
1344 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1346 rdlo
= (insn
>> 12) & 0xf;
1347 rdhi
= (insn
>> 16) & 0xf;
1348 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1349 iwmmxt_load_reg(cpu_V0
, wrd
);
1350 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1351 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1352 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1353 } else { /* TMCRR */
1354 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1355 iwmmxt_store_reg(cpu_V0
, wrd
);
1356 gen_op_iwmmxt_set_mup();
1361 wrd
= (insn
>> 12) & 0xf;
1363 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1367 if (insn
& ARM_CP_RW_BIT
) {
1368 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1370 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1371 iwmmxt_store_creg(wrd
, tmp
);
1374 if (insn
& (1 << 8)) {
1375 if (insn
& (1 << 22)) { /* WLDRD */
1376 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1378 } else { /* WLDRW wRd */
1379 tmp
= gen_ld32(addr
, IS_USER(s
));
1382 if (insn
& (1 << 22)) { /* WLDRH */
1383 tmp
= gen_ld16u(addr
, IS_USER(s
));
1384 } else { /* WLDRB */
1385 tmp
= gen_ld8u(addr
, IS_USER(s
));
1389 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1392 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1395 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1396 tmp
= iwmmxt_load_creg(wrd
);
1397 gen_st32(tmp
, addr
, IS_USER(s
));
1399 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1401 if (insn
& (1 << 8)) {
1402 if (insn
& (1 << 22)) { /* WSTRD */
1404 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1405 } else { /* WSTRW wRd */
1406 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1407 gen_st32(tmp
, addr
, IS_USER(s
));
1410 if (insn
& (1 << 22)) { /* WSTRH */
1411 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1412 gen_st16(tmp
, addr
, IS_USER(s
));
1413 } else { /* WSTRB */
1414 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1415 gen_st8(tmp
, addr
, IS_USER(s
));
1424 if ((insn
& 0x0f000000) != 0x0e000000)
1427 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1428 case 0x000: /* WOR */
1429 wrd
= (insn
>> 12) & 0xf;
1430 rd0
= (insn
>> 0) & 0xf;
1431 rd1
= (insn
>> 16) & 0xf;
1432 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1433 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1434 gen_op_iwmmxt_setpsr_nz();
1435 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1436 gen_op_iwmmxt_set_mup();
1437 gen_op_iwmmxt_set_cup();
1439 case 0x011: /* TMCR */
1442 rd
= (insn
>> 12) & 0xf;
1443 wrd
= (insn
>> 16) & 0xf;
1445 case ARM_IWMMXT_wCID
:
1446 case ARM_IWMMXT_wCASF
:
1448 case ARM_IWMMXT_wCon
:
1449 gen_op_iwmmxt_set_cup();
1451 case ARM_IWMMXT_wCSSF
:
1452 tmp
= iwmmxt_load_creg(wrd
);
1453 tmp2
= load_reg(s
, rd
);
1454 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1456 iwmmxt_store_creg(wrd
, tmp
);
1458 case ARM_IWMMXT_wCGR0
:
1459 case ARM_IWMMXT_wCGR1
:
1460 case ARM_IWMMXT_wCGR2
:
1461 case ARM_IWMMXT_wCGR3
:
1462 gen_op_iwmmxt_set_cup();
1463 tmp
= load_reg(s
, rd
);
1464 iwmmxt_store_creg(wrd
, tmp
);
1470 case 0x100: /* WXOR */
1471 wrd
= (insn
>> 12) & 0xf;
1472 rd0
= (insn
>> 0) & 0xf;
1473 rd1
= (insn
>> 16) & 0xf;
1474 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1475 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1476 gen_op_iwmmxt_setpsr_nz();
1477 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1478 gen_op_iwmmxt_set_mup();
1479 gen_op_iwmmxt_set_cup();
1481 case 0x111: /* TMRC */
1484 rd
= (insn
>> 12) & 0xf;
1485 wrd
= (insn
>> 16) & 0xf;
1486 tmp
= iwmmxt_load_creg(wrd
);
1487 store_reg(s
, rd
, tmp
);
1489 case 0x300: /* WANDN */
1490 wrd
= (insn
>> 12) & 0xf;
1491 rd0
= (insn
>> 0) & 0xf;
1492 rd1
= (insn
>> 16) & 0xf;
1493 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1494 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1495 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1496 gen_op_iwmmxt_setpsr_nz();
1497 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1498 gen_op_iwmmxt_set_mup();
1499 gen_op_iwmmxt_set_cup();
1501 case 0x200: /* WAND */
1502 wrd
= (insn
>> 12) & 0xf;
1503 rd0
= (insn
>> 0) & 0xf;
1504 rd1
= (insn
>> 16) & 0xf;
1505 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1506 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1507 gen_op_iwmmxt_setpsr_nz();
1508 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1509 gen_op_iwmmxt_set_mup();
1510 gen_op_iwmmxt_set_cup();
1512 case 0x810: case 0xa10: /* WMADD */
1513 wrd
= (insn
>> 12) & 0xf;
1514 rd0
= (insn
>> 0) & 0xf;
1515 rd1
= (insn
>> 16) & 0xf;
1516 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1517 if (insn
& (1 << 21))
1518 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1520 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1521 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1522 gen_op_iwmmxt_set_mup();
1524 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1525 wrd
= (insn
>> 12) & 0xf;
1526 rd0
= (insn
>> 16) & 0xf;
1527 rd1
= (insn
>> 0) & 0xf;
1528 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1529 switch ((insn
>> 22) & 3) {
1531 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1534 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1537 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1542 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1543 gen_op_iwmmxt_set_mup();
1544 gen_op_iwmmxt_set_cup();
1546 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1547 wrd
= (insn
>> 12) & 0xf;
1548 rd0
= (insn
>> 16) & 0xf;
1549 rd1
= (insn
>> 0) & 0xf;
1550 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1551 switch ((insn
>> 22) & 3) {
1553 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1556 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1559 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1564 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1565 gen_op_iwmmxt_set_mup();
1566 gen_op_iwmmxt_set_cup();
1568 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1569 wrd
= (insn
>> 12) & 0xf;
1570 rd0
= (insn
>> 16) & 0xf;
1571 rd1
= (insn
>> 0) & 0xf;
1572 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1573 if (insn
& (1 << 22))
1574 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1576 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1577 if (!(insn
& (1 << 20)))
1578 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1579 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1580 gen_op_iwmmxt_set_mup();
1582 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1583 wrd
= (insn
>> 12) & 0xf;
1584 rd0
= (insn
>> 16) & 0xf;
1585 rd1
= (insn
>> 0) & 0xf;
1586 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1587 if (insn
& (1 << 21)) {
1588 if (insn
& (1 << 20))
1589 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1591 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1593 if (insn
& (1 << 20))
1594 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1596 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1598 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1599 gen_op_iwmmxt_set_mup();
1601 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1602 wrd
= (insn
>> 12) & 0xf;
1603 rd0
= (insn
>> 16) & 0xf;
1604 rd1
= (insn
>> 0) & 0xf;
1605 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1606 if (insn
& (1 << 21))
1607 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1609 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1610 if (!(insn
& (1 << 20))) {
1611 iwmmxt_load_reg(cpu_V1
, wrd
);
1612 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1614 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1615 gen_op_iwmmxt_set_mup();
1617 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1618 wrd
= (insn
>> 12) & 0xf;
1619 rd0
= (insn
>> 16) & 0xf;
1620 rd1
= (insn
>> 0) & 0xf;
1621 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1622 switch ((insn
>> 22) & 3) {
1624 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1627 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1630 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1635 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1636 gen_op_iwmmxt_set_mup();
1637 gen_op_iwmmxt_set_cup();
1639 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1640 wrd
= (insn
>> 12) & 0xf;
1641 rd0
= (insn
>> 16) & 0xf;
1642 rd1
= (insn
>> 0) & 0xf;
1643 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1644 if (insn
& (1 << 22)) {
1645 if (insn
& (1 << 20))
1646 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1648 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1650 if (insn
& (1 << 20))
1651 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1653 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1655 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1656 gen_op_iwmmxt_set_mup();
1657 gen_op_iwmmxt_set_cup();
1659 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1660 wrd
= (insn
>> 12) & 0xf;
1661 rd0
= (insn
>> 16) & 0xf;
1662 rd1
= (insn
>> 0) & 0xf;
1663 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1664 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1665 tcg_gen_andi_i32(tmp
, tmp
, 7);
1666 iwmmxt_load_reg(cpu_V1
, rd1
);
1667 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1669 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1670 gen_op_iwmmxt_set_mup();
1672 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1673 if (((insn
>> 6) & 3) == 3)
1675 rd
= (insn
>> 12) & 0xf;
1676 wrd
= (insn
>> 16) & 0xf;
1677 tmp
= load_reg(s
, rd
);
1678 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1679 switch ((insn
>> 6) & 3) {
1681 tmp2
= tcg_const_i32(0xff);
1682 tmp3
= tcg_const_i32((insn
& 7) << 3);
1685 tmp2
= tcg_const_i32(0xffff);
1686 tmp3
= tcg_const_i32((insn
& 3) << 4);
1689 tmp2
= tcg_const_i32(0xffffffff);
1690 tmp3
= tcg_const_i32((insn
& 1) << 5);
1696 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1697 tcg_temp_free(tmp3
);
1698 tcg_temp_free(tmp2
);
1700 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1701 gen_op_iwmmxt_set_mup();
1703 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1704 rd
= (insn
>> 12) & 0xf;
1705 wrd
= (insn
>> 16) & 0xf;
1706 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1708 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1710 switch ((insn
>> 22) & 3) {
1712 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1713 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1715 tcg_gen_ext8s_i32(tmp
, tmp
);
1717 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1721 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1722 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1724 tcg_gen_ext16s_i32(tmp
, tmp
);
1726 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1730 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1731 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1734 store_reg(s
, rd
, tmp
);
1736 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1737 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1739 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1740 switch ((insn
>> 22) & 3) {
1742 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1745 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1748 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1751 tcg_gen_shli_i32(tmp
, tmp
, 28);
1755 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1756 if (((insn
>> 6) & 3) == 3)
1758 rd
= (insn
>> 12) & 0xf;
1759 wrd
= (insn
>> 16) & 0xf;
1760 tmp
= load_reg(s
, rd
);
1761 switch ((insn
>> 6) & 3) {
1763 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1766 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1769 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1773 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1774 gen_op_iwmmxt_set_mup();
1776 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1777 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1779 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1781 tcg_gen_mov_i32(tmp2
, tmp
);
1782 switch ((insn
>> 22) & 3) {
1784 for (i
= 0; i
< 7; i
++) {
1785 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1786 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1790 for (i
= 0; i
< 3; i
++) {
1791 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1792 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1796 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1797 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1804 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1805 wrd
= (insn
>> 12) & 0xf;
1806 rd0
= (insn
>> 16) & 0xf;
1807 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1808 switch ((insn
>> 22) & 3) {
1810 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1813 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1816 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1821 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1822 gen_op_iwmmxt_set_mup();
1824 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1825 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1827 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1829 tcg_gen_mov_i32(tmp2
, tmp
);
1830 switch ((insn
>> 22) & 3) {
1832 for (i
= 0; i
< 7; i
++) {
1833 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1834 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1838 for (i
= 0; i
< 3; i
++) {
1839 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1840 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1844 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1845 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1852 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1853 rd
= (insn
>> 12) & 0xf;
1854 rd0
= (insn
>> 16) & 0xf;
1855 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1857 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1859 switch ((insn
>> 22) & 3) {
1861 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1864 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1867 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1870 store_reg(s
, rd
, tmp
);
1872 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1873 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1874 wrd
= (insn
>> 12) & 0xf;
1875 rd0
= (insn
>> 16) & 0xf;
1876 rd1
= (insn
>> 0) & 0xf;
1877 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1878 switch ((insn
>> 22) & 3) {
1880 if (insn
& (1 << 21))
1881 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1883 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1886 if (insn
& (1 << 21))
1887 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1889 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1892 if (insn
& (1 << 21))
1893 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1895 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1900 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1901 gen_op_iwmmxt_set_mup();
1902 gen_op_iwmmxt_set_cup();
1904 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1905 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1906 wrd
= (insn
>> 12) & 0xf;
1907 rd0
= (insn
>> 16) & 0xf;
1908 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1909 switch ((insn
>> 22) & 3) {
1911 if (insn
& (1 << 21))
1912 gen_op_iwmmxt_unpacklsb_M0();
1914 gen_op_iwmmxt_unpacklub_M0();
1917 if (insn
& (1 << 21))
1918 gen_op_iwmmxt_unpacklsw_M0();
1920 gen_op_iwmmxt_unpackluw_M0();
1923 if (insn
& (1 << 21))
1924 gen_op_iwmmxt_unpacklsl_M0();
1926 gen_op_iwmmxt_unpacklul_M0();
1931 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1932 gen_op_iwmmxt_set_mup();
1933 gen_op_iwmmxt_set_cup();
1935 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1936 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1937 wrd
= (insn
>> 12) & 0xf;
1938 rd0
= (insn
>> 16) & 0xf;
1939 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1940 switch ((insn
>> 22) & 3) {
1942 if (insn
& (1 << 21))
1943 gen_op_iwmmxt_unpackhsb_M0();
1945 gen_op_iwmmxt_unpackhub_M0();
1948 if (insn
& (1 << 21))
1949 gen_op_iwmmxt_unpackhsw_M0();
1951 gen_op_iwmmxt_unpackhuw_M0();
1954 if (insn
& (1 << 21))
1955 gen_op_iwmmxt_unpackhsl_M0();
1957 gen_op_iwmmxt_unpackhul_M0();
1962 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1963 gen_op_iwmmxt_set_mup();
1964 gen_op_iwmmxt_set_cup();
1966 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1967 case 0x214: case 0x614: case 0xa14: case 0xe14:
1968 if (((insn
>> 22) & 3) == 0)
1970 wrd
= (insn
>> 12) & 0xf;
1971 rd0
= (insn
>> 16) & 0xf;
1972 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1974 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1978 switch ((insn
>> 22) & 3) {
1980 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1983 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1986 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1990 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1991 gen_op_iwmmxt_set_mup();
1992 gen_op_iwmmxt_set_cup();
1994 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1995 case 0x014: case 0x414: case 0x814: case 0xc14:
1996 if (((insn
>> 22) & 3) == 0)
1998 wrd
= (insn
>> 12) & 0xf;
1999 rd0
= (insn
>> 16) & 0xf;
2000 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2002 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2006 switch ((insn
>> 22) & 3) {
2008 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2011 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2014 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2018 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2019 gen_op_iwmmxt_set_mup();
2020 gen_op_iwmmxt_set_cup();
2022 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2023 case 0x114: case 0x514: case 0x914: case 0xd14:
2024 if (((insn
>> 22) & 3) == 0)
2026 wrd
= (insn
>> 12) & 0xf;
2027 rd0
= (insn
>> 16) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2030 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2034 switch ((insn
>> 22) & 3) {
2036 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2039 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2042 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2046 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2047 gen_op_iwmmxt_set_mup();
2048 gen_op_iwmmxt_set_cup();
2050 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2051 case 0x314: case 0x714: case 0xb14: case 0xf14:
2052 if (((insn
>> 22) & 3) == 0)
2054 wrd
= (insn
>> 12) & 0xf;
2055 rd0
= (insn
>> 16) & 0xf;
2056 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2058 switch ((insn
>> 22) & 3) {
2060 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2064 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2067 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2071 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2074 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2078 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2082 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2086 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2087 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2088 wrd
= (insn
>> 12) & 0xf;
2089 rd0
= (insn
>> 16) & 0xf;
2090 rd1
= (insn
>> 0) & 0xf;
2091 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2092 switch ((insn
>> 22) & 3) {
2094 if (insn
& (1 << 21))
2095 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2097 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2100 if (insn
& (1 << 21))
2101 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2103 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2106 if (insn
& (1 << 21))
2107 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2109 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2114 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2115 gen_op_iwmmxt_set_mup();
2117 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2118 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2119 wrd
= (insn
>> 12) & 0xf;
2120 rd0
= (insn
>> 16) & 0xf;
2121 rd1
= (insn
>> 0) & 0xf;
2122 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2123 switch ((insn
>> 22) & 3) {
2125 if (insn
& (1 << 21))
2126 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2128 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2131 if (insn
& (1 << 21))
2132 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2134 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2137 if (insn
& (1 << 21))
2138 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2140 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2145 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2146 gen_op_iwmmxt_set_mup();
2148 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2149 case 0x402: case 0x502: case 0x602: case 0x702:
2150 wrd
= (insn
>> 12) & 0xf;
2151 rd0
= (insn
>> 16) & 0xf;
2152 rd1
= (insn
>> 0) & 0xf;
2153 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2154 tmp
= tcg_const_i32((insn
>> 20) & 3);
2155 iwmmxt_load_reg(cpu_V1
, rd1
);
2156 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2158 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2159 gen_op_iwmmxt_set_mup();
2161 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2162 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2163 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2164 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2165 wrd
= (insn
>> 12) & 0xf;
2166 rd0
= (insn
>> 16) & 0xf;
2167 rd1
= (insn
>> 0) & 0xf;
2168 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2169 switch ((insn
>> 20) & 0xf) {
2171 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2174 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2177 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2180 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2183 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2186 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2189 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2192 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2195 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2200 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2201 gen_op_iwmmxt_set_mup();
2202 gen_op_iwmmxt_set_cup();
2204 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2205 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2206 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2207 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2208 wrd
= (insn
>> 12) & 0xf;
2209 rd0
= (insn
>> 16) & 0xf;
2210 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2211 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2212 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2214 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2215 gen_op_iwmmxt_set_mup();
2216 gen_op_iwmmxt_set_cup();
2218 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2219 case 0x418: case 0x518: case 0x618: case 0x718:
2220 case 0x818: case 0x918: case 0xa18: case 0xb18:
2221 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2222 wrd
= (insn
>> 12) & 0xf;
2223 rd0
= (insn
>> 16) & 0xf;
2224 rd1
= (insn
>> 0) & 0xf;
2225 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2226 switch ((insn
>> 20) & 0xf) {
2228 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2231 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2234 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2237 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2240 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2243 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2246 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2249 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2252 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2257 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2258 gen_op_iwmmxt_set_mup();
2259 gen_op_iwmmxt_set_cup();
2261 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2262 case 0x408: case 0x508: case 0x608: case 0x708:
2263 case 0x808: case 0x908: case 0xa08: case 0xb08:
2264 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2265 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2267 wrd
= (insn
>> 12) & 0xf;
2268 rd0
= (insn
>> 16) & 0xf;
2269 rd1
= (insn
>> 0) & 0xf;
2270 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2271 switch ((insn
>> 22) & 3) {
2273 if (insn
& (1 << 21))
2274 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2276 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2279 if (insn
& (1 << 21))
2280 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2282 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2285 if (insn
& (1 << 21))
2286 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2288 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2291 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2292 gen_op_iwmmxt_set_mup();
2293 gen_op_iwmmxt_set_cup();
2295 case 0x201: case 0x203: case 0x205: case 0x207:
2296 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2297 case 0x211: case 0x213: case 0x215: case 0x217:
2298 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2299 wrd
= (insn
>> 5) & 0xf;
2300 rd0
= (insn
>> 12) & 0xf;
2301 rd1
= (insn
>> 0) & 0xf;
2302 if (rd0
== 0xf || rd1
== 0xf)
2304 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2305 tmp
= load_reg(s
, rd0
);
2306 tmp2
= load_reg(s
, rd1
);
2307 switch ((insn
>> 16) & 0xf) {
2308 case 0x0: /* TMIA */
2309 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2311 case 0x8: /* TMIAPH */
2312 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2314 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2315 if (insn
& (1 << 16))
2316 tcg_gen_shri_i32(tmp
, tmp
, 16);
2317 if (insn
& (1 << 17))
2318 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2319 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2328 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2329 gen_op_iwmmxt_set_mup();
2338 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2339 (ie. an undefined instruction). */
2340 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2342 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2345 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2346 /* Multiply with Internal Accumulate Format */
2347 rd0
= (insn
>> 12) & 0xf;
2349 acc
= (insn
>> 5) & 7;
2354 tmp
= load_reg(s
, rd0
);
2355 tmp2
= load_reg(s
, rd1
);
2356 switch ((insn
>> 16) & 0xf) {
2358 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2360 case 0x8: /* MIAPH */
2361 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2363 case 0xc: /* MIABB */
2364 case 0xd: /* MIABT */
2365 case 0xe: /* MIATB */
2366 case 0xf: /* MIATT */
2367 if (insn
& (1 << 16))
2368 tcg_gen_shri_i32(tmp
, tmp
, 16);
2369 if (insn
& (1 << 17))
2370 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2371 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2379 gen_op_iwmmxt_movq_wRn_M0(acc
);
2383 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2384 /* Internal Accumulator Access Format */
2385 rdhi
= (insn
>> 16) & 0xf;
2386 rdlo
= (insn
>> 12) & 0xf;
2392 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2393 iwmmxt_load_reg(cpu_V0
, acc
);
2394 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2395 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2396 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2397 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2399 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2400 iwmmxt_store_reg(cpu_V0
, acc
);
2408 /* Disassemble system coprocessor instruction. Return nonzero if
2409 instruction is not defined. */
2410 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2413 uint32_t rd
= (insn
>> 12) & 0xf;
2414 uint32_t cp
= (insn
>> 8) & 0xf;
2419 if (insn
& ARM_CP_RW_BIT
) {
2420 if (!env
->cp
[cp
].cp_read
)
2422 gen_set_pc_im(s
->pc
);
2424 tmp2
= tcg_const_i32(insn
);
2425 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2426 tcg_temp_free(tmp2
);
2427 store_reg(s
, rd
, tmp
);
2429 if (!env
->cp
[cp
].cp_write
)
2431 gen_set_pc_im(s
->pc
);
2432 tmp
= load_reg(s
, rd
);
2433 tmp2
= tcg_const_i32(insn
);
2434 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2435 tcg_temp_free(tmp2
);
2441 static int cp15_user_ok(uint32_t insn
)
2443 int cpn
= (insn
>> 16) & 0xf;
2444 int cpm
= insn
& 0xf;
2445 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2447 if (cpn
== 13 && cpm
== 0) {
2449 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2453 /* ISB, DSB, DMB. */
2454 if ((cpm
== 5 && op
== 4)
2455 || (cpm
== 10 && (op
== 4 || op
== 5)))
2461 static int cp15_tls_load_store(CPUState
*env
, DisasContext
*s
, uint32_t insn
, uint32_t rd
)
2464 int cpn
= (insn
>> 16) & 0xf;
2465 int cpm
= insn
& 0xf;
2466 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2468 if (!arm_feature(env
, ARM_FEATURE_V6K
))
2471 if (!(cpn
== 13 && cpm
== 0))
2474 if (insn
& ARM_CP_RW_BIT
) {
2477 tmp
= load_cpu_field(cp15
.c13_tls1
);
2480 tmp
= load_cpu_field(cp15
.c13_tls2
);
2483 tmp
= load_cpu_field(cp15
.c13_tls3
);
2488 store_reg(s
, rd
, tmp
);
2491 tmp
= load_reg(s
, rd
);
2494 store_cpu_field(tmp
, cp15
.c13_tls1
);
2497 store_cpu_field(tmp
, cp15
.c13_tls2
);
2500 store_cpu_field(tmp
, cp15
.c13_tls3
);
2510 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2511 instruction is not defined. */
2512 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2517 /* M profile cores use memory mapped registers instead of cp15. */
2518 if (arm_feature(env
, ARM_FEATURE_M
))
2521 if ((insn
& (1 << 25)) == 0) {
2522 if (insn
& (1 << 20)) {
2526 /* mcrr. Used for block cache operations, so implement as no-op. */
2529 if ((insn
& (1 << 4)) == 0) {
2533 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2536 if ((insn
& 0x0fff0fff) == 0x0e070f90
2537 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2538 /* Wait for interrupt. */
2539 gen_set_pc_im(s
->pc
);
2540 s
->is_jmp
= DISAS_WFI
;
2543 rd
= (insn
>> 12) & 0xf;
2545 if (cp15_tls_load_store(env
, s
, insn
, rd
))
2548 tmp2
= tcg_const_i32(insn
);
2549 if (insn
& ARM_CP_RW_BIT
) {
2551 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2552 /* If the destination register is r15 then sets condition codes. */
2554 store_reg(s
, rd
, tmp
);
2558 tmp
= load_reg(s
, rd
);
2559 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2561 /* Normally we would always end the TB here, but Linux
2562 * arch/arm/mach-pxa/sleep.S expects two instructions following
2563 * an MMU enable to execute from cache. Imitate this behaviour. */
2564 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2565 (insn
& 0x0fff0fff) != 0x0e010f10)
2568 tcg_temp_free_i32(tmp2
);
2572 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2573 #define VFP_SREG(insn, bigbit, smallbit) \
2574 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2575 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2576 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2577 reg = (((insn) >> (bigbit)) & 0x0f) \
2578 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2580 if (insn & (1 << (smallbit))) \
2582 reg = ((insn) >> (bigbit)) & 0x0f; \
2585 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2586 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2587 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2588 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2589 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2590 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2592 /* Move between integer and VFP cores. */
2593 static TCGv
gen_vfp_mrs(void)
2595 TCGv tmp
= new_tmp();
2596 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2600 static void gen_vfp_msr(TCGv tmp
)
2602 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2607 vfp_enabled(CPUState
* env
)
2609 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2612 static void gen_neon_dup_u8(TCGv var
, int shift
)
2614 TCGv tmp
= new_tmp();
2616 tcg_gen_shri_i32(var
, var
, shift
);
2617 tcg_gen_ext8u_i32(var
, var
);
2618 tcg_gen_shli_i32(tmp
, var
, 8);
2619 tcg_gen_or_i32(var
, var
, tmp
);
2620 tcg_gen_shli_i32(tmp
, var
, 16);
2621 tcg_gen_or_i32(var
, var
, tmp
);
2625 static void gen_neon_dup_low16(TCGv var
)
2627 TCGv tmp
= new_tmp();
2628 tcg_gen_ext16u_i32(var
, var
);
2629 tcg_gen_shli_i32(tmp
, var
, 16);
2630 tcg_gen_or_i32(var
, var
, tmp
);
2634 static void gen_neon_dup_high16(TCGv var
)
2636 TCGv tmp
= new_tmp();
2637 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2638 tcg_gen_shri_i32(tmp
, var
, 16);
2639 tcg_gen_or_i32(var
, var
, tmp
);
2643 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2644 (ie. an undefined instruction). */
2645 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2647 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2653 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2656 if (!vfp_enabled(env
)) {
2657 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2658 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2660 rn
= (insn
>> 16) & 0xf;
2661 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2662 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2665 dp
= ((insn
& 0xf00) == 0xb00);
2666 switch ((insn
>> 24) & 0xf) {
2668 if (insn
& (1 << 4)) {
2669 /* single register transfer */
2670 rd
= (insn
>> 12) & 0xf;
2675 VFP_DREG_N(rn
, insn
);
2678 if (insn
& 0x00c00060
2679 && !arm_feature(env
, ARM_FEATURE_NEON
))
2682 pass
= (insn
>> 21) & 1;
2683 if (insn
& (1 << 22)) {
2685 offset
= ((insn
>> 5) & 3) * 8;
2686 } else if (insn
& (1 << 5)) {
2688 offset
= (insn
& (1 << 6)) ? 16 : 0;
2693 if (insn
& ARM_CP_RW_BIT
) {
2695 tmp
= neon_load_reg(rn
, pass
);
2699 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2700 if (insn
& (1 << 23))
2706 if (insn
& (1 << 23)) {
2708 tcg_gen_shri_i32(tmp
, tmp
, 16);
2714 tcg_gen_sari_i32(tmp
, tmp
, 16);
2723 store_reg(s
, rd
, tmp
);
2726 tmp
= load_reg(s
, rd
);
2727 if (insn
& (1 << 23)) {
2730 gen_neon_dup_u8(tmp
, 0);
2731 } else if (size
== 1) {
2732 gen_neon_dup_low16(tmp
);
2734 for (n
= 0; n
<= pass
* 2; n
++) {
2736 tcg_gen_mov_i32(tmp2
, tmp
);
2737 neon_store_reg(rn
, n
, tmp2
);
2739 neon_store_reg(rn
, n
, tmp
);
2744 tmp2
= neon_load_reg(rn
, pass
);
2745 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2749 tmp2
= neon_load_reg(rn
, pass
);
2750 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2756 neon_store_reg(rn
, pass
, tmp
);
2760 if ((insn
& 0x6f) != 0x00)
2762 rn
= VFP_SREG_N(insn
);
2763 if (insn
& ARM_CP_RW_BIT
) {
2765 if (insn
& (1 << 21)) {
2766 /* system register */
2771 /* VFP2 allows access to FSID from userspace.
2772 VFP3 restricts all id registers to privileged
2775 && arm_feature(env
, ARM_FEATURE_VFP3
))
2777 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2782 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2784 case ARM_VFP_FPINST
:
2785 case ARM_VFP_FPINST2
:
2786 /* Not present in VFP3. */
2788 || arm_feature(env
, ARM_FEATURE_VFP3
))
2790 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2794 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2795 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2798 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2804 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2806 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2812 gen_mov_F0_vreg(0, rn
);
2813 tmp
= gen_vfp_mrs();
2816 /* Set the 4 flag bits in the CPSR. */
2820 store_reg(s
, rd
, tmp
);
2824 tmp
= load_reg(s
, rd
);
2825 if (insn
& (1 << 21)) {
2827 /* system register */
2832 /* Writes are ignored. */
2835 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2842 /* TODO: VFP subarchitecture support.
2843 * For now, keep the EN bit only */
2844 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2845 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2848 case ARM_VFP_FPINST
:
2849 case ARM_VFP_FPINST2
:
2850 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2857 gen_mov_vreg_F0(0, rn
);
2862 /* data processing */
2863 /* The opcode is in bits 23, 21, 20 and 6. */
2864 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2868 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2870 /* rn is register number */
2871 VFP_DREG_N(rn
, insn
);
2874 if (op
== 15 && (rn
== 15 || ((rn
& 0x1c) == 0x18))) {
2875 /* Integer or single precision destination. */
2876 rd
= VFP_SREG_D(insn
);
2878 VFP_DREG_D(rd
, insn
);
2881 (((rn
& 0x1c) == 0x10) || ((rn
& 0x14) == 0x14))) {
2882 /* VCVT from int is always from S reg regardless of dp bit.
2883 * VCVT with immediate frac_bits has same format as SREG_M
2885 rm
= VFP_SREG_M(insn
);
2887 VFP_DREG_M(rm
, insn
);
2890 rn
= VFP_SREG_N(insn
);
2891 if (op
== 15 && rn
== 15) {
2892 /* Double precision destination. */
2893 VFP_DREG_D(rd
, insn
);
2895 rd
= VFP_SREG_D(insn
);
2897 /* NB that we implicitly rely on the encoding for the frac_bits
2898 * in VCVT of fixed to float being the same as that of an SREG_M
2900 rm
= VFP_SREG_M(insn
);
2903 veclen
= env
->vfp
.vec_len
;
2904 if (op
== 15 && rn
> 3)
2907 /* Shut up compiler warnings. */
2918 /* Figure out what type of vector operation this is. */
2919 if ((rd
& bank_mask
) == 0) {
2924 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2926 delta_d
= env
->vfp
.vec_stride
+ 1;
2928 if ((rm
& bank_mask
) == 0) {
2929 /* mixed scalar/vector */
2938 /* Load the initial operands. */
2943 /* Integer source */
2944 gen_mov_F0_vreg(0, rm
);
2949 gen_mov_F0_vreg(dp
, rd
);
2950 gen_mov_F1_vreg(dp
, rm
);
2954 /* Compare with zero */
2955 gen_mov_F0_vreg(dp
, rd
);
2966 /* Source and destination the same. */
2967 gen_mov_F0_vreg(dp
, rd
);
2970 /* One source operand. */
2971 gen_mov_F0_vreg(dp
, rm
);
2975 /* Two source operands. */
2976 gen_mov_F0_vreg(dp
, rn
);
2977 gen_mov_F1_vreg(dp
, rm
);
2981 /* Perform the calculation. */
2983 case 0: /* mac: fd + (fn * fm) */
2985 gen_mov_F1_vreg(dp
, rd
);
2988 case 1: /* nmac: fd - (fn * fm) */
2991 gen_mov_F1_vreg(dp
, rd
);
2994 case 2: /* msc: -fd + (fn * fm) */
2996 gen_mov_F1_vreg(dp
, rd
);
2999 case 3: /* nmsc: -fd - (fn * fm) */
3002 gen_mov_F1_vreg(dp
, rd
);
3005 case 4: /* mul: fn * fm */
3008 case 5: /* nmul: -(fn * fm) */
3012 case 6: /* add: fn + fm */
3015 case 7: /* sub: fn - fm */
3018 case 8: /* div: fn / fm */
3021 case 14: /* fconst */
3022 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3025 n
= (insn
<< 12) & 0x80000000;
3026 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3033 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3040 tcg_gen_movi_i32(cpu_F0s
, n
);
3043 case 15: /* extension space */
3057 case 4: /* vcvtb.f32.f16 */
3058 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3060 tmp
= gen_vfp_mrs();
3061 tcg_gen_ext16u_i32(tmp
, tmp
);
3062 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3065 case 5: /* vcvtt.f32.f16 */
3066 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3068 tmp
= gen_vfp_mrs();
3069 tcg_gen_shri_i32(tmp
, tmp
, 16);
3070 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3073 case 6: /* vcvtb.f16.f32 */
3074 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3077 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3078 gen_mov_F0_vreg(0, rd
);
3079 tmp2
= gen_vfp_mrs();
3080 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3081 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3085 case 7: /* vcvtt.f16.f32 */
3086 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3089 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3090 tcg_gen_shli_i32(tmp
, tmp
, 16);
3091 gen_mov_F0_vreg(0, rd
);
3092 tmp2
= gen_vfp_mrs();
3093 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3094 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3107 case 11: /* cmpez */
3111 case 15: /* single<->double conversion */
3113 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3115 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3117 case 16: /* fuito */
3120 case 17: /* fsito */
3123 case 20: /* fshto */
3124 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3126 gen_vfp_shto(dp
, 16 - rm
);
3128 case 21: /* fslto */
3129 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3131 gen_vfp_slto(dp
, 32 - rm
);
3133 case 22: /* fuhto */
3134 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3136 gen_vfp_uhto(dp
, 16 - rm
);
3138 case 23: /* fulto */
3139 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3141 gen_vfp_ulto(dp
, 32 - rm
);
3143 case 24: /* ftoui */
3146 case 25: /* ftouiz */
3149 case 26: /* ftosi */
3152 case 27: /* ftosiz */
3155 case 28: /* ftosh */
3156 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3158 gen_vfp_tosh(dp
, 16 - rm
);
3160 case 29: /* ftosl */
3161 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3163 gen_vfp_tosl(dp
, 32 - rm
);
3165 case 30: /* ftouh */
3166 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3168 gen_vfp_touh(dp
, 16 - rm
);
3170 case 31: /* ftoul */
3171 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3173 gen_vfp_toul(dp
, 32 - rm
);
3175 default: /* undefined */
3176 printf ("rn:%d\n", rn
);
3180 default: /* undefined */
3181 printf ("op:%d\n", op
);
3185 /* Write back the result. */
3186 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3187 ; /* Comparison, do nothing. */
3188 else if (op
== 15 && dp
&& ((rn
& 0x1c) == 0x18))
3189 /* VCVT double to int: always integer result. */
3190 gen_mov_vreg_F0(0, rd
);
3191 else if (op
== 15 && rn
== 15)
3193 gen_mov_vreg_F0(!dp
, rd
);
3195 gen_mov_vreg_F0(dp
, rd
);
3197 /* break out of the loop if we have finished */
3201 if (op
== 15 && delta_m
== 0) {
3202 /* single source one-many */
3204 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3206 gen_mov_vreg_F0(dp
, rd
);
3210 /* Setup the next operands. */
3212 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3216 /* One source operand. */
3217 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3219 gen_mov_F0_vreg(dp
, rm
);
3221 /* Two source operands. */
3222 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3224 gen_mov_F0_vreg(dp
, rn
);
3226 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3228 gen_mov_F1_vreg(dp
, rm
);
3236 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3237 /* two-register transfer */
3238 rn
= (insn
>> 16) & 0xf;
3239 rd
= (insn
>> 12) & 0xf;
3241 VFP_DREG_M(rm
, insn
);
3243 rm
= VFP_SREG_M(insn
);
3246 if (insn
& ARM_CP_RW_BIT
) {
3249 gen_mov_F0_vreg(0, rm
* 2);
3250 tmp
= gen_vfp_mrs();
3251 store_reg(s
, rd
, tmp
);
3252 gen_mov_F0_vreg(0, rm
* 2 + 1);
3253 tmp
= gen_vfp_mrs();
3254 store_reg(s
, rn
, tmp
);
3256 gen_mov_F0_vreg(0, rm
);
3257 tmp
= gen_vfp_mrs();
3258 store_reg(s
, rn
, tmp
);
3259 gen_mov_F0_vreg(0, rm
+ 1);
3260 tmp
= gen_vfp_mrs();
3261 store_reg(s
, rd
, tmp
);
3266 tmp
= load_reg(s
, rd
);
3268 gen_mov_vreg_F0(0, rm
* 2);
3269 tmp
= load_reg(s
, rn
);
3271 gen_mov_vreg_F0(0, rm
* 2 + 1);
3273 tmp
= load_reg(s
, rn
);
3275 gen_mov_vreg_F0(0, rm
);
3276 tmp
= load_reg(s
, rd
);
3278 gen_mov_vreg_F0(0, rm
+ 1);
3283 rn
= (insn
>> 16) & 0xf;
3285 VFP_DREG_D(rd
, insn
);
3287 rd
= VFP_SREG_D(insn
);
3288 if (s
->thumb
&& rn
== 15) {
3290 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3292 addr
= load_reg(s
, rn
);
3294 if ((insn
& 0x01200000) == 0x01000000) {
3295 /* Single load/store */
3296 offset
= (insn
& 0xff) << 2;
3297 if ((insn
& (1 << 23)) == 0)
3299 tcg_gen_addi_i32(addr
, addr
, offset
);
3300 if (insn
& (1 << 20)) {
3301 gen_vfp_ld(s
, dp
, addr
);
3302 gen_mov_vreg_F0(dp
, rd
);
3304 gen_mov_F0_vreg(dp
, rd
);
3305 gen_vfp_st(s
, dp
, addr
);
3309 /* load/store multiple */
3311 n
= (insn
>> 1) & 0x7f;
3315 if (insn
& (1 << 24)) /* pre-decrement */
3316 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3322 for (i
= 0; i
< n
; i
++) {
3323 if (insn
& ARM_CP_RW_BIT
) {
3325 gen_vfp_ld(s
, dp
, addr
);
3326 gen_mov_vreg_F0(dp
, rd
+ i
);
3329 gen_mov_F0_vreg(dp
, rd
+ i
);
3330 gen_vfp_st(s
, dp
, addr
);
3332 tcg_gen_addi_i32(addr
, addr
, offset
);
3334 if (insn
& (1 << 21)) {
3336 if (insn
& (1 << 24))
3337 offset
= -offset
* n
;
3338 else if (dp
&& (insn
& 1))
3344 tcg_gen_addi_i32(addr
, addr
, offset
);
3345 store_reg(s
, rn
, addr
);
3353 /* Should never happen. */
3359 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3361 TranslationBlock
*tb
;
3364 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3366 gen_set_pc_im(dest
);
3367 tcg_gen_exit_tb((long)tb
+ n
);
3369 gen_set_pc_im(dest
);
3374 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3376 if (unlikely(s
->singlestep_enabled
)) {
3377 /* An indirect jump so that we still trigger the debug exception. */
3382 gen_goto_tb(s
, 0, dest
);
3383 s
->is_jmp
= DISAS_TB_JUMP
;
3387 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3390 tcg_gen_sari_i32(t0
, t0
, 16);
3394 tcg_gen_sari_i32(t1
, t1
, 16);
3397 tcg_gen_mul_i32(t0
, t0
, t1
);
3400 /* Return the mask of PSR bits set by a MSR instruction. */
3401 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3405 if (flags
& (1 << 0))
3407 if (flags
& (1 << 1))
3409 if (flags
& (1 << 2))
3411 if (flags
& (1 << 3))
3414 /* Mask out undefined bits. */
3415 mask
&= ~CPSR_RESERVED
;
3416 if (!arm_feature(env
, ARM_FEATURE_V6
))
3417 mask
&= ~(CPSR_E
| CPSR_GE
);
3418 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3420 /* Mask out execution state bits. */
3423 /* Mask out privileged bits. */
3429 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3430 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3434 /* ??? This is also undefined in system mode. */
3438 tmp
= load_cpu_field(spsr
);
3439 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3440 tcg_gen_andi_i32(t0
, t0
, mask
);
3441 tcg_gen_or_i32(tmp
, tmp
, t0
);
3442 store_cpu_field(tmp
, spsr
);
3444 gen_set_cpsr(t0
, mask
);
3451 /* Returns nonzero if access to the PSR is not permitted. */
3452 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3456 tcg_gen_movi_i32(tmp
, val
);
3457 return gen_set_psr(s
, mask
, spsr
, tmp
);
3460 /* Generate an old-style exception return. Marks pc as dead. */
3461 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3464 store_reg(s
, 15, pc
);
3465 tmp
= load_cpu_field(spsr
);
3466 gen_set_cpsr(tmp
, 0xffffffff);
3468 s
->is_jmp
= DISAS_UPDATE
;
3471 /* Generate a v6 exception return. Marks both values as dead. */
3472 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3474 gen_set_cpsr(cpsr
, 0xffffffff);
3476 store_reg(s
, 15, pc
);
3477 s
->is_jmp
= DISAS_UPDATE
;
3481 gen_set_condexec (DisasContext
*s
)
3483 if (s
->condexec_mask
) {
3484 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3485 TCGv tmp
= new_tmp();
3486 tcg_gen_movi_i32(tmp
, val
);
3487 store_cpu_field(tmp
, condexec_bits
);
3491 static void gen_nop_hint(DisasContext
*s
, int val
)
3495 gen_set_pc_im(s
->pc
);
3496 s
->is_jmp
= DISAS_WFI
;
3500 /* TODO: Implement SEV and WFE. May help SMP performance. */
3506 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3508 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3511 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3512 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3513 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3519 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3522 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3523 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3524 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3529 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3530 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3531 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3532 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3533 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3535 /* FIXME: This is wrong. They set the wrong overflow bit. */
3536 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3537 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3538 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3539 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3541 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3542 switch ((size << 1) | u) { \
3544 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3547 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3550 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3553 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3556 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3559 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3561 default: return 1; \
3564 #define GEN_NEON_INTEGER_OP(name) do { \
3565 switch ((size << 1) | u) { \
3567 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3570 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3573 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3576 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3579 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3582 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3584 default: return 1; \
3587 static TCGv
neon_load_scratch(int scratch
)
3589 TCGv tmp
= new_tmp();
3590 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3594 static void neon_store_scratch(int scratch
, TCGv var
)
3596 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3600 static inline TCGv
neon_get_scalar(int size
, int reg
)
3604 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3606 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3608 gen_neon_dup_low16(tmp
);
3610 gen_neon_dup_high16(tmp
);
3616 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3624 tcg_gen_andi_i32(rd
, t0
, 0xff);
3625 tcg_gen_shri_i32(tmp
, t0
, 8);
3626 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3627 tcg_gen_or_i32(rd
, rd
, tmp
);
3628 tcg_gen_shli_i32(tmp
, t1
, 16);
3629 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3630 tcg_gen_or_i32(rd
, rd
, tmp
);
3631 tcg_gen_shli_i32(tmp
, t1
, 8);
3632 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3633 tcg_gen_or_i32(rd
, rd
, tmp
);
3635 tcg_gen_shri_i32(rm
, t0
, 8);
3636 tcg_gen_andi_i32(rm
, rm
, 0xff);
3637 tcg_gen_shri_i32(tmp
, t0
, 16);
3638 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3639 tcg_gen_or_i32(rm
, rm
, tmp
);
3640 tcg_gen_shli_i32(tmp
, t1
, 8);
3641 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3642 tcg_gen_or_i32(rm
, rm
, tmp
);
3643 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3644 tcg_gen_or_i32(t1
, rm
, tmp
);
3645 tcg_gen_mov_i32(t0
, rd
);
3652 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3660 tcg_gen_andi_i32(rd
, t0
, 0xff);
3661 tcg_gen_shli_i32(tmp
, t1
, 8);
3662 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3663 tcg_gen_or_i32(rd
, rd
, tmp
);
3664 tcg_gen_shli_i32(tmp
, t0
, 16);
3665 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3666 tcg_gen_or_i32(rd
, rd
, tmp
);
3667 tcg_gen_shli_i32(tmp
, t1
, 24);
3668 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3669 tcg_gen_or_i32(rd
, rd
, tmp
);
3671 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3672 tcg_gen_shri_i32(tmp
, t0
, 8);
3673 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3674 tcg_gen_or_i32(rm
, rm
, tmp
);
3675 tcg_gen_shri_i32(tmp
, t1
, 8);
3676 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3677 tcg_gen_or_i32(rm
, rm
, tmp
);
3678 tcg_gen_shri_i32(tmp
, t0
, 16);
3679 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3680 tcg_gen_or_i32(t1
, rm
, tmp
);
3681 tcg_gen_mov_i32(t0
, rd
);
3688 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3695 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3696 tcg_gen_shli_i32(tmp2
, t1
, 16);
3697 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3698 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3699 tcg_gen_shri_i32(tmp2
, t0
, 16);
3700 tcg_gen_or_i32(t1
, t1
, tmp2
);
3701 tcg_gen_mov_i32(t0
, tmp
);
3707 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3712 for (n
= 0; n
< q
+ 1; n
+= 2) {
3713 t0
= neon_load_reg(reg
, n
);
3714 t1
= neon_load_reg(reg
, n
+ 1);
3716 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3717 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3718 case 2: /* no-op */; break;
3721 neon_store_scratch(tmp
+ n
, t0
);
3722 neon_store_scratch(tmp
+ n
+ 1, t1
);
3726 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3733 tcg_gen_shli_i32(rd
, t0
, 8);
3734 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3735 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3736 tcg_gen_or_i32(rd
, rd
, tmp
);
3738 tcg_gen_shri_i32(t1
, t1
, 8);
3739 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3740 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3741 tcg_gen_or_i32(t1
, t1
, tmp
);
3742 tcg_gen_mov_i32(t0
, rd
);
3748 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3755 tcg_gen_shli_i32(rd
, t0
, 16);
3756 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3757 tcg_gen_or_i32(rd
, rd
, tmp
);
3758 tcg_gen_shri_i32(t1
, t1
, 16);
3759 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3760 tcg_gen_or_i32(t1
, t1
, tmp
);
3761 tcg_gen_mov_i32(t0
, rd
);
3772 } neon_ls_element_type
[11] = {
3786 /* Translate a NEON load/store element instruction. Return nonzero if the
3787 instruction is invalid. */
3788 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3807 if (!vfp_enabled(env
))
3809 VFP_DREG_D(rd
, insn
);
3810 rn
= (insn
>> 16) & 0xf;
3812 load
= (insn
& (1 << 21)) != 0;
3814 if ((insn
& (1 << 23)) == 0) {
3815 /* Load store all elements. */
3816 op
= (insn
>> 8) & 0xf;
3817 size
= (insn
>> 6) & 3;
3820 nregs
= neon_ls_element_type
[op
].nregs
;
3821 interleave
= neon_ls_element_type
[op
].interleave
;
3822 spacing
= neon_ls_element_type
[op
].spacing
;
3823 if (size
== 3 && (interleave
| spacing
) != 1)
3825 load_reg_var(s
, addr
, rn
);
3826 stride
= (1 << size
) * interleave
;
3827 for (reg
= 0; reg
< nregs
; reg
++) {
3828 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3829 load_reg_var(s
, addr
, rn
);
3830 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3831 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3832 load_reg_var(s
, addr
, rn
);
3833 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3837 tmp64
= gen_ld64(addr
, IS_USER(s
));
3838 neon_store_reg64(tmp64
, rd
);
3839 tcg_temp_free_i64(tmp64
);
3841 tmp64
= tcg_temp_new_i64();
3842 neon_load_reg64(tmp64
, rd
);
3843 gen_st64(tmp64
, addr
, IS_USER(s
));
3845 tcg_gen_addi_i32(addr
, addr
, stride
);
3847 for (pass
= 0; pass
< 2; pass
++) {
3850 tmp
= gen_ld32(addr
, IS_USER(s
));
3851 neon_store_reg(rd
, pass
, tmp
);
3853 tmp
= neon_load_reg(rd
, pass
);
3854 gen_st32(tmp
, addr
, IS_USER(s
));
3856 tcg_gen_addi_i32(addr
, addr
, stride
);
3857 } else if (size
== 1) {
3859 tmp
= gen_ld16u(addr
, IS_USER(s
));
3860 tcg_gen_addi_i32(addr
, addr
, stride
);
3861 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3862 tcg_gen_addi_i32(addr
, addr
, stride
);
3863 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3864 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3866 neon_store_reg(rd
, pass
, tmp
);
3868 tmp
= neon_load_reg(rd
, pass
);
3870 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3871 gen_st16(tmp
, addr
, IS_USER(s
));
3872 tcg_gen_addi_i32(addr
, addr
, stride
);
3873 gen_st16(tmp2
, addr
, IS_USER(s
));
3874 tcg_gen_addi_i32(addr
, addr
, stride
);
3876 } else /* size == 0 */ {
3879 for (n
= 0; n
< 4; n
++) {
3880 tmp
= gen_ld8u(addr
, IS_USER(s
));
3881 tcg_gen_addi_i32(addr
, addr
, stride
);
3885 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3886 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3890 neon_store_reg(rd
, pass
, tmp2
);
3892 tmp2
= neon_load_reg(rd
, pass
);
3893 for (n
= 0; n
< 4; n
++) {
3896 tcg_gen_mov_i32(tmp
, tmp2
);
3898 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3900 gen_st8(tmp
, addr
, IS_USER(s
));
3901 tcg_gen_addi_i32(addr
, addr
, stride
);
3912 size
= (insn
>> 10) & 3;
3914 /* Load single element to all lanes. */
3917 size
= (insn
>> 6) & 3;
3918 nregs
= ((insn
>> 8) & 3) + 1;
3919 stride
= (insn
& (1 << 5)) ? 2 : 1;
3920 load_reg_var(s
, addr
, rn
);
3921 for (reg
= 0; reg
< nregs
; reg
++) {
3924 tmp
= gen_ld8u(addr
, IS_USER(s
));
3925 gen_neon_dup_u8(tmp
, 0);
3928 tmp
= gen_ld16u(addr
, IS_USER(s
));
3929 gen_neon_dup_low16(tmp
);
3932 tmp
= gen_ld32(addr
, IS_USER(s
));
3936 default: /* Avoid compiler warnings. */
3939 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3941 tcg_gen_mov_i32(tmp2
, tmp
);
3942 neon_store_reg(rd
, 0, tmp2
);
3943 neon_store_reg(rd
, 1, tmp
);
3946 stride
= (1 << size
) * nregs
;
3948 /* Single element. */
3949 pass
= (insn
>> 7) & 1;
3952 shift
= ((insn
>> 5) & 3) * 8;
3956 shift
= ((insn
>> 6) & 1) * 16;
3957 stride
= (insn
& (1 << 5)) ? 2 : 1;
3961 stride
= (insn
& (1 << 6)) ? 2 : 1;
3966 nregs
= ((insn
>> 8) & 3) + 1;
3967 load_reg_var(s
, addr
, rn
);
3968 for (reg
= 0; reg
< nregs
; reg
++) {
3972 tmp
= gen_ld8u(addr
, IS_USER(s
));
3975 tmp
= gen_ld16u(addr
, IS_USER(s
));
3978 tmp
= gen_ld32(addr
, IS_USER(s
));
3980 default: /* Avoid compiler warnings. */
3984 tmp2
= neon_load_reg(rd
, pass
);
3985 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3988 neon_store_reg(rd
, pass
, tmp
);
3989 } else { /* Store */
3990 tmp
= neon_load_reg(rd
, pass
);
3992 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3995 gen_st8(tmp
, addr
, IS_USER(s
));
3998 gen_st16(tmp
, addr
, IS_USER(s
));
4001 gen_st32(tmp
, addr
, IS_USER(s
));
4006 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4008 stride
= nregs
* (1 << size
);
4015 base
= load_reg(s
, rn
);
4017 tcg_gen_addi_i32(base
, base
, stride
);
4020 index
= load_reg(s
, rm
);
4021 tcg_gen_add_i32(base
, base
, index
);
4024 store_reg(s
, rn
, base
);
4029 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4030 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4032 tcg_gen_and_i32(t
, t
, c
);
4033 tcg_gen_andc_i32(f
, f
, c
);
4034 tcg_gen_or_i32(dest
, t
, f
);
4037 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4040 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4041 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4042 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4047 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4050 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4051 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4052 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4057 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4060 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4061 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4062 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4067 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4073 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4074 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4079 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4080 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4087 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4088 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4093 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4094 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4101 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4105 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4106 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4107 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4112 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4113 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4114 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4121 static inline void gen_neon_addl(int size
)
4124 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4125 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4126 case 2: tcg_gen_add_i64(CPU_V001
); break;
4131 static inline void gen_neon_subl(int size
)
4134 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4135 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4136 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4141 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4144 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4145 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4146 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4151 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4154 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4155 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4160 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4164 switch ((size
<< 1) | u
) {
4165 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4166 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4167 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4168 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4170 tmp
= gen_muls_i64_i32(a
, b
);
4171 tcg_gen_mov_i64(dest
, tmp
);
4174 tmp
= gen_mulu_i64_i32(a
, b
);
4175 tcg_gen_mov_i64(dest
, tmp
);
4181 /* Translate a NEON data processing instruction. Return nonzero if the
4182 instruction is invalid.
4183 We process data in a mixture of 32-bit and 64-bit chunks.
4184 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4186 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4199 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4202 if (!vfp_enabled(env
))
4204 q
= (insn
& (1 << 6)) != 0;
4205 u
= (insn
>> 24) & 1;
4206 VFP_DREG_D(rd
, insn
);
4207 VFP_DREG_N(rn
, insn
);
4208 VFP_DREG_M(rm
, insn
);
4209 size
= (insn
>> 20) & 3;
4210 if ((insn
& (1 << 23)) == 0) {
4211 /* Three register same length. */
4212 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4213 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4214 || op
== 10 || op
== 11 || op
== 16)) {
4215 /* 64-bit element instructions. */
4216 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4217 neon_load_reg64(cpu_V0
, rn
+ pass
);
4218 neon_load_reg64(cpu_V1
, rm
+ pass
);
4222 gen_helper_neon_add_saturate_u64(CPU_V001
);
4224 gen_helper_neon_add_saturate_s64(CPU_V001
);
4229 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4231 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4236 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4238 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4243 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4246 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4250 case 10: /* VRSHL */
4252 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4254 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4257 case 11: /* VQRSHL */
4259 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4262 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4268 tcg_gen_sub_i64(CPU_V001
);
4270 tcg_gen_add_i64(CPU_V001
);
4276 neon_store_reg64(cpu_V0
, rd
+ pass
);
4283 case 10: /* VRSHL */
4284 case 11: /* VQRSHL */
4287 /* Shift instruction operands are reversed. */
4294 case 20: /* VPMAX */
4295 case 21: /* VPMIN */
4296 case 23: /* VPADD */
4299 case 26: /* VPADD (float) */
4300 pairwise
= (u
&& size
< 2);
4302 case 30: /* VPMIN/VPMAX (float) */
4310 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4319 tmp
= neon_load_reg(rn
, n
);
4320 tmp2
= neon_load_reg(rn
, n
+ 1);
4322 tmp
= neon_load_reg(rm
, n
);
4323 tmp2
= neon_load_reg(rm
, n
+ 1);
4327 tmp
= neon_load_reg(rn
, pass
);
4328 tmp2
= neon_load_reg(rm
, pass
);
4332 GEN_NEON_INTEGER_OP(hadd
);
4335 GEN_NEON_INTEGER_OP_ENV(qadd
);
4337 case 2: /* VRHADD */
4338 GEN_NEON_INTEGER_OP(rhadd
);
4340 case 3: /* Logic ops. */
4341 switch ((u
<< 2) | size
) {
4343 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4346 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4349 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4352 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4355 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4358 tmp3
= neon_load_reg(rd
, pass
);
4359 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4363 tmp3
= neon_load_reg(rd
, pass
);
4364 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4368 tmp3
= neon_load_reg(rd
, pass
);
4369 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4375 GEN_NEON_INTEGER_OP(hsub
);
4378 GEN_NEON_INTEGER_OP_ENV(qsub
);
4381 GEN_NEON_INTEGER_OP(cgt
);
4384 GEN_NEON_INTEGER_OP(cge
);
4387 GEN_NEON_INTEGER_OP(shl
);
4390 GEN_NEON_INTEGER_OP_ENV(qshl
);
4392 case 10: /* VRSHL */
4393 GEN_NEON_INTEGER_OP(rshl
);
4395 case 11: /* VQRSHL */
4396 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4399 GEN_NEON_INTEGER_OP(max
);
4402 GEN_NEON_INTEGER_OP(min
);
4405 GEN_NEON_INTEGER_OP(abd
);
4408 GEN_NEON_INTEGER_OP(abd
);
4410 tmp2
= neon_load_reg(rd
, pass
);
4411 gen_neon_add(size
, tmp
, tmp2
);
4414 if (!u
) { /* VADD */
4415 if (gen_neon_add(size
, tmp
, tmp2
))
4419 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4420 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4421 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4427 if (!u
) { /* VTST */
4429 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4430 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4431 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4436 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4437 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4438 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4443 case 18: /* Multiply. */
4445 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4446 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4447 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4451 tmp2
= neon_load_reg(rd
, pass
);
4453 gen_neon_rsb(size
, tmp
, tmp2
);
4455 gen_neon_add(size
, tmp
, tmp2
);
4459 if (u
) { /* polynomial */
4460 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4461 } else { /* Integer */
4463 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4464 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4465 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4470 case 20: /* VPMAX */
4471 GEN_NEON_INTEGER_OP(pmax
);
4473 case 21: /* VPMIN */
4474 GEN_NEON_INTEGER_OP(pmin
);
4476 case 22: /* Hultiply high. */
4477 if (!u
) { /* VQDMULH */
4479 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4480 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4483 } else { /* VQRDHMUL */
4485 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4486 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4491 case 23: /* VPADD */
4495 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4496 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4497 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4501 case 26: /* Floating point arithnetic. */
4502 switch ((u
<< 2) | size
) {
4504 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4507 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4510 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4513 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4519 case 27: /* Float multiply. */
4520 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4523 tmp2
= neon_load_reg(rd
, pass
);
4525 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4527 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4531 case 28: /* Float compare. */
4533 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4536 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4538 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4541 case 29: /* Float compare absolute. */
4545 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4547 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4549 case 30: /* Float min/max. */
4551 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4553 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4557 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4559 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4566 /* Save the result. For elementwise operations we can put it
4567 straight into the destination register. For pairwise operations
4568 we have to be careful to avoid clobbering the source operands. */
4569 if (pairwise
&& rd
== rm
) {
4570 neon_store_scratch(pass
, tmp
);
4572 neon_store_reg(rd
, pass
, tmp
);
4576 if (pairwise
&& rd
== rm
) {
4577 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4578 tmp
= neon_load_scratch(pass
);
4579 neon_store_reg(rd
, pass
, tmp
);
4582 /* End of 3 register same size operations. */
4583 } else if (insn
& (1 << 4)) {
4584 if ((insn
& 0x00380080) != 0) {
4585 /* Two registers and shift. */
4586 op
= (insn
>> 8) & 0xf;
4587 if (insn
& (1 << 7)) {
4592 while ((insn
& (1 << (size
+ 19))) == 0)
4595 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4596 /* To avoid excessive dumplication of ops we implement shift
4597 by immediate using the variable shift operations. */
4599 /* Shift by immediate:
4600 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4601 /* Right shifts are encoded as N - shift, where N is the
4602 element size in bits. */
4604 shift
= shift
- (1 << (size
+ 3));
4612 imm
= (uint8_t) shift
;
4617 imm
= (uint16_t) shift
;
4628 for (pass
= 0; pass
< count
; pass
++) {
4630 neon_load_reg64(cpu_V0
, rm
+ pass
);
4631 tcg_gen_movi_i64(cpu_V1
, imm
);
4636 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4638 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4643 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4645 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4650 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4652 case 5: /* VSHL, VSLI */
4653 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4657 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4659 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4661 case 7: /* VQSHLU */
4662 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4665 if (op
== 1 || op
== 3) {
4667 neon_load_reg64(cpu_V0
, rd
+ pass
);
4668 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4669 } else if (op
== 4 || (op
== 5 && u
)) {
4671 cpu_abort(env
, "VS[LR]I.64 not implemented");
4673 neon_store_reg64(cpu_V0
, rd
+ pass
);
4674 } else { /* size < 3 */
4675 /* Operands in T0 and T1. */
4676 tmp
= neon_load_reg(rm
, pass
);
4678 tcg_gen_movi_i32(tmp2
, imm
);
4682 GEN_NEON_INTEGER_OP(shl
);
4686 GEN_NEON_INTEGER_OP(rshl
);
4691 GEN_NEON_INTEGER_OP(shl
);
4693 case 5: /* VSHL, VSLI */
4695 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4696 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4697 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4702 GEN_NEON_INTEGER_OP_ENV(qshl
);
4704 case 7: /* VQSHLU */
4706 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4707 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4708 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4715 if (op
== 1 || op
== 3) {
4717 tmp2
= neon_load_reg(rd
, pass
);
4718 gen_neon_add(size
, tmp2
, tmp
);
4720 } else if (op
== 4 || (op
== 5 && u
)) {
4725 mask
= 0xff >> -shift
;
4727 mask
= (uint8_t)(0xff << shift
);
4733 mask
= 0xffff >> -shift
;
4735 mask
= (uint16_t)(0xffff << shift
);
4739 if (shift
< -31 || shift
> 31) {
4743 mask
= 0xffffffffu
>> -shift
;
4745 mask
= 0xffffffffu
<< shift
;
4751 tmp2
= neon_load_reg(rd
, pass
);
4752 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4753 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4754 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4757 neon_store_reg(rd
, pass
, tmp
);
4760 } else if (op
< 10) {
4761 /* Shift by immediate and narrow:
4762 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4763 shift
= shift
- (1 << (size
+ 3));
4767 imm
= (uint16_t)shift
;
4769 tmp2
= tcg_const_i32(imm
);
4770 TCGV_UNUSED_I64(tmp64
);
4773 imm
= (uint32_t)shift
;
4774 tmp2
= tcg_const_i32(imm
);
4775 TCGV_UNUSED_I64(tmp64
);
4778 tmp64
= tcg_const_i64(shift
);
4785 for (pass
= 0; pass
< 2; pass
++) {
4787 neon_load_reg64(cpu_V0
, rm
+ pass
);
4790 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4792 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4795 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4797 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4800 tmp
= neon_load_reg(rm
+ pass
, 0);
4801 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4802 tmp3
= neon_load_reg(rm
+ pass
, 1);
4803 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4804 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4809 if (op
== 8 && !u
) {
4810 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4813 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4815 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4817 neon_store_reg(rd
, pass
, tmp
);
4820 tcg_temp_free_i64(tmp64
);
4824 } else if (op
== 10) {
4828 tmp
= neon_load_reg(rm
, 0);
4829 tmp2
= neon_load_reg(rm
, 1);
4830 for (pass
= 0; pass
< 2; pass
++) {
4834 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4837 /* The shift is less than the width of the source
4838 type, so we can just shift the whole register. */
4839 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4840 if (size
< 2 || !u
) {
4843 imm
= (0xffu
>> (8 - shift
));
4846 imm
= 0xffff >> (16 - shift
);
4848 imm64
= imm
| (((uint64_t)imm
) << 32);
4849 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4852 neon_store_reg64(cpu_V0
, rd
+ pass
);
4854 } else if (op
>= 14) {
4855 /* VCVT fixed-point. */
4856 /* We have already masked out the must-be-1 top bit of imm6,
4857 * hence this 32-shift where the ARM ARM has 64-imm6.
4860 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4861 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4864 gen_vfp_ulto(0, shift
);
4866 gen_vfp_slto(0, shift
);
4869 gen_vfp_toul(0, shift
);
4871 gen_vfp_tosl(0, shift
);
4873 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4878 } else { /* (insn & 0x00380080) == 0 */
4881 op
= (insn
>> 8) & 0xf;
4882 /* One register and immediate. */
4883 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4884 invert
= (insn
& (1 << 5)) != 0;
4902 imm
= (imm
<< 8) | (imm
<< 24);
4905 imm
= (imm
<< 8) | 0xff;
4908 imm
= (imm
<< 16) | 0xffff;
4911 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4916 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4917 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4923 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4924 if (op
& 1 && op
< 12) {
4925 tmp
= neon_load_reg(rd
, pass
);
4927 /* The immediate value has already been inverted, so
4929 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4931 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4936 if (op
== 14 && invert
) {
4939 for (n
= 0; n
< 4; n
++) {
4940 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4941 val
|= 0xff << (n
* 8);
4943 tcg_gen_movi_i32(tmp
, val
);
4945 tcg_gen_movi_i32(tmp
, imm
);
4948 neon_store_reg(rd
, pass
, tmp
);
4951 } else { /* (insn & 0x00800010 == 0x00800000) */
4953 op
= (insn
>> 8) & 0xf;
4954 if ((insn
& (1 << 6)) == 0) {
4955 /* Three registers of different lengths. */
4959 /* prewiden, src1_wide, src2_wide */
4960 static const int neon_3reg_wide
[16][3] = {
4961 {1, 0, 0}, /* VADDL */
4962 {1, 1, 0}, /* VADDW */
4963 {1, 0, 0}, /* VSUBL */
4964 {1, 1, 0}, /* VSUBW */
4965 {0, 1, 1}, /* VADDHN */
4966 {0, 0, 0}, /* VABAL */
4967 {0, 1, 1}, /* VSUBHN */
4968 {0, 0, 0}, /* VABDL */
4969 {0, 0, 0}, /* VMLAL */
4970 {0, 0, 0}, /* VQDMLAL */
4971 {0, 0, 0}, /* VMLSL */
4972 {0, 0, 0}, /* VQDMLSL */
4973 {0, 0, 0}, /* Integer VMULL */
4974 {0, 0, 0}, /* VQDMULL */
4975 {0, 0, 0} /* Polynomial VMULL */
4978 prewiden
= neon_3reg_wide
[op
][0];
4979 src1_wide
= neon_3reg_wide
[op
][1];
4980 src2_wide
= neon_3reg_wide
[op
][2];
4982 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4985 /* Avoid overlapping operands. Wide source operands are
4986 always aligned so will never overlap with wide
4987 destinations in problematic ways. */
4988 if (rd
== rm
&& !src2_wide
) {
4989 tmp
= neon_load_reg(rm
, 1);
4990 neon_store_scratch(2, tmp
);
4991 } else if (rd
== rn
&& !src1_wide
) {
4992 tmp
= neon_load_reg(rn
, 1);
4993 neon_store_scratch(2, tmp
);
4996 for (pass
= 0; pass
< 2; pass
++) {
4998 neon_load_reg64(cpu_V0
, rn
+ pass
);
5001 if (pass
== 1 && rd
== rn
) {
5002 tmp
= neon_load_scratch(2);
5004 tmp
= neon_load_reg(rn
, pass
);
5007 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5011 neon_load_reg64(cpu_V1
, rm
+ pass
);
5014 if (pass
== 1 && rd
== rm
) {
5015 tmp2
= neon_load_scratch(2);
5017 tmp2
= neon_load_reg(rm
, pass
);
5020 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5024 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5025 gen_neon_addl(size
);
5027 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5028 gen_neon_subl(size
);
5030 case 5: case 7: /* VABAL, VABDL */
5031 switch ((size
<< 1) | u
) {
5033 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5036 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5039 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5042 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5045 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5048 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5055 case 8: case 9: case 10: case 11: case 12: case 13:
5056 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5057 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5061 case 14: /* Polynomial VMULL */
5062 cpu_abort(env
, "Polynomial VMULL not implemented");
5064 default: /* 15 is RESERVED. */
5067 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5069 if (op
== 10 || op
== 11) {
5070 gen_neon_negl(cpu_V0
, size
);
5074 neon_load_reg64(cpu_V1
, rd
+ pass
);
5078 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5079 gen_neon_addl(size
);
5081 case 9: case 11: /* VQDMLAL, VQDMLSL */
5082 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5083 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5086 case 13: /* VQDMULL */
5087 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5092 neon_store_reg64(cpu_V0
, rd
+ pass
);
5093 } else if (op
== 4 || op
== 6) {
5094 /* Narrowing operation. */
5099 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5102 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5105 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5106 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5113 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5116 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5119 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5120 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5121 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5129 neon_store_reg(rd
, 0, tmp3
);
5130 neon_store_reg(rd
, 1, tmp
);
5133 /* Write back the result. */
5134 neon_store_reg64(cpu_V0
, rd
+ pass
);
5138 /* Two registers and a scalar. */
5140 case 0: /* Integer VMLA scalar */
5141 case 1: /* Float VMLA scalar */
5142 case 4: /* Integer VMLS scalar */
5143 case 5: /* Floating point VMLS scalar */
5144 case 8: /* Integer VMUL scalar */
5145 case 9: /* Floating point VMUL scalar */
5146 case 12: /* VQDMULH scalar */
5147 case 13: /* VQRDMULH scalar */
5148 tmp
= neon_get_scalar(size
, rm
);
5149 neon_store_scratch(0, tmp
);
5150 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5151 tmp
= neon_load_scratch(0);
5152 tmp2
= neon_load_reg(rn
, pass
);
5155 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5157 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5159 } else if (op
== 13) {
5161 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5163 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5165 } else if (op
& 1) {
5166 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5169 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5170 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5171 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5178 tmp2
= neon_load_reg(rd
, pass
);
5181 gen_neon_add(size
, tmp
, tmp2
);
5184 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5187 gen_neon_rsb(size
, tmp
, tmp2
);
5190 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5197 neon_store_reg(rd
, pass
, tmp
);
5200 case 2: /* VMLAL sclar */
5201 case 3: /* VQDMLAL scalar */
5202 case 6: /* VMLSL scalar */
5203 case 7: /* VQDMLSL scalar */
5204 case 10: /* VMULL scalar */
5205 case 11: /* VQDMULL scalar */
5206 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5209 tmp2
= neon_get_scalar(size
, rm
);
5210 tmp3
= neon_load_reg(rn
, 1);
5212 for (pass
= 0; pass
< 2; pass
++) {
5214 tmp
= neon_load_reg(rn
, 0);
5218 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5220 if (op
== 6 || op
== 7) {
5221 gen_neon_negl(cpu_V0
, size
);
5224 neon_load_reg64(cpu_V1
, rd
+ pass
);
5228 gen_neon_addl(size
);
5231 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5232 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5238 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5243 neon_store_reg64(cpu_V0
, rd
+ pass
);
5249 default: /* 14 and 15 are RESERVED */
5253 } else { /* size == 3 */
5256 imm
= (insn
>> 8) & 0xf;
5262 neon_load_reg64(cpu_V0
, rn
);
5264 neon_load_reg64(cpu_V1
, rn
+ 1);
5266 } else if (imm
== 8) {
5267 neon_load_reg64(cpu_V0
, rn
+ 1);
5269 neon_load_reg64(cpu_V1
, rm
);
5272 tmp64
= tcg_temp_new_i64();
5274 neon_load_reg64(cpu_V0
, rn
);
5275 neon_load_reg64(tmp64
, rn
+ 1);
5277 neon_load_reg64(cpu_V0
, rn
+ 1);
5278 neon_load_reg64(tmp64
, rm
);
5280 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5281 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5282 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5284 neon_load_reg64(cpu_V1
, rm
);
5286 neon_load_reg64(cpu_V1
, rm
+ 1);
5289 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5290 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5291 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5292 tcg_temp_free_i64(tmp64
);
5295 neon_load_reg64(cpu_V0
, rn
);
5296 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5297 neon_load_reg64(cpu_V1
, rm
);
5298 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5299 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5301 neon_store_reg64(cpu_V0
, rd
);
5303 neon_store_reg64(cpu_V1
, rd
+ 1);
5305 } else if ((insn
& (1 << 11)) == 0) {
5306 /* Two register misc. */
5307 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5308 size
= (insn
>> 18) & 3;
5310 case 0: /* VREV64 */
5313 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5314 tmp
= neon_load_reg(rm
, pass
* 2);
5315 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5317 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5318 case 1: gen_swap_half(tmp
); break;
5319 case 2: /* no-op */ break;
5322 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5324 neon_store_reg(rd
, pass
* 2, tmp2
);
5327 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5328 case 1: gen_swap_half(tmp2
); break;
5331 neon_store_reg(rd
, pass
* 2, tmp2
);
5335 case 4: case 5: /* VPADDL */
5336 case 12: case 13: /* VPADAL */
5339 for (pass
= 0; pass
< q
+ 1; pass
++) {
5340 tmp
= neon_load_reg(rm
, pass
* 2);
5341 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5342 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5343 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5345 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5346 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5347 case 2: tcg_gen_add_i64(CPU_V001
); break;
5352 neon_load_reg64(cpu_V1
, rd
+ pass
);
5353 gen_neon_addl(size
);
5355 neon_store_reg64(cpu_V0
, rd
+ pass
);
5360 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5361 tmp
= neon_load_reg(rm
, n
);
5362 tmp2
= neon_load_reg(rd
, n
+ 1);
5363 neon_store_reg(rm
, n
, tmp2
);
5364 neon_store_reg(rd
, n
+ 1, tmp
);
5372 Rd A3 A2 A1 A0 B2 B0 A2 A0
5373 Rm B3 B2 B1 B0 B3 B1 A3 A1
5377 gen_neon_unzip(rd
, q
, 0, size
);
5378 gen_neon_unzip(rm
, q
, 4, size
);
5380 static int unzip_order_q
[8] =
5381 {0, 2, 4, 6, 1, 3, 5, 7};
5382 for (n
= 0; n
< 8; n
++) {
5383 int reg
= (n
< 4) ? rd
: rm
;
5384 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5385 neon_store_reg(reg
, n
% 4, tmp
);
5388 static int unzip_order
[4] =
5390 for (n
= 0; n
< 4; n
++) {
5391 int reg
= (n
< 2) ? rd
: rm
;
5392 tmp
= neon_load_scratch(unzip_order
[n
]);
5393 neon_store_reg(reg
, n
% 2, tmp
);
5399 Rd A3 A2 A1 A0 B1 A1 B0 A0
5400 Rm B3 B2 B1 B0 B3 A3 B2 A2
5404 count
= (q
? 4 : 2);
5405 for (n
= 0; n
< count
; n
++) {
5406 tmp
= neon_load_reg(rd
, n
);
5407 tmp2
= neon_load_reg(rd
, n
);
5409 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5410 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5411 case 2: /* no-op */; break;
5414 neon_store_scratch(n
* 2, tmp
);
5415 neon_store_scratch(n
* 2 + 1, tmp2
);
5417 for (n
= 0; n
< count
* 2; n
++) {
5418 int reg
= (n
< count
) ? rd
: rm
;
5419 tmp
= neon_load_scratch(n
);
5420 neon_store_reg(reg
, n
% count
, tmp
);
5423 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5427 for (pass
= 0; pass
< 2; pass
++) {
5428 neon_load_reg64(cpu_V0
, rm
+ pass
);
5430 if (op
== 36 && q
== 0) {
5431 gen_neon_narrow(size
, tmp
, cpu_V0
);
5433 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5435 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5440 neon_store_reg(rd
, 0, tmp2
);
5441 neon_store_reg(rd
, 1, tmp
);
5445 case 38: /* VSHLL */
5448 tmp
= neon_load_reg(rm
, 0);
5449 tmp2
= neon_load_reg(rm
, 1);
5450 for (pass
= 0; pass
< 2; pass
++) {
5453 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5454 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5455 neon_store_reg64(cpu_V0
, rd
+ pass
);
5458 case 44: /* VCVT.F16.F32 */
5459 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5463 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5464 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5465 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5466 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5467 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5468 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5469 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5470 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5471 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5472 neon_store_reg(rd
, 0, tmp2
);
5474 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5475 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5476 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5477 neon_store_reg(rd
, 1, tmp2
);
5480 case 46: /* VCVT.F32.F16 */
5481 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5484 tmp
= neon_load_reg(rm
, 0);
5485 tmp2
= neon_load_reg(rm
, 1);
5486 tcg_gen_ext16u_i32(tmp3
, tmp
);
5487 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5488 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5489 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5490 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5491 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5493 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5494 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5495 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5496 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5497 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5498 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5504 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5505 if (op
== 30 || op
== 31 || op
>= 58) {
5506 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5507 neon_reg_offset(rm
, pass
));
5510 tmp
= neon_load_reg(rm
, pass
);
5513 case 1: /* VREV32 */
5515 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5516 case 1: gen_swap_half(tmp
); break;
5520 case 2: /* VREV16 */
5527 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5528 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5529 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5535 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5536 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5537 case 2: gen_helper_clz(tmp
, tmp
); break;
5544 gen_helper_neon_cnt_u8(tmp
, tmp
);
5549 tcg_gen_not_i32(tmp
, tmp
);
5551 case 14: /* VQABS */
5553 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5554 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5555 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5559 case 15: /* VQNEG */
5561 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5562 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5563 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5567 case 16: case 19: /* VCGT #0, VCLE #0 */
5568 tmp2
= tcg_const_i32(0);
5570 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5571 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5572 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5575 tcg_temp_free(tmp2
);
5577 tcg_gen_not_i32(tmp
, tmp
);
5579 case 17: case 20: /* VCGE #0, VCLT #0 */
5580 tmp2
= tcg_const_i32(0);
5582 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5583 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5584 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5587 tcg_temp_free(tmp2
);
5589 tcg_gen_not_i32(tmp
, tmp
);
5591 case 18: /* VCEQ #0 */
5592 tmp2
= tcg_const_i32(0);
5594 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5595 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5596 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5599 tcg_temp_free(tmp2
);
5603 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5604 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5605 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5612 tmp2
= tcg_const_i32(0);
5613 gen_neon_rsb(size
, tmp
, tmp2
);
5614 tcg_temp_free(tmp2
);
5616 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5617 tmp2
= tcg_const_i32(0);
5618 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5619 tcg_temp_free(tmp2
);
5621 tcg_gen_not_i32(tmp
, tmp
);
5623 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5624 tmp2
= tcg_const_i32(0);
5625 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5626 tcg_temp_free(tmp2
);
5628 tcg_gen_not_i32(tmp
, tmp
);
5630 case 26: /* Float VCEQ #0 */
5631 tmp2
= tcg_const_i32(0);
5632 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5633 tcg_temp_free(tmp2
);
5635 case 30: /* Float VABS */
5638 case 31: /* Float VNEG */
5642 tmp2
= neon_load_reg(rd
, pass
);
5643 neon_store_reg(rm
, pass
, tmp2
);
5646 tmp2
= neon_load_reg(rd
, pass
);
5648 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5649 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5653 neon_store_reg(rm
, pass
, tmp2
);
5655 case 56: /* Integer VRECPE */
5656 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5658 case 57: /* Integer VRSQRTE */
5659 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5661 case 58: /* Float VRECPE */
5662 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5664 case 59: /* Float VRSQRTE */
5665 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5667 case 60: /* VCVT.F32.S32 */
5670 case 61: /* VCVT.F32.U32 */
5673 case 62: /* VCVT.S32.F32 */
5676 case 63: /* VCVT.U32.F32 */
5680 /* Reserved: 21, 29, 39-56 */
5683 if (op
== 30 || op
== 31 || op
>= 58) {
5684 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5685 neon_reg_offset(rd
, pass
));
5687 neon_store_reg(rd
, pass
, tmp
);
5692 } else if ((insn
& (1 << 10)) == 0) {
5694 n
= ((insn
>> 5) & 0x18) + 8;
5695 if (insn
& (1 << 6)) {
5696 tmp
= neon_load_reg(rd
, 0);
5699 tcg_gen_movi_i32(tmp
, 0);
5701 tmp2
= neon_load_reg(rm
, 0);
5702 tmp4
= tcg_const_i32(rn
);
5703 tmp5
= tcg_const_i32(n
);
5704 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5706 if (insn
& (1 << 6)) {
5707 tmp
= neon_load_reg(rd
, 1);
5710 tcg_gen_movi_i32(tmp
, 0);
5712 tmp3
= neon_load_reg(rm
, 1);
5713 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5714 tcg_temp_free_i32(tmp5
);
5715 tcg_temp_free_i32(tmp4
);
5716 neon_store_reg(rd
, 0, tmp2
);
5717 neon_store_reg(rd
, 1, tmp3
);
5719 } else if ((insn
& 0x380) == 0) {
5721 if (insn
& (1 << 19)) {
5722 tmp
= neon_load_reg(rm
, 1);
5724 tmp
= neon_load_reg(rm
, 0);
5726 if (insn
& (1 << 16)) {
5727 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5728 } else if (insn
& (1 << 17)) {
5729 if ((insn
>> 18) & 1)
5730 gen_neon_dup_high16(tmp
);
5732 gen_neon_dup_low16(tmp
);
5734 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5736 tcg_gen_mov_i32(tmp2
, tmp
);
5737 neon_store_reg(rd
, pass
, tmp2
);
5748 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5750 int crn
= (insn
>> 16) & 0xf;
5751 int crm
= insn
& 0xf;
5752 int op1
= (insn
>> 21) & 7;
5753 int op2
= (insn
>> 5) & 7;
5754 int rt
= (insn
>> 12) & 0xf;
5757 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5758 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5762 tmp
= load_cpu_field(teecr
);
5763 store_reg(s
, rt
, tmp
);
5766 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5768 if (IS_USER(s
) && (env
->teecr
& 1))
5770 tmp
= load_cpu_field(teehbr
);
5771 store_reg(s
, rt
, tmp
);
5775 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5776 op1
, crn
, crm
, op2
);
5780 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5782 int crn
= (insn
>> 16) & 0xf;
5783 int crm
= insn
& 0xf;
5784 int op1
= (insn
>> 21) & 7;
5785 int op2
= (insn
>> 5) & 7;
5786 int rt
= (insn
>> 12) & 0xf;
5789 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5790 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5794 tmp
= load_reg(s
, rt
);
5795 gen_helper_set_teecr(cpu_env
, tmp
);
5799 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5801 if (IS_USER(s
) && (env
->teecr
& 1))
5803 tmp
= load_reg(s
, rt
);
5804 store_cpu_field(tmp
, teehbr
);
5808 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5809 op1
, crn
, crm
, op2
);
5813 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5817 cpnum
= (insn
>> 8) & 0xf;
5818 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5819 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5825 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5826 return disas_iwmmxt_insn(env
, s
, insn
);
5827 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5828 return disas_dsp_insn(env
, s
, insn
);
5833 return disas_vfp_insn (env
, s
, insn
);
5835 /* Coprocessors 7-15 are architecturally reserved by ARM.
5836 Unfortunately Intel decided to ignore this. */
5837 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5839 if (insn
& (1 << 20))
5840 return disas_cp14_read(env
, s
, insn
);
5842 return disas_cp14_write(env
, s
, insn
);
5844 return disas_cp15_insn (env
, s
, insn
);
5847 /* Unknown coprocessor. See if the board has hooked it. */
5848 return disas_cp_insn (env
, s
, insn
);
5853 /* Store a 64-bit value to a register pair. Clobbers val. */
5854 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5858 tcg_gen_trunc_i64_i32(tmp
, val
);
5859 store_reg(s
, rlow
, tmp
);
5861 tcg_gen_shri_i64(val
, val
, 32);
5862 tcg_gen_trunc_i64_i32(tmp
, val
);
5863 store_reg(s
, rhigh
, tmp
);
5866 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5867 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5872 /* Load value and extend to 64 bits. */
5873 tmp
= tcg_temp_new_i64();
5874 tmp2
= load_reg(s
, rlow
);
5875 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5877 tcg_gen_add_i64(val
, val
, tmp
);
5878 tcg_temp_free_i64(tmp
);
5881 /* load and add a 64-bit value from a register pair. */
5882 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5888 /* Load 64-bit value rd:rn. */
5889 tmpl
= load_reg(s
, rlow
);
5890 tmph
= load_reg(s
, rhigh
);
5891 tmp
= tcg_temp_new_i64();
5892 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5895 tcg_gen_add_i64(val
, val
, tmp
);
5896 tcg_temp_free_i64(tmp
);
5899 /* Set N and Z flags from a 64-bit value. */
5900 static void gen_logicq_cc(TCGv_i64 val
)
5902 TCGv tmp
= new_tmp();
5903 gen_helper_logicq_cc(tmp
, val
);
5908 /* Load/Store exclusive instructions are implemented by remembering
5909 the value/address loaded, and seeing if these are the same
5910 when the store is performed. This should be is sufficient to implement
5911 the architecturally mandated semantics, and avoids having to monitor
5914 In system emulation mode only one CPU will be running at once, so
5915 this sequence is effectively atomic. In user emulation mode we
5916 throw an exception and handle the atomic operation elsewhere. */
5917 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
5918 TCGv addr
, int size
)
5924 tmp
= gen_ld8u(addr
, IS_USER(s
));
5927 tmp
= gen_ld16u(addr
, IS_USER(s
));
5931 tmp
= gen_ld32(addr
, IS_USER(s
));
5936 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
5937 store_reg(s
, rt
, tmp
);
5939 TCGv tmp2
= new_tmp();
5940 tcg_gen_addi_i32(tmp2
, addr
, 4);
5941 tmp
= gen_ld32(tmp2
, IS_USER(s
));
5943 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
5944 store_reg(s
, rt2
, tmp
);
5946 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
5949 static void gen_clrex(DisasContext
*s
)
5951 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
5954 #ifdef CONFIG_USER_ONLY
5955 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5956 TCGv addr
, int size
)
5958 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
5959 tcg_gen_movi_i32(cpu_exclusive_info
,
5960 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
5961 gen_set_condexec(s
);
5962 gen_set_pc_im(s
->pc
- 4);
5963 gen_exception(EXCP_STREX
);
5964 s
->is_jmp
= DISAS_JUMP
;
5967 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5968 TCGv addr
, int size
)
5974 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5980 fail_label
= gen_new_label();
5981 done_label
= gen_new_label();
5982 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
5985 tmp
= gen_ld8u(addr
, IS_USER(s
));
5988 tmp
= gen_ld16u(addr
, IS_USER(s
));
5992 tmp
= gen_ld32(addr
, IS_USER(s
));
5997 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
6000 TCGv tmp2
= new_tmp();
6001 tcg_gen_addi_i32(tmp2
, addr
, 4);
6002 tmp
= gen_ld32(tmp2
, IS_USER(s
));
6004 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6007 tmp
= load_reg(s
, rt
);
6010 gen_st8(tmp
, addr
, IS_USER(s
));
6013 gen_st16(tmp
, addr
, IS_USER(s
));
6017 gen_st32(tmp
, addr
, IS_USER(s
));
6023 tcg_gen_addi_i32(addr
, addr
, 4);
6024 tmp
= load_reg(s
, rt2
);
6025 gen_st32(tmp
, addr
, IS_USER(s
));
6027 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6028 tcg_gen_br(done_label
);
6029 gen_set_label(fail_label
);
6030 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6031 gen_set_label(done_label
);
6032 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6036 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
6038 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6045 insn
= ldl_code(s
->pc
);
6048 /* M variants do not implement ARM mode. */
6053 /* Unconditional instructions. */
6054 if (((insn
>> 25) & 7) == 1) {
6055 /* NEON Data processing. */
6056 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6059 if (disas_neon_data_insn(env
, s
, insn
))
6063 if ((insn
& 0x0f100000) == 0x04000000) {
6064 /* NEON load/store. */
6065 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6068 if (disas_neon_ls_insn(env
, s
, insn
))
6072 if ((insn
& 0x0d70f000) == 0x0550f000)
6074 else if ((insn
& 0x0ffffdff) == 0x01010000) {
6077 if (insn
& (1 << 9)) {
6078 /* BE8 mode not implemented. */
6082 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6083 switch ((insn
>> 4) & 0xf) {
6092 /* We don't emulate caches so these are a no-op. */
6097 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6103 op1
= (insn
& 0x1f);
6104 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6105 addr
= load_reg(s
, 13);
6108 tmp
= tcg_const_i32(op1
);
6109 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6110 tcg_temp_free_i32(tmp
);
6112 i
= (insn
>> 23) & 3;
6114 case 0: offset
= -4; break; /* DA */
6115 case 1: offset
= 0; break; /* IA */
6116 case 2: offset
= -8; break; /* DB */
6117 case 3: offset
= 4; break; /* IB */
6121 tcg_gen_addi_i32(addr
, addr
, offset
);
6122 tmp
= load_reg(s
, 14);
6123 gen_st32(tmp
, addr
, 0);
6124 tmp
= load_cpu_field(spsr
);
6125 tcg_gen_addi_i32(addr
, addr
, 4);
6126 gen_st32(tmp
, addr
, 0);
6127 if (insn
& (1 << 21)) {
6128 /* Base writeback. */
6130 case 0: offset
= -8; break;
6131 case 1: offset
= 4; break;
6132 case 2: offset
= -4; break;
6133 case 3: offset
= 0; break;
6137 tcg_gen_addi_i32(addr
, addr
, offset
);
6138 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6139 store_reg(s
, 13, addr
);
6141 tmp
= tcg_const_i32(op1
);
6142 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6143 tcg_temp_free_i32(tmp
);
6150 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6156 rn
= (insn
>> 16) & 0xf;
6157 addr
= load_reg(s
, rn
);
6158 i
= (insn
>> 23) & 3;
6160 case 0: offset
= -4; break; /* DA */
6161 case 1: offset
= 0; break; /* IA */
6162 case 2: offset
= -8; break; /* DB */
6163 case 3: offset
= 4; break; /* IB */
6167 tcg_gen_addi_i32(addr
, addr
, offset
);
6168 /* Load PC into tmp and CPSR into tmp2. */
6169 tmp
= gen_ld32(addr
, 0);
6170 tcg_gen_addi_i32(addr
, addr
, 4);
6171 tmp2
= gen_ld32(addr
, 0);
6172 if (insn
& (1 << 21)) {
6173 /* Base writeback. */
6175 case 0: offset
= -8; break;
6176 case 1: offset
= 4; break;
6177 case 2: offset
= -4; break;
6178 case 3: offset
= 0; break;
6182 tcg_gen_addi_i32(addr
, addr
, offset
);
6183 store_reg(s
, rn
, addr
);
6187 gen_rfe(s
, tmp
, tmp2
);
6189 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6190 /* branch link and change to thumb (blx <offset>) */
6193 val
= (uint32_t)s
->pc
;
6195 tcg_gen_movi_i32(tmp
, val
);
6196 store_reg(s
, 14, tmp
);
6197 /* Sign-extend the 24-bit offset */
6198 offset
= (((int32_t)insn
) << 8) >> 8;
6199 /* offset * 4 + bit24 * 2 + (thumb bit) */
6200 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6201 /* pipeline offset */
6205 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6206 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6207 /* iWMMXt register transfer. */
6208 if (env
->cp15
.c15_cpar
& (1 << 1))
6209 if (!disas_iwmmxt_insn(env
, s
, insn
))
6212 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6213 /* Coprocessor double register transfer. */
6214 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6215 /* Additional coprocessor register transfer. */
6216 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6219 /* cps (privileged) */
6223 if (insn
& (1 << 19)) {
6224 if (insn
& (1 << 8))
6226 if (insn
& (1 << 7))
6228 if (insn
& (1 << 6))
6230 if (insn
& (1 << 18))
6233 if (insn
& (1 << 17)) {
6235 val
|= (insn
& 0x1f);
6238 gen_set_psr_im(s
, mask
, 0, val
);
6245 /* if not always execute, we generate a conditional jump to
6247 s
->condlabel
= gen_new_label();
6248 gen_test_cc(cond
^ 1, s
->condlabel
);
6251 if ((insn
& 0x0f900000) == 0x03000000) {
6252 if ((insn
& (1 << 21)) == 0) {
6254 rd
= (insn
>> 12) & 0xf;
6255 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6256 if ((insn
& (1 << 22)) == 0) {
6259 tcg_gen_movi_i32(tmp
, val
);
6262 tmp
= load_reg(s
, rd
);
6263 tcg_gen_ext16u_i32(tmp
, tmp
);
6264 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6266 store_reg(s
, rd
, tmp
);
6268 if (((insn
>> 12) & 0xf) != 0xf)
6270 if (((insn
>> 16) & 0xf) == 0) {
6271 gen_nop_hint(s
, insn
& 0xff);
6273 /* CPSR = immediate */
6275 shift
= ((insn
>> 8) & 0xf) * 2;
6277 val
= (val
>> shift
) | (val
<< (32 - shift
));
6278 i
= ((insn
& (1 << 22)) != 0);
6279 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6283 } else if ((insn
& 0x0f900000) == 0x01000000
6284 && (insn
& 0x00000090) != 0x00000090) {
6285 /* miscellaneous instructions */
6286 op1
= (insn
>> 21) & 3;
6287 sh
= (insn
>> 4) & 0xf;
6290 case 0x0: /* move program status register */
6293 tmp
= load_reg(s
, rm
);
6294 i
= ((op1
& 2) != 0);
6295 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6299 rd
= (insn
>> 12) & 0xf;
6303 tmp
= load_cpu_field(spsr
);
6306 gen_helper_cpsr_read(tmp
);
6308 store_reg(s
, rd
, tmp
);
6313 /* branch/exchange thumb (bx). */
6314 tmp
= load_reg(s
, rm
);
6316 } else if (op1
== 3) {
6318 rd
= (insn
>> 12) & 0xf;
6319 tmp
= load_reg(s
, rm
);
6320 gen_helper_clz(tmp
, tmp
);
6321 store_reg(s
, rd
, tmp
);
6329 /* Trivial implementation equivalent to bx. */
6330 tmp
= load_reg(s
, rm
);
6340 /* branch link/exchange thumb (blx) */
6341 tmp
= load_reg(s
, rm
);
6343 tcg_gen_movi_i32(tmp2
, s
->pc
);
6344 store_reg(s
, 14, tmp2
);
6347 case 0x5: /* saturating add/subtract */
6348 rd
= (insn
>> 12) & 0xf;
6349 rn
= (insn
>> 16) & 0xf;
6350 tmp
= load_reg(s
, rm
);
6351 tmp2
= load_reg(s
, rn
);
6353 gen_helper_double_saturate(tmp2
, tmp2
);
6355 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6357 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6359 store_reg(s
, rd
, tmp
);
6362 /* SMC instruction (op1 == 3)
6363 and undefined instructions (op1 == 0 || op1 == 2)
6369 gen_set_condexec(s
);
6370 gen_set_pc_im(s
->pc
- 4);
6371 gen_exception(EXCP_BKPT
);
6372 s
->is_jmp
= DISAS_JUMP
;
6374 case 0x8: /* signed multiply */
6378 rs
= (insn
>> 8) & 0xf;
6379 rn
= (insn
>> 12) & 0xf;
6380 rd
= (insn
>> 16) & 0xf;
6382 /* (32 * 16) >> 16 */
6383 tmp
= load_reg(s
, rm
);
6384 tmp2
= load_reg(s
, rs
);
6386 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6389 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6390 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6392 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6393 tcg_temp_free_i64(tmp64
);
6394 if ((sh
& 2) == 0) {
6395 tmp2
= load_reg(s
, rn
);
6396 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6399 store_reg(s
, rd
, tmp
);
6402 tmp
= load_reg(s
, rm
);
6403 tmp2
= load_reg(s
, rs
);
6404 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6407 tmp64
= tcg_temp_new_i64();
6408 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6410 gen_addq(s
, tmp64
, rn
, rd
);
6411 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6412 tcg_temp_free_i64(tmp64
);
6415 tmp2
= load_reg(s
, rn
);
6416 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6419 store_reg(s
, rd
, tmp
);
6426 } else if (((insn
& 0x0e000000) == 0 &&
6427 (insn
& 0x00000090) != 0x90) ||
6428 ((insn
& 0x0e000000) == (1 << 25))) {
6429 int set_cc
, logic_cc
, shiftop
;
6431 op1
= (insn
>> 21) & 0xf;
6432 set_cc
= (insn
>> 20) & 1;
6433 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6435 /* data processing instruction */
6436 if (insn
& (1 << 25)) {
6437 /* immediate operand */
6439 shift
= ((insn
>> 8) & 0xf) * 2;
6441 val
= (val
>> shift
) | (val
<< (32 - shift
));
6444 tcg_gen_movi_i32(tmp2
, val
);
6445 if (logic_cc
&& shift
) {
6446 gen_set_CF_bit31(tmp2
);
6451 tmp2
= load_reg(s
, rm
);
6452 shiftop
= (insn
>> 5) & 3;
6453 if (!(insn
& (1 << 4))) {
6454 shift
= (insn
>> 7) & 0x1f;
6455 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6457 rs
= (insn
>> 8) & 0xf;
6458 tmp
= load_reg(s
, rs
);
6459 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6462 if (op1
!= 0x0f && op1
!= 0x0d) {
6463 rn
= (insn
>> 16) & 0xf;
6464 tmp
= load_reg(s
, rn
);
6468 rd
= (insn
>> 12) & 0xf;
6471 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6475 store_reg_bx(env
, s
, rd
, tmp
);
6478 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6482 store_reg_bx(env
, s
, rd
, tmp
);
6485 if (set_cc
&& rd
== 15) {
6486 /* SUBS r15, ... is used for exception return. */
6490 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6491 gen_exception_return(s
, tmp
);
6494 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6496 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6498 store_reg_bx(env
, s
, rd
, tmp
);
6503 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6505 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6507 store_reg_bx(env
, s
, rd
, tmp
);
6511 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6513 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6515 store_reg_bx(env
, s
, rd
, tmp
);
6519 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6521 gen_add_carry(tmp
, tmp
, tmp2
);
6523 store_reg_bx(env
, s
, rd
, tmp
);
6527 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6529 gen_sub_carry(tmp
, tmp
, tmp2
);
6531 store_reg_bx(env
, s
, rd
, tmp
);
6535 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6537 gen_sub_carry(tmp
, tmp2
, tmp
);
6539 store_reg_bx(env
, s
, rd
, tmp
);
6543 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6550 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6557 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6563 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6568 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6572 store_reg_bx(env
, s
, rd
, tmp
);
6575 if (logic_cc
&& rd
== 15) {
6576 /* MOVS r15, ... is used for exception return. */
6580 gen_exception_return(s
, tmp2
);
6585 store_reg_bx(env
, s
, rd
, tmp2
);
6589 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6593 store_reg_bx(env
, s
, rd
, tmp
);
6597 tcg_gen_not_i32(tmp2
, tmp2
);
6601 store_reg_bx(env
, s
, rd
, tmp2
);
6604 if (op1
!= 0x0f && op1
!= 0x0d) {
6608 /* other instructions */
6609 op1
= (insn
>> 24) & 0xf;
6613 /* multiplies, extra load/stores */
6614 sh
= (insn
>> 5) & 3;
6617 rd
= (insn
>> 16) & 0xf;
6618 rn
= (insn
>> 12) & 0xf;
6619 rs
= (insn
>> 8) & 0xf;
6621 op1
= (insn
>> 20) & 0xf;
6623 case 0: case 1: case 2: case 3: case 6:
6625 tmp
= load_reg(s
, rs
);
6626 tmp2
= load_reg(s
, rm
);
6627 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6629 if (insn
& (1 << 22)) {
6630 /* Subtract (mls) */
6632 tmp2
= load_reg(s
, rn
);
6633 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6635 } else if (insn
& (1 << 21)) {
6637 tmp2
= load_reg(s
, rn
);
6638 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6641 if (insn
& (1 << 20))
6643 store_reg(s
, rd
, tmp
);
6646 /* 64 bit mul double accumulate (UMAAL) */
6648 tmp
= load_reg(s
, rs
);
6649 tmp2
= load_reg(s
, rm
);
6650 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6651 gen_addq_lo(s
, tmp64
, rn
);
6652 gen_addq_lo(s
, tmp64
, rd
);
6653 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6654 tcg_temp_free_i64(tmp64
);
6656 case 8: case 9: case 10: case 11:
6657 case 12: case 13: case 14: case 15:
6658 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6659 tmp
= load_reg(s
, rs
);
6660 tmp2
= load_reg(s
, rm
);
6661 if (insn
& (1 << 22)) {
6662 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6664 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6666 if (insn
& (1 << 21)) { /* mult accumulate */
6667 gen_addq(s
, tmp64
, rn
, rd
);
6669 if (insn
& (1 << 20)) {
6670 gen_logicq_cc(tmp64
);
6672 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6673 tcg_temp_free_i64(tmp64
);
6679 rn
= (insn
>> 16) & 0xf;
6680 rd
= (insn
>> 12) & 0xf;
6681 if (insn
& (1 << 23)) {
6682 /* load/store exclusive */
6683 op1
= (insn
>> 21) & 0x3;
6688 addr
= tcg_temp_local_new_i32();
6689 load_reg_var(s
, addr
, rn
);
6690 if (insn
& (1 << 20)) {
6693 gen_load_exclusive(s
, rd
, 15, addr
, 2);
6695 case 1: /* ldrexd */
6696 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
6698 case 2: /* ldrexb */
6699 gen_load_exclusive(s
, rd
, 15, addr
, 0);
6701 case 3: /* ldrexh */
6702 gen_load_exclusive(s
, rd
, 15, addr
, 1);
6711 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
6713 case 1: /* strexd */
6714 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
6716 case 2: /* strexb */
6717 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
6719 case 3: /* strexh */
6720 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
6726 tcg_temp_free(addr
);
6728 /* SWP instruction */
6731 /* ??? This is not really atomic. However we know
6732 we never have multiple CPUs running in parallel,
6733 so it is good enough. */
6734 addr
= load_reg(s
, rn
);
6735 tmp
= load_reg(s
, rm
);
6736 if (insn
& (1 << 22)) {
6737 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6738 gen_st8(tmp
, addr
, IS_USER(s
));
6740 tmp2
= gen_ld32(addr
, IS_USER(s
));
6741 gen_st32(tmp
, addr
, IS_USER(s
));
6744 store_reg(s
, rd
, tmp2
);
6750 /* Misc load/store */
6751 rn
= (insn
>> 16) & 0xf;
6752 rd
= (insn
>> 12) & 0xf;
6753 addr
= load_reg(s
, rn
);
6754 if (insn
& (1 << 24))
6755 gen_add_datah_offset(s
, insn
, 0, addr
);
6757 if (insn
& (1 << 20)) {
6761 tmp
= gen_ld16u(addr
, IS_USER(s
));
6764 tmp
= gen_ld8s(addr
, IS_USER(s
));
6768 tmp
= gen_ld16s(addr
, IS_USER(s
));
6772 } else if (sh
& 2) {
6776 tmp
= load_reg(s
, rd
);
6777 gen_st32(tmp
, addr
, IS_USER(s
));
6778 tcg_gen_addi_i32(addr
, addr
, 4);
6779 tmp
= load_reg(s
, rd
+ 1);
6780 gen_st32(tmp
, addr
, IS_USER(s
));
6784 tmp
= gen_ld32(addr
, IS_USER(s
));
6785 store_reg(s
, rd
, tmp
);
6786 tcg_gen_addi_i32(addr
, addr
, 4);
6787 tmp
= gen_ld32(addr
, IS_USER(s
));
6791 address_offset
= -4;
6794 tmp
= load_reg(s
, rd
);
6795 gen_st16(tmp
, addr
, IS_USER(s
));
6798 /* Perform base writeback before the loaded value to
6799 ensure correct behavior with overlapping index registers.
6800 ldrd with base writeback is is undefined if the
6801 destination and index registers overlap. */
6802 if (!(insn
& (1 << 24))) {
6803 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6804 store_reg(s
, rn
, addr
);
6805 } else if (insn
& (1 << 21)) {
6807 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6808 store_reg(s
, rn
, addr
);
6813 /* Complete the load. */
6814 store_reg(s
, rd
, tmp
);
6823 if (insn
& (1 << 4)) {
6825 /* Armv6 Media instructions. */
6827 rn
= (insn
>> 16) & 0xf;
6828 rd
= (insn
>> 12) & 0xf;
6829 rs
= (insn
>> 8) & 0xf;
6830 switch ((insn
>> 23) & 3) {
6831 case 0: /* Parallel add/subtract. */
6832 op1
= (insn
>> 20) & 7;
6833 tmp
= load_reg(s
, rn
);
6834 tmp2
= load_reg(s
, rm
);
6835 sh
= (insn
>> 5) & 7;
6836 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6838 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6840 store_reg(s
, rd
, tmp
);
6843 if ((insn
& 0x00700020) == 0) {
6844 /* Halfword pack. */
6845 tmp
= load_reg(s
, rn
);
6846 tmp2
= load_reg(s
, rm
);
6847 shift
= (insn
>> 7) & 0x1f;
6848 if (insn
& (1 << 6)) {
6852 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6853 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6854 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6858 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6859 tcg_gen_ext16u_i32(tmp
, tmp
);
6860 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6862 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6864 store_reg(s
, rd
, tmp
);
6865 } else if ((insn
& 0x00200020) == 0x00200000) {
6867 tmp
= load_reg(s
, rm
);
6868 shift
= (insn
>> 7) & 0x1f;
6869 if (insn
& (1 << 6)) {
6872 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6874 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6876 sh
= (insn
>> 16) & 0x1f;
6878 tmp2
= tcg_const_i32(sh
);
6879 if (insn
& (1 << 22))
6880 gen_helper_usat(tmp
, tmp
, tmp2
);
6882 gen_helper_ssat(tmp
, tmp
, tmp2
);
6883 tcg_temp_free_i32(tmp2
);
6885 store_reg(s
, rd
, tmp
);
6886 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6888 tmp
= load_reg(s
, rm
);
6889 sh
= (insn
>> 16) & 0x1f;
6891 tmp2
= tcg_const_i32(sh
);
6892 if (insn
& (1 << 22))
6893 gen_helper_usat16(tmp
, tmp
, tmp2
);
6895 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6896 tcg_temp_free_i32(tmp2
);
6898 store_reg(s
, rd
, tmp
);
6899 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6901 tmp
= load_reg(s
, rn
);
6902 tmp2
= load_reg(s
, rm
);
6904 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6905 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6908 store_reg(s
, rd
, tmp
);
6909 } else if ((insn
& 0x000003e0) == 0x00000060) {
6910 tmp
= load_reg(s
, rm
);
6911 shift
= (insn
>> 10) & 3;
6912 /* ??? In many cases it's not neccessary to do a
6913 rotate, a shift is sufficient. */
6915 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6916 op1
= (insn
>> 20) & 7;
6918 case 0: gen_sxtb16(tmp
); break;
6919 case 2: gen_sxtb(tmp
); break;
6920 case 3: gen_sxth(tmp
); break;
6921 case 4: gen_uxtb16(tmp
); break;
6922 case 6: gen_uxtb(tmp
); break;
6923 case 7: gen_uxth(tmp
); break;
6924 default: goto illegal_op
;
6927 tmp2
= load_reg(s
, rn
);
6928 if ((op1
& 3) == 0) {
6929 gen_add16(tmp
, tmp2
);
6931 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6935 store_reg(s
, rd
, tmp
);
6936 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6938 tmp
= load_reg(s
, rm
);
6939 if (insn
& (1 << 22)) {
6940 if (insn
& (1 << 7)) {
6944 gen_helper_rbit(tmp
, tmp
);
6947 if (insn
& (1 << 7))
6950 tcg_gen_bswap32_i32(tmp
, tmp
);
6952 store_reg(s
, rd
, tmp
);
6957 case 2: /* Multiplies (Type 3). */
6958 tmp
= load_reg(s
, rm
);
6959 tmp2
= load_reg(s
, rs
);
6960 if (insn
& (1 << 20)) {
6961 /* Signed multiply most significant [accumulate].
6962 (SMMUL, SMMLA, SMMLS) */
6963 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6966 tmp
= load_reg(s
, rd
);
6967 if (insn
& (1 << 6)) {
6968 tmp64
= gen_subq_msw(tmp64
, tmp
);
6970 tmp64
= gen_addq_msw(tmp64
, tmp
);
6973 if (insn
& (1 << 5)) {
6974 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6976 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6978 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6979 tcg_temp_free_i64(tmp64
);
6980 store_reg(s
, rn
, tmp
);
6982 if (insn
& (1 << 5))
6983 gen_swap_half(tmp2
);
6984 gen_smul_dual(tmp
, tmp2
);
6985 /* This addition cannot overflow. */
6986 if (insn
& (1 << 6)) {
6987 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6989 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6992 if (insn
& (1 << 22)) {
6993 /* smlald, smlsld */
6994 tmp64
= tcg_temp_new_i64();
6995 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6997 gen_addq(s
, tmp64
, rd
, rn
);
6998 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6999 tcg_temp_free_i64(tmp64
);
7001 /* smuad, smusd, smlad, smlsd */
7004 tmp2
= load_reg(s
, rd
);
7005 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7008 store_reg(s
, rn
, tmp
);
7013 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
7015 case 0: /* Unsigned sum of absolute differences. */
7017 tmp
= load_reg(s
, rm
);
7018 tmp2
= load_reg(s
, rs
);
7019 gen_helper_usad8(tmp
, tmp
, tmp2
);
7022 tmp2
= load_reg(s
, rd
);
7023 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7026 store_reg(s
, rn
, tmp
);
7028 case 0x20: case 0x24: case 0x28: case 0x2c:
7029 /* Bitfield insert/clear. */
7031 shift
= (insn
>> 7) & 0x1f;
7032 i
= (insn
>> 16) & 0x1f;
7036 tcg_gen_movi_i32(tmp
, 0);
7038 tmp
= load_reg(s
, rm
);
7041 tmp2
= load_reg(s
, rd
);
7042 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
7045 store_reg(s
, rd
, tmp
);
7047 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7048 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7050 tmp
= load_reg(s
, rm
);
7051 shift
= (insn
>> 7) & 0x1f;
7052 i
= ((insn
>> 16) & 0x1f) + 1;
7057 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7059 gen_sbfx(tmp
, shift
, i
);
7062 store_reg(s
, rd
, tmp
);
7072 /* Check for undefined extension instructions
7073 * per the ARM Bible IE:
7074 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7076 sh
= (0xf << 20) | (0xf << 4);
7077 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7081 /* load/store byte/word */
7082 rn
= (insn
>> 16) & 0xf;
7083 rd
= (insn
>> 12) & 0xf;
7084 tmp2
= load_reg(s
, rn
);
7085 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7086 if (insn
& (1 << 24))
7087 gen_add_data_offset(s
, insn
, tmp2
);
7088 if (insn
& (1 << 20)) {
7090 if (insn
& (1 << 22)) {
7091 tmp
= gen_ld8u(tmp2
, i
);
7093 tmp
= gen_ld32(tmp2
, i
);
7097 tmp
= load_reg(s
, rd
);
7098 if (insn
& (1 << 22))
7099 gen_st8(tmp
, tmp2
, i
);
7101 gen_st32(tmp
, tmp2
, i
);
7103 if (!(insn
& (1 << 24))) {
7104 gen_add_data_offset(s
, insn
, tmp2
);
7105 store_reg(s
, rn
, tmp2
);
7106 } else if (insn
& (1 << 21)) {
7107 store_reg(s
, rn
, tmp2
);
7111 if (insn
& (1 << 20)) {
7112 /* Complete the load. */
7116 store_reg(s
, rd
, tmp
);
7122 int j
, n
, user
, loaded_base
;
7124 /* load/store multiple words */
7125 /* XXX: store correct base if write back */
7127 if (insn
& (1 << 22)) {
7129 goto illegal_op
; /* only usable in supervisor mode */
7131 if ((insn
& (1 << 15)) == 0)
7134 rn
= (insn
>> 16) & 0xf;
7135 addr
= load_reg(s
, rn
);
7137 /* compute total size */
7139 TCGV_UNUSED(loaded_var
);
7142 if (insn
& (1 << i
))
7145 /* XXX: test invalid n == 0 case ? */
7146 if (insn
& (1 << 23)) {
7147 if (insn
& (1 << 24)) {
7149 tcg_gen_addi_i32(addr
, addr
, 4);
7151 /* post increment */
7154 if (insn
& (1 << 24)) {
7156 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7158 /* post decrement */
7160 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7165 if (insn
& (1 << i
)) {
7166 if (insn
& (1 << 20)) {
7168 tmp
= gen_ld32(addr
, IS_USER(s
));
7172 tmp2
= tcg_const_i32(i
);
7173 gen_helper_set_user_reg(tmp2
, tmp
);
7174 tcg_temp_free_i32(tmp2
);
7176 } else if (i
== rn
) {
7180 store_reg(s
, i
, tmp
);
7185 /* special case: r15 = PC + 8 */
7186 val
= (long)s
->pc
+ 4;
7188 tcg_gen_movi_i32(tmp
, val
);
7191 tmp2
= tcg_const_i32(i
);
7192 gen_helper_get_user_reg(tmp
, tmp2
);
7193 tcg_temp_free_i32(tmp2
);
7195 tmp
= load_reg(s
, i
);
7197 gen_st32(tmp
, addr
, IS_USER(s
));
7200 /* no need to add after the last transfer */
7202 tcg_gen_addi_i32(addr
, addr
, 4);
7205 if (insn
& (1 << 21)) {
7207 if (insn
& (1 << 23)) {
7208 if (insn
& (1 << 24)) {
7211 /* post increment */
7212 tcg_gen_addi_i32(addr
, addr
, 4);
7215 if (insn
& (1 << 24)) {
7218 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7220 /* post decrement */
7221 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7224 store_reg(s
, rn
, addr
);
7229 store_reg(s
, rn
, loaded_var
);
7231 if ((insn
& (1 << 22)) && !user
) {
7232 /* Restore CPSR from SPSR. */
7233 tmp
= load_cpu_field(spsr
);
7234 gen_set_cpsr(tmp
, 0xffffffff);
7236 s
->is_jmp
= DISAS_UPDATE
;
7245 /* branch (and link) */
7246 val
= (int32_t)s
->pc
;
7247 if (insn
& (1 << 24)) {
7249 tcg_gen_movi_i32(tmp
, val
);
7250 store_reg(s
, 14, tmp
);
7252 offset
= (((int32_t)insn
<< 8) >> 8);
7253 val
+= (offset
<< 2) + 4;
7261 if (disas_coproc_insn(env
, s
, insn
))
7266 gen_set_pc_im(s
->pc
);
7267 s
->is_jmp
= DISAS_SWI
;
7271 gen_set_condexec(s
);
7272 gen_set_pc_im(s
->pc
- 4);
7273 gen_exception(EXCP_UDEF
);
7274 s
->is_jmp
= DISAS_JUMP
;
7280 /* Return true if this is a Thumb-2 logical op. */
7282 thumb2_logic_op(int op
)
7287 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7288 then set condition code flags based on the result of the operation.
7289 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7290 to the high bit of T1.
7291 Returns zero if the opcode is valid. */
7294 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7301 tcg_gen_and_i32(t0
, t0
, t1
);
7305 tcg_gen_andc_i32(t0
, t0
, t1
);
7309 tcg_gen_or_i32(t0
, t0
, t1
);
7313 tcg_gen_not_i32(t1
, t1
);
7314 tcg_gen_or_i32(t0
, t0
, t1
);
7318 tcg_gen_xor_i32(t0
, t0
, t1
);
7323 gen_helper_add_cc(t0
, t0
, t1
);
7325 tcg_gen_add_i32(t0
, t0
, t1
);
7329 gen_helper_adc_cc(t0
, t0
, t1
);
7335 gen_helper_sbc_cc(t0
, t0
, t1
);
7337 gen_sub_carry(t0
, t0
, t1
);
7341 gen_helper_sub_cc(t0
, t0
, t1
);
7343 tcg_gen_sub_i32(t0
, t0
, t1
);
7347 gen_helper_sub_cc(t0
, t1
, t0
);
7349 tcg_gen_sub_i32(t0
, t1
, t0
);
7351 default: /* 5, 6, 7, 9, 12, 15. */
7357 gen_set_CF_bit31(t1
);
7362 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7364 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7366 uint32_t insn
, imm
, shift
, offset
;
7367 uint32_t rd
, rn
, rm
, rs
;
7378 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7379 || arm_feature (env
, ARM_FEATURE_M
))) {
7380 /* Thumb-1 cores may need to treat bl and blx as a pair of
7381 16-bit instructions to get correct prefetch abort behavior. */
7383 if ((insn
& (1 << 12)) == 0) {
7384 /* Second half of blx. */
7385 offset
= ((insn
& 0x7ff) << 1);
7386 tmp
= load_reg(s
, 14);
7387 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7388 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7391 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7392 store_reg(s
, 14, tmp2
);
7396 if (insn
& (1 << 11)) {
7397 /* Second half of bl. */
7398 offset
= ((insn
& 0x7ff) << 1) | 1;
7399 tmp
= load_reg(s
, 14);
7400 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7403 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7404 store_reg(s
, 14, tmp2
);
7408 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7409 /* Instruction spans a page boundary. Implement it as two
7410 16-bit instructions in case the second half causes an
7412 offset
= ((int32_t)insn
<< 21) >> 9;
7413 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7416 /* Fall through to 32-bit decode. */
7419 insn
= lduw_code(s
->pc
);
7421 insn
|= (uint32_t)insn_hw1
<< 16;
7423 if ((insn
& 0xf800e800) != 0xf000e800) {
7427 rn
= (insn
>> 16) & 0xf;
7428 rs
= (insn
>> 12) & 0xf;
7429 rd
= (insn
>> 8) & 0xf;
7431 switch ((insn
>> 25) & 0xf) {
7432 case 0: case 1: case 2: case 3:
7433 /* 16-bit instructions. Should never happen. */
7436 if (insn
& (1 << 22)) {
7437 /* Other load/store, table branch. */
7438 if (insn
& 0x01200000) {
7439 /* Load/store doubleword. */
7442 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7444 addr
= load_reg(s
, rn
);
7446 offset
= (insn
& 0xff) * 4;
7447 if ((insn
& (1 << 23)) == 0)
7449 if (insn
& (1 << 24)) {
7450 tcg_gen_addi_i32(addr
, addr
, offset
);
7453 if (insn
& (1 << 20)) {
7455 tmp
= gen_ld32(addr
, IS_USER(s
));
7456 store_reg(s
, rs
, tmp
);
7457 tcg_gen_addi_i32(addr
, addr
, 4);
7458 tmp
= gen_ld32(addr
, IS_USER(s
));
7459 store_reg(s
, rd
, tmp
);
7462 tmp
= load_reg(s
, rs
);
7463 gen_st32(tmp
, addr
, IS_USER(s
));
7464 tcg_gen_addi_i32(addr
, addr
, 4);
7465 tmp
= load_reg(s
, rd
);
7466 gen_st32(tmp
, addr
, IS_USER(s
));
7468 if (insn
& (1 << 21)) {
7469 /* Base writeback. */
7472 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7473 store_reg(s
, rn
, addr
);
7477 } else if ((insn
& (1 << 23)) == 0) {
7478 /* Load/store exclusive word. */
7479 addr
= tcg_temp_local_new();
7480 load_reg_var(s
, addr
, rn
);
7481 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
7482 if (insn
& (1 << 20)) {
7483 gen_load_exclusive(s
, rs
, 15, addr
, 2);
7485 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
7487 tcg_temp_free(addr
);
7488 } else if ((insn
& (1 << 6)) == 0) {
7492 tcg_gen_movi_i32(addr
, s
->pc
);
7494 addr
= load_reg(s
, rn
);
7496 tmp
= load_reg(s
, rm
);
7497 tcg_gen_add_i32(addr
, addr
, tmp
);
7498 if (insn
& (1 << 4)) {
7500 tcg_gen_add_i32(addr
, addr
, tmp
);
7502 tmp
= gen_ld16u(addr
, IS_USER(s
));
7505 tmp
= gen_ld8u(addr
, IS_USER(s
));
7508 tcg_gen_shli_i32(tmp
, tmp
, 1);
7509 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7510 store_reg(s
, 15, tmp
);
7512 /* Load/store exclusive byte/halfword/doubleword. */
7514 op
= (insn
>> 4) & 0x3;
7518 addr
= tcg_temp_local_new();
7519 load_reg_var(s
, addr
, rn
);
7520 if (insn
& (1 << 20)) {
7521 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
7523 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
7525 tcg_temp_free(addr
);
7528 /* Load/store multiple, RFE, SRS. */
7529 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7530 /* Not available in user mode. */
7533 if (insn
& (1 << 20)) {
7535 addr
= load_reg(s
, rn
);
7536 if ((insn
& (1 << 24)) == 0)
7537 tcg_gen_addi_i32(addr
, addr
, -8);
7538 /* Load PC into tmp and CPSR into tmp2. */
7539 tmp
= gen_ld32(addr
, 0);
7540 tcg_gen_addi_i32(addr
, addr
, 4);
7541 tmp2
= gen_ld32(addr
, 0);
7542 if (insn
& (1 << 21)) {
7543 /* Base writeback. */
7544 if (insn
& (1 << 24)) {
7545 tcg_gen_addi_i32(addr
, addr
, 4);
7547 tcg_gen_addi_i32(addr
, addr
, -4);
7549 store_reg(s
, rn
, addr
);
7553 gen_rfe(s
, tmp
, tmp2
);
7557 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7558 addr
= load_reg(s
, 13);
7561 tmp
= tcg_const_i32(op
);
7562 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7563 tcg_temp_free_i32(tmp
);
7565 if ((insn
& (1 << 24)) == 0) {
7566 tcg_gen_addi_i32(addr
, addr
, -8);
7568 tmp
= load_reg(s
, 14);
7569 gen_st32(tmp
, addr
, 0);
7570 tcg_gen_addi_i32(addr
, addr
, 4);
7572 gen_helper_cpsr_read(tmp
);
7573 gen_st32(tmp
, addr
, 0);
7574 if (insn
& (1 << 21)) {
7575 if ((insn
& (1 << 24)) == 0) {
7576 tcg_gen_addi_i32(addr
, addr
, -4);
7578 tcg_gen_addi_i32(addr
, addr
, 4);
7580 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7581 store_reg(s
, 13, addr
);
7583 tmp
= tcg_const_i32(op
);
7584 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7585 tcg_temp_free_i32(tmp
);
7593 /* Load/store multiple. */
7594 addr
= load_reg(s
, rn
);
7596 for (i
= 0; i
< 16; i
++) {
7597 if (insn
& (1 << i
))
7600 if (insn
& (1 << 24)) {
7601 tcg_gen_addi_i32(addr
, addr
, -offset
);
7604 for (i
= 0; i
< 16; i
++) {
7605 if ((insn
& (1 << i
)) == 0)
7607 if (insn
& (1 << 20)) {
7609 tmp
= gen_ld32(addr
, IS_USER(s
));
7613 store_reg(s
, i
, tmp
);
7617 tmp
= load_reg(s
, i
);
7618 gen_st32(tmp
, addr
, IS_USER(s
));
7620 tcg_gen_addi_i32(addr
, addr
, 4);
7622 if (insn
& (1 << 21)) {
7623 /* Base register writeback. */
7624 if (insn
& (1 << 24)) {
7625 tcg_gen_addi_i32(addr
, addr
, -offset
);
7627 /* Fault if writeback register is in register list. */
7628 if (insn
& (1 << rn
))
7630 store_reg(s
, rn
, addr
);
7639 op
= (insn
>> 21) & 0xf;
7641 /* Halfword pack. */
7642 tmp
= load_reg(s
, rn
);
7643 tmp2
= load_reg(s
, rm
);
7644 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
7645 if (insn
& (1 << 5)) {
7649 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7650 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7651 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7655 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7656 tcg_gen_ext16u_i32(tmp
, tmp
);
7657 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7659 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7661 store_reg(s
, rd
, tmp
);
7663 /* Data processing register constant shift. */
7666 tcg_gen_movi_i32(tmp
, 0);
7668 tmp
= load_reg(s
, rn
);
7670 tmp2
= load_reg(s
, rm
);
7672 shiftop
= (insn
>> 4) & 3;
7673 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7674 conds
= (insn
& (1 << 20)) != 0;
7675 logic_cc
= (conds
&& thumb2_logic_op(op
));
7676 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7677 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7681 store_reg(s
, rd
, tmp
);
7687 case 13: /* Misc data processing. */
7688 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7689 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7692 case 0: /* Register controlled shift. */
7693 tmp
= load_reg(s
, rn
);
7694 tmp2
= load_reg(s
, rm
);
7695 if ((insn
& 0x70) != 0)
7697 op
= (insn
>> 21) & 3;
7698 logic_cc
= (insn
& (1 << 20)) != 0;
7699 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7702 store_reg_bx(env
, s
, rd
, tmp
);
7704 case 1: /* Sign/zero extend. */
7705 tmp
= load_reg(s
, rm
);
7706 shift
= (insn
>> 4) & 3;
7707 /* ??? In many cases it's not neccessary to do a
7708 rotate, a shift is sufficient. */
7710 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7711 op
= (insn
>> 20) & 7;
7713 case 0: gen_sxth(tmp
); break;
7714 case 1: gen_uxth(tmp
); break;
7715 case 2: gen_sxtb16(tmp
); break;
7716 case 3: gen_uxtb16(tmp
); break;
7717 case 4: gen_sxtb(tmp
); break;
7718 case 5: gen_uxtb(tmp
); break;
7719 default: goto illegal_op
;
7722 tmp2
= load_reg(s
, rn
);
7723 if ((op
>> 1) == 1) {
7724 gen_add16(tmp
, tmp2
);
7726 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7730 store_reg(s
, rd
, tmp
);
7732 case 2: /* SIMD add/subtract. */
7733 op
= (insn
>> 20) & 7;
7734 shift
= (insn
>> 4) & 7;
7735 if ((op
& 3) == 3 || (shift
& 3) == 3)
7737 tmp
= load_reg(s
, rn
);
7738 tmp2
= load_reg(s
, rm
);
7739 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7741 store_reg(s
, rd
, tmp
);
7743 case 3: /* Other data processing. */
7744 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7746 /* Saturating add/subtract. */
7747 tmp
= load_reg(s
, rn
);
7748 tmp2
= load_reg(s
, rm
);
7750 gen_helper_double_saturate(tmp
, tmp
);
7752 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7754 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7757 tmp
= load_reg(s
, rn
);
7759 case 0x0a: /* rbit */
7760 gen_helper_rbit(tmp
, tmp
);
7762 case 0x08: /* rev */
7763 tcg_gen_bswap32_i32(tmp
, tmp
);
7765 case 0x09: /* rev16 */
7768 case 0x0b: /* revsh */
7771 case 0x10: /* sel */
7772 tmp2
= load_reg(s
, rm
);
7774 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7775 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7779 case 0x18: /* clz */
7780 gen_helper_clz(tmp
, tmp
);
7786 store_reg(s
, rd
, tmp
);
7788 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7789 op
= (insn
>> 4) & 0xf;
7790 tmp
= load_reg(s
, rn
);
7791 tmp2
= load_reg(s
, rm
);
7792 switch ((insn
>> 20) & 7) {
7793 case 0: /* 32 x 32 -> 32 */
7794 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7797 tmp2
= load_reg(s
, rs
);
7799 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7801 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7805 case 1: /* 16 x 16 -> 32 */
7806 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7809 tmp2
= load_reg(s
, rs
);
7810 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7814 case 2: /* Dual multiply add. */
7815 case 4: /* Dual multiply subtract. */
7817 gen_swap_half(tmp2
);
7818 gen_smul_dual(tmp
, tmp2
);
7819 /* This addition cannot overflow. */
7820 if (insn
& (1 << 22)) {
7821 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7823 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7828 tmp2
= load_reg(s
, rs
);
7829 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7833 case 3: /* 32 * 16 -> 32msb */
7835 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7838 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7839 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7841 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7842 tcg_temp_free_i64(tmp64
);
7845 tmp2
= load_reg(s
, rs
);
7846 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7850 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7851 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7853 tmp
= load_reg(s
, rs
);
7854 if (insn
& (1 << 20)) {
7855 tmp64
= gen_addq_msw(tmp64
, tmp
);
7857 tmp64
= gen_subq_msw(tmp64
, tmp
);
7860 if (insn
& (1 << 4)) {
7861 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
7863 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
7865 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7866 tcg_temp_free_i64(tmp64
);
7868 case 7: /* Unsigned sum of absolute differences. */
7869 gen_helper_usad8(tmp
, tmp
, tmp2
);
7872 tmp2
= load_reg(s
, rs
);
7873 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7878 store_reg(s
, rd
, tmp
);
7880 case 6: case 7: /* 64-bit multiply, Divide. */
7881 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7882 tmp
= load_reg(s
, rn
);
7883 tmp2
= load_reg(s
, rm
);
7884 if ((op
& 0x50) == 0x10) {
7886 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7889 gen_helper_udiv(tmp
, tmp
, tmp2
);
7891 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7893 store_reg(s
, rd
, tmp
);
7894 } else if ((op
& 0xe) == 0xc) {
7895 /* Dual multiply accumulate long. */
7897 gen_swap_half(tmp2
);
7898 gen_smul_dual(tmp
, tmp2
);
7900 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7902 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7906 tmp64
= tcg_temp_new_i64();
7907 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7909 gen_addq(s
, tmp64
, rs
, rd
);
7910 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7911 tcg_temp_free_i64(tmp64
);
7914 /* Unsigned 64-bit multiply */
7915 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7919 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7921 tmp64
= tcg_temp_new_i64();
7922 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7925 /* Signed 64-bit multiply */
7926 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7931 gen_addq_lo(s
, tmp64
, rs
);
7932 gen_addq_lo(s
, tmp64
, rd
);
7933 } else if (op
& 0x40) {
7934 /* 64-bit accumulate. */
7935 gen_addq(s
, tmp64
, rs
, rd
);
7937 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7938 tcg_temp_free_i64(tmp64
);
7943 case 6: case 7: case 14: case 15:
7945 if (((insn
>> 24) & 3) == 3) {
7946 /* Translate into the equivalent ARM encoding. */
7947 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7948 if (disas_neon_data_insn(env
, s
, insn
))
7951 if (insn
& (1 << 28))
7953 if (disas_coproc_insn (env
, s
, insn
))
7957 case 8: case 9: case 10: case 11:
7958 if (insn
& (1 << 15)) {
7959 /* Branches, misc control. */
7960 if (insn
& 0x5000) {
7961 /* Unconditional branch. */
7962 /* signextend(hw1[10:0]) -> offset[:12]. */
7963 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7964 /* hw1[10:0] -> offset[11:1]. */
7965 offset
|= (insn
& 0x7ff) << 1;
7966 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7967 offset[24:22] already have the same value because of the
7968 sign extension above. */
7969 offset
^= ((~insn
) & (1 << 13)) << 10;
7970 offset
^= ((~insn
) & (1 << 11)) << 11;
7972 if (insn
& (1 << 14)) {
7973 /* Branch and link. */
7974 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7978 if (insn
& (1 << 12)) {
7983 offset
&= ~(uint32_t)2;
7984 gen_bx_im(s
, offset
);
7986 } else if (((insn
>> 23) & 7) == 7) {
7988 if (insn
& (1 << 13))
7991 if (insn
& (1 << 26)) {
7992 /* Secure monitor call (v6Z) */
7993 goto illegal_op
; /* not implemented. */
7995 op
= (insn
>> 20) & 7;
7997 case 0: /* msr cpsr. */
7999 tmp
= load_reg(s
, rn
);
8000 addr
= tcg_const_i32(insn
& 0xff);
8001 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8002 tcg_temp_free_i32(addr
);
8008 case 1: /* msr spsr. */
8011 tmp
= load_reg(s
, rn
);
8013 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
8017 case 2: /* cps, nop-hint. */
8018 if (((insn
>> 8) & 7) == 0) {
8019 gen_nop_hint(s
, insn
& 0xff);
8021 /* Implemented as NOP in user mode. */
8026 if (insn
& (1 << 10)) {
8027 if (insn
& (1 << 7))
8029 if (insn
& (1 << 6))
8031 if (insn
& (1 << 5))
8033 if (insn
& (1 << 9))
8034 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8036 if (insn
& (1 << 8)) {
8038 imm
|= (insn
& 0x1f);
8041 gen_set_psr_im(s
, offset
, 0, imm
);
8044 case 3: /* Special control operations. */
8046 op
= (insn
>> 4) & 0xf;
8054 /* These execute as NOPs. */
8061 /* Trivial implementation equivalent to bx. */
8062 tmp
= load_reg(s
, rn
);
8065 case 5: /* Exception return. */
8069 if (rn
!= 14 || rd
!= 15) {
8072 tmp
= load_reg(s
, rn
);
8073 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8074 gen_exception_return(s
, tmp
);
8076 case 6: /* mrs cpsr. */
8079 addr
= tcg_const_i32(insn
& 0xff);
8080 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8081 tcg_temp_free_i32(addr
);
8083 gen_helper_cpsr_read(tmp
);
8085 store_reg(s
, rd
, tmp
);
8087 case 7: /* mrs spsr. */
8088 /* Not accessible in user mode. */
8089 if (IS_USER(s
) || IS_M(env
))
8091 tmp
= load_cpu_field(spsr
);
8092 store_reg(s
, rd
, tmp
);
8097 /* Conditional branch. */
8098 op
= (insn
>> 22) & 0xf;
8099 /* Generate a conditional jump to next instruction. */
8100 s
->condlabel
= gen_new_label();
8101 gen_test_cc(op
^ 1, s
->condlabel
);
8104 /* offset[11:1] = insn[10:0] */
8105 offset
= (insn
& 0x7ff) << 1;
8106 /* offset[17:12] = insn[21:16]. */
8107 offset
|= (insn
& 0x003f0000) >> 4;
8108 /* offset[31:20] = insn[26]. */
8109 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8110 /* offset[18] = insn[13]. */
8111 offset
|= (insn
& (1 << 13)) << 5;
8112 /* offset[19] = insn[11]. */
8113 offset
|= (insn
& (1 << 11)) << 8;
8115 /* jump to the offset */
8116 gen_jmp(s
, s
->pc
+ offset
);
8119 /* Data processing immediate. */
8120 if (insn
& (1 << 25)) {
8121 if (insn
& (1 << 24)) {
8122 if (insn
& (1 << 20))
8124 /* Bitfield/Saturate. */
8125 op
= (insn
>> 21) & 7;
8127 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8130 tcg_gen_movi_i32(tmp
, 0);
8132 tmp
= load_reg(s
, rn
);
8135 case 2: /* Signed bitfield extract. */
8137 if (shift
+ imm
> 32)
8140 gen_sbfx(tmp
, shift
, imm
);
8142 case 6: /* Unsigned bitfield extract. */
8144 if (shift
+ imm
> 32)
8147 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8149 case 3: /* Bitfield insert/clear. */
8152 imm
= imm
+ 1 - shift
;
8154 tmp2
= load_reg(s
, rd
);
8155 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
8161 default: /* Saturate. */
8164 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8166 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8168 tmp2
= tcg_const_i32(imm
);
8171 if ((op
& 1) && shift
== 0)
8172 gen_helper_usat16(tmp
, tmp
, tmp2
);
8174 gen_helper_usat(tmp
, tmp
, tmp2
);
8177 if ((op
& 1) && shift
== 0)
8178 gen_helper_ssat16(tmp
, tmp
, tmp2
);
8180 gen_helper_ssat(tmp
, tmp
, tmp2
);
8182 tcg_temp_free_i32(tmp2
);
8185 store_reg(s
, rd
, tmp
);
8187 imm
= ((insn
& 0x04000000) >> 15)
8188 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8189 if (insn
& (1 << 22)) {
8190 /* 16-bit immediate. */
8191 imm
|= (insn
>> 4) & 0xf000;
8192 if (insn
& (1 << 23)) {
8194 tmp
= load_reg(s
, rd
);
8195 tcg_gen_ext16u_i32(tmp
, tmp
);
8196 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8200 tcg_gen_movi_i32(tmp
, imm
);
8203 /* Add/sub 12-bit immediate. */
8205 offset
= s
->pc
& ~(uint32_t)3;
8206 if (insn
& (1 << 23))
8211 tcg_gen_movi_i32(tmp
, offset
);
8213 tmp
= load_reg(s
, rn
);
8214 if (insn
& (1 << 23))
8215 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8217 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8220 store_reg(s
, rd
, tmp
);
8223 int shifter_out
= 0;
8224 /* modified 12-bit immediate. */
8225 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8226 imm
= (insn
& 0xff);
8229 /* Nothing to do. */
8231 case 1: /* 00XY00XY */
8234 case 2: /* XY00XY00 */
8238 case 3: /* XYXYXYXY */
8242 default: /* Rotated constant. */
8243 shift
= (shift
<< 1) | (imm
>> 7);
8245 imm
= imm
<< (32 - shift
);
8250 tcg_gen_movi_i32(tmp2
, imm
);
8251 rn
= (insn
>> 16) & 0xf;
8254 tcg_gen_movi_i32(tmp
, 0);
8256 tmp
= load_reg(s
, rn
);
8258 op
= (insn
>> 21) & 0xf;
8259 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8260 shifter_out
, tmp
, tmp2
))
8263 rd
= (insn
>> 8) & 0xf;
8265 store_reg(s
, rd
, tmp
);
8272 case 12: /* Load/store single data item. */
8277 if ((insn
& 0x01100000) == 0x01000000) {
8278 if (disas_neon_ls_insn(env
, s
, insn
))
8286 /* s->pc has already been incremented by 4. */
8287 imm
= s
->pc
& 0xfffffffc;
8288 if (insn
& (1 << 23))
8289 imm
+= insn
& 0xfff;
8291 imm
-= insn
& 0xfff;
8292 tcg_gen_movi_i32(addr
, imm
);
8294 addr
= load_reg(s
, rn
);
8295 if (insn
& (1 << 23)) {
8296 /* Positive offset. */
8298 tcg_gen_addi_i32(addr
, addr
, imm
);
8300 op
= (insn
>> 8) & 7;
8303 case 0: case 8: /* Shifted Register. */
8304 shift
= (insn
>> 4) & 0xf;
8307 tmp
= load_reg(s
, rm
);
8309 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8310 tcg_gen_add_i32(addr
, addr
, tmp
);
8313 case 4: /* Negative offset. */
8314 tcg_gen_addi_i32(addr
, addr
, -imm
);
8316 case 6: /* User privilege. */
8317 tcg_gen_addi_i32(addr
, addr
, imm
);
8320 case 1: /* Post-decrement. */
8323 case 3: /* Post-increment. */
8327 case 5: /* Pre-decrement. */
8330 case 7: /* Pre-increment. */
8331 tcg_gen_addi_i32(addr
, addr
, imm
);
8339 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8340 if (insn
& (1 << 20)) {
8342 if (rs
== 15 && op
!= 2) {
8345 /* Memory hint. Implemented as NOP. */
8348 case 0: tmp
= gen_ld8u(addr
, user
); break;
8349 case 4: tmp
= gen_ld8s(addr
, user
); break;
8350 case 1: tmp
= gen_ld16u(addr
, user
); break;
8351 case 5: tmp
= gen_ld16s(addr
, user
); break;
8352 case 2: tmp
= gen_ld32(addr
, user
); break;
8353 default: goto illegal_op
;
8358 store_reg(s
, rs
, tmp
);
8365 tmp
= load_reg(s
, rs
);
8367 case 0: gen_st8(tmp
, addr
, user
); break;
8368 case 1: gen_st16(tmp
, addr
, user
); break;
8369 case 2: gen_st32(tmp
, addr
, user
); break;
8370 default: goto illegal_op
;
8374 tcg_gen_addi_i32(addr
, addr
, imm
);
8376 store_reg(s
, rn
, addr
);
8390 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8392 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8399 if (s
->condexec_mask
) {
8400 cond
= s
->condexec_cond
;
8401 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
8402 s
->condlabel
= gen_new_label();
8403 gen_test_cc(cond
^ 1, s
->condlabel
);
8408 insn
= lduw_code(s
->pc
);
8411 switch (insn
>> 12) {
8415 op
= (insn
>> 11) & 3;
8418 rn
= (insn
>> 3) & 7;
8419 tmp
= load_reg(s
, rn
);
8420 if (insn
& (1 << 10)) {
8423 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8426 rm
= (insn
>> 6) & 7;
8427 tmp2
= load_reg(s
, rm
);
8429 if (insn
& (1 << 9)) {
8430 if (s
->condexec_mask
)
8431 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8433 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8435 if (s
->condexec_mask
)
8436 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8438 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8441 store_reg(s
, rd
, tmp
);
8443 /* shift immediate */
8444 rm
= (insn
>> 3) & 7;
8445 shift
= (insn
>> 6) & 0x1f;
8446 tmp
= load_reg(s
, rm
);
8447 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8448 if (!s
->condexec_mask
)
8450 store_reg(s
, rd
, tmp
);
8454 /* arithmetic large immediate */
8455 op
= (insn
>> 11) & 3;
8456 rd
= (insn
>> 8) & 0x7;
8457 if (op
== 0) { /* mov */
8459 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8460 if (!s
->condexec_mask
)
8462 store_reg(s
, rd
, tmp
);
8464 tmp
= load_reg(s
, rd
);
8466 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8469 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8474 if (s
->condexec_mask
)
8475 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8477 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8479 store_reg(s
, rd
, tmp
);
8482 if (s
->condexec_mask
)
8483 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8485 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8487 store_reg(s
, rd
, tmp
);
8493 if (insn
& (1 << 11)) {
8494 rd
= (insn
>> 8) & 7;
8495 /* load pc-relative. Bit 1 of PC is ignored. */
8496 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8497 val
&= ~(uint32_t)2;
8499 tcg_gen_movi_i32(addr
, val
);
8500 tmp
= gen_ld32(addr
, IS_USER(s
));
8502 store_reg(s
, rd
, tmp
);
8505 if (insn
& (1 << 10)) {
8506 /* data processing extended or blx */
8507 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8508 rm
= (insn
>> 3) & 0xf;
8509 op
= (insn
>> 8) & 3;
8512 tmp
= load_reg(s
, rd
);
8513 tmp2
= load_reg(s
, rm
);
8514 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8516 store_reg(s
, rd
, tmp
);
8519 tmp
= load_reg(s
, rd
);
8520 tmp2
= load_reg(s
, rm
);
8521 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8525 case 2: /* mov/cpy */
8526 tmp
= load_reg(s
, rm
);
8527 store_reg(s
, rd
, tmp
);
8529 case 3:/* branch [and link] exchange thumb register */
8530 tmp
= load_reg(s
, rm
);
8531 if (insn
& (1 << 7)) {
8532 val
= (uint32_t)s
->pc
| 1;
8534 tcg_gen_movi_i32(tmp2
, val
);
8535 store_reg(s
, 14, tmp2
);
8543 /* data processing register */
8545 rm
= (insn
>> 3) & 7;
8546 op
= (insn
>> 6) & 0xf;
8547 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8548 /* the shift/rotate ops want the operands backwards */
8557 if (op
== 9) { /* neg */
8559 tcg_gen_movi_i32(tmp
, 0);
8560 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8561 tmp
= load_reg(s
, rd
);
8566 tmp2
= load_reg(s
, rm
);
8569 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8570 if (!s
->condexec_mask
)
8574 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8575 if (!s
->condexec_mask
)
8579 if (s
->condexec_mask
) {
8580 gen_helper_shl(tmp2
, tmp2
, tmp
);
8582 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8587 if (s
->condexec_mask
) {
8588 gen_helper_shr(tmp2
, tmp2
, tmp
);
8590 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8595 if (s
->condexec_mask
) {
8596 gen_helper_sar(tmp2
, tmp2
, tmp
);
8598 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8603 if (s
->condexec_mask
)
8606 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8609 if (s
->condexec_mask
)
8610 gen_sub_carry(tmp
, tmp
, tmp2
);
8612 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8615 if (s
->condexec_mask
) {
8616 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8617 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8619 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8624 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8629 if (s
->condexec_mask
)
8630 tcg_gen_neg_i32(tmp
, tmp2
);
8632 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8635 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8639 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8643 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8644 if (!s
->condexec_mask
)
8648 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8649 if (!s
->condexec_mask
)
8653 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8654 if (!s
->condexec_mask
)
8658 tcg_gen_not_i32(tmp2
, tmp2
);
8659 if (!s
->condexec_mask
)
8667 store_reg(s
, rm
, tmp2
);
8671 store_reg(s
, rd
, tmp
);
8681 /* load/store register offset. */
8683 rn
= (insn
>> 3) & 7;
8684 rm
= (insn
>> 6) & 7;
8685 op
= (insn
>> 9) & 7;
8686 addr
= load_reg(s
, rn
);
8687 tmp
= load_reg(s
, rm
);
8688 tcg_gen_add_i32(addr
, addr
, tmp
);
8691 if (op
< 3) /* store */
8692 tmp
= load_reg(s
, rd
);
8696 gen_st32(tmp
, addr
, IS_USER(s
));
8699 gen_st16(tmp
, addr
, IS_USER(s
));
8702 gen_st8(tmp
, addr
, IS_USER(s
));
8705 tmp
= gen_ld8s(addr
, IS_USER(s
));
8708 tmp
= gen_ld32(addr
, IS_USER(s
));
8711 tmp
= gen_ld16u(addr
, IS_USER(s
));
8714 tmp
= gen_ld8u(addr
, IS_USER(s
));
8717 tmp
= gen_ld16s(addr
, IS_USER(s
));
8720 if (op
>= 3) /* load */
8721 store_reg(s
, rd
, tmp
);
8726 /* load/store word immediate offset */
8728 rn
= (insn
>> 3) & 7;
8729 addr
= load_reg(s
, rn
);
8730 val
= (insn
>> 4) & 0x7c;
8731 tcg_gen_addi_i32(addr
, addr
, val
);
8733 if (insn
& (1 << 11)) {
8735 tmp
= gen_ld32(addr
, IS_USER(s
));
8736 store_reg(s
, rd
, tmp
);
8739 tmp
= load_reg(s
, rd
);
8740 gen_st32(tmp
, addr
, IS_USER(s
));
8746 /* load/store byte immediate offset */
8748 rn
= (insn
>> 3) & 7;
8749 addr
= load_reg(s
, rn
);
8750 val
= (insn
>> 6) & 0x1f;
8751 tcg_gen_addi_i32(addr
, addr
, val
);
8753 if (insn
& (1 << 11)) {
8755 tmp
= gen_ld8u(addr
, IS_USER(s
));
8756 store_reg(s
, rd
, tmp
);
8759 tmp
= load_reg(s
, rd
);
8760 gen_st8(tmp
, addr
, IS_USER(s
));
8766 /* load/store halfword immediate offset */
8768 rn
= (insn
>> 3) & 7;
8769 addr
= load_reg(s
, rn
);
8770 val
= (insn
>> 5) & 0x3e;
8771 tcg_gen_addi_i32(addr
, addr
, val
);
8773 if (insn
& (1 << 11)) {
8775 tmp
= gen_ld16u(addr
, IS_USER(s
));
8776 store_reg(s
, rd
, tmp
);
8779 tmp
= load_reg(s
, rd
);
8780 gen_st16(tmp
, addr
, IS_USER(s
));
8786 /* load/store from stack */
8787 rd
= (insn
>> 8) & 7;
8788 addr
= load_reg(s
, 13);
8789 val
= (insn
& 0xff) * 4;
8790 tcg_gen_addi_i32(addr
, addr
, val
);
8792 if (insn
& (1 << 11)) {
8794 tmp
= gen_ld32(addr
, IS_USER(s
));
8795 store_reg(s
, rd
, tmp
);
8798 tmp
= load_reg(s
, rd
);
8799 gen_st32(tmp
, addr
, IS_USER(s
));
8805 /* add to high reg */
8806 rd
= (insn
>> 8) & 7;
8807 if (insn
& (1 << 11)) {
8809 tmp
= load_reg(s
, 13);
8811 /* PC. bit 1 is ignored. */
8813 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8815 val
= (insn
& 0xff) * 4;
8816 tcg_gen_addi_i32(tmp
, tmp
, val
);
8817 store_reg(s
, rd
, tmp
);
8822 op
= (insn
>> 8) & 0xf;
8825 /* adjust stack pointer */
8826 tmp
= load_reg(s
, 13);
8827 val
= (insn
& 0x7f) * 4;
8828 if (insn
& (1 << 7))
8829 val
= -(int32_t)val
;
8830 tcg_gen_addi_i32(tmp
, tmp
, val
);
8831 store_reg(s
, 13, tmp
);
8834 case 2: /* sign/zero extend. */
8837 rm
= (insn
>> 3) & 7;
8838 tmp
= load_reg(s
, rm
);
8839 switch ((insn
>> 6) & 3) {
8840 case 0: gen_sxth(tmp
); break;
8841 case 1: gen_sxtb(tmp
); break;
8842 case 2: gen_uxth(tmp
); break;
8843 case 3: gen_uxtb(tmp
); break;
8845 store_reg(s
, rd
, tmp
);
8847 case 4: case 5: case 0xc: case 0xd:
8849 addr
= load_reg(s
, 13);
8850 if (insn
& (1 << 8))
8854 for (i
= 0; i
< 8; i
++) {
8855 if (insn
& (1 << i
))
8858 if ((insn
& (1 << 11)) == 0) {
8859 tcg_gen_addi_i32(addr
, addr
, -offset
);
8861 for (i
= 0; i
< 8; i
++) {
8862 if (insn
& (1 << i
)) {
8863 if (insn
& (1 << 11)) {
8865 tmp
= gen_ld32(addr
, IS_USER(s
));
8866 store_reg(s
, i
, tmp
);
8869 tmp
= load_reg(s
, i
);
8870 gen_st32(tmp
, addr
, IS_USER(s
));
8872 /* advance to the next address. */
8873 tcg_gen_addi_i32(addr
, addr
, 4);
8877 if (insn
& (1 << 8)) {
8878 if (insn
& (1 << 11)) {
8880 tmp
= gen_ld32(addr
, IS_USER(s
));
8881 /* don't set the pc until the rest of the instruction
8885 tmp
= load_reg(s
, 14);
8886 gen_st32(tmp
, addr
, IS_USER(s
));
8888 tcg_gen_addi_i32(addr
, addr
, 4);
8890 if ((insn
& (1 << 11)) == 0) {
8891 tcg_gen_addi_i32(addr
, addr
, -offset
);
8893 /* write back the new stack pointer */
8894 store_reg(s
, 13, addr
);
8895 /* set the new PC value */
8896 if ((insn
& 0x0900) == 0x0900)
8900 case 1: case 3: case 9: case 11: /* czb */
8902 tmp
= load_reg(s
, rm
);
8903 s
->condlabel
= gen_new_label();
8905 if (insn
& (1 << 11))
8906 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8908 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8910 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8911 val
= (uint32_t)s
->pc
+ 2;
8916 case 15: /* IT, nop-hint. */
8917 if ((insn
& 0xf) == 0) {
8918 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8922 s
->condexec_cond
= (insn
>> 4) & 0xe;
8923 s
->condexec_mask
= insn
& 0x1f;
8924 /* No actual code generated for this insn, just setup state. */
8927 case 0xe: /* bkpt */
8928 gen_set_condexec(s
);
8929 gen_set_pc_im(s
->pc
- 2);
8930 gen_exception(EXCP_BKPT
);
8931 s
->is_jmp
= DISAS_JUMP
;
8936 rn
= (insn
>> 3) & 0x7;
8938 tmp
= load_reg(s
, rn
);
8939 switch ((insn
>> 6) & 3) {
8940 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8941 case 1: gen_rev16(tmp
); break;
8942 case 3: gen_revsh(tmp
); break;
8943 default: goto illegal_op
;
8945 store_reg(s
, rd
, tmp
);
8953 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8956 addr
= tcg_const_i32(16);
8957 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8958 tcg_temp_free_i32(addr
);
8962 addr
= tcg_const_i32(17);
8963 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8964 tcg_temp_free_i32(addr
);
8966 tcg_temp_free_i32(tmp
);
8969 if (insn
& (1 << 4))
8970 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8973 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
8983 /* load/store multiple */
8984 rn
= (insn
>> 8) & 0x7;
8985 addr
= load_reg(s
, rn
);
8986 for (i
= 0; i
< 8; i
++) {
8987 if (insn
& (1 << i
)) {
8988 if (insn
& (1 << 11)) {
8990 tmp
= gen_ld32(addr
, IS_USER(s
));
8991 store_reg(s
, i
, tmp
);
8994 tmp
= load_reg(s
, i
);
8995 gen_st32(tmp
, addr
, IS_USER(s
));
8997 /* advance to the next address */
8998 tcg_gen_addi_i32(addr
, addr
, 4);
9001 /* Base register writeback. */
9002 if ((insn
& (1 << rn
)) == 0) {
9003 store_reg(s
, rn
, addr
);
9010 /* conditional branch or swi */
9011 cond
= (insn
>> 8) & 0xf;
9017 gen_set_condexec(s
);
9018 gen_set_pc_im(s
->pc
);
9019 s
->is_jmp
= DISAS_SWI
;
9022 /* generate a conditional jump to next instruction */
9023 s
->condlabel
= gen_new_label();
9024 gen_test_cc(cond
^ 1, s
->condlabel
);
9027 /* jump to the offset */
9028 val
= (uint32_t)s
->pc
+ 2;
9029 offset
= ((int32_t)insn
<< 24) >> 24;
9035 if (insn
& (1 << 11)) {
9036 if (disas_thumb2_insn(env
, s
, insn
))
9040 /* unconditional branch */
9041 val
= (uint32_t)s
->pc
;
9042 offset
= ((int32_t)insn
<< 21) >> 21;
9043 val
+= (offset
<< 1) + 2;
9048 if (disas_thumb2_insn(env
, s
, insn
))
9054 gen_set_condexec(s
);
9055 gen_set_pc_im(s
->pc
- 4);
9056 gen_exception(EXCP_UDEF
);
9057 s
->is_jmp
= DISAS_JUMP
;
9061 gen_set_condexec(s
);
9062 gen_set_pc_im(s
->pc
- 2);
9063 gen_exception(EXCP_UDEF
);
9064 s
->is_jmp
= DISAS_JUMP
;
9067 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9068 basic block 'tb'. If search_pc is TRUE, also generate PC
9069 information for each intermediate instruction. */
9070 static inline void gen_intermediate_code_internal(CPUState
*env
,
9071 TranslationBlock
*tb
,
9074 DisasContext dc1
, *dc
= &dc1
;
9076 uint16_t *gen_opc_end
;
9078 target_ulong pc_start
;
9079 uint32_t next_page_start
;
9083 /* generate intermediate code */
9090 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
9092 dc
->is_jmp
= DISAS_NEXT
;
9094 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9096 dc
->thumb
= env
->thumb
;
9097 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
9098 dc
->condexec_cond
= env
->condexec_bits
>> 4;
9099 #if !defined(CONFIG_USER_ONLY)
9101 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
9103 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
9106 cpu_F0s
= tcg_temp_new_i32();
9107 cpu_F1s
= tcg_temp_new_i32();
9108 cpu_F0d
= tcg_temp_new_i64();
9109 cpu_F1d
= tcg_temp_new_i64();
9112 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9113 cpu_M0
= tcg_temp_new_i64();
9114 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9117 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9119 max_insns
= CF_COUNT_MASK
;
9122 /* Reset the conditional execution bits immediately. This avoids
9123 complications trying to do it at the end of the block. */
9124 if (env
->condexec_bits
)
9126 TCGv tmp
= new_tmp();
9127 tcg_gen_movi_i32(tmp
, 0);
9128 store_cpu_field(tmp
, condexec_bits
);
9131 #ifdef CONFIG_USER_ONLY
9132 /* Intercept jump to the magic kernel page. */
9133 if (dc
->pc
>= 0xffff0000) {
9134 /* We always get here via a jump, so know we are not in a
9135 conditional execution block. */
9136 gen_exception(EXCP_KERNEL_TRAP
);
9137 dc
->is_jmp
= DISAS_UPDATE
;
9141 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9142 /* We always get here via a jump, so know we are not in a
9143 conditional execution block. */
9144 gen_exception(EXCP_EXCEPTION_EXIT
);
9145 dc
->is_jmp
= DISAS_UPDATE
;
9150 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9151 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9152 if (bp
->pc
== dc
->pc
) {
9153 gen_set_condexec(dc
);
9154 gen_set_pc_im(dc
->pc
);
9155 gen_exception(EXCP_DEBUG
);
9156 dc
->is_jmp
= DISAS_JUMP
;
9157 /* Advance PC so that clearing the breakpoint will
9158 invalidate this TB. */
9160 goto done_generating
;
9166 j
= gen_opc_ptr
- gen_opc_buf
;
9170 gen_opc_instr_start
[lj
++] = 0;
9172 gen_opc_pc
[lj
] = dc
->pc
;
9173 gen_opc_instr_start
[lj
] = 1;
9174 gen_opc_icount
[lj
] = num_insns
;
9177 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9181 disas_thumb_insn(env
, dc
);
9182 if (dc
->condexec_mask
) {
9183 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9184 | ((dc
->condexec_mask
>> 4) & 1);
9185 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9186 if (dc
->condexec_mask
== 0) {
9187 dc
->condexec_cond
= 0;
9191 disas_arm_insn(env
, dc
);
9194 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
9198 if (dc
->condjmp
&& !dc
->is_jmp
) {
9199 gen_set_label(dc
->condlabel
);
9202 /* Translation stops when a conditional branch is encountered.
9203 * Otherwise the subsequent code could get translated several times.
9204 * Also stop translation when a page boundary is reached. This
9205 * ensures prefetch aborts occur at the right place. */
9207 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9208 !env
->singlestep_enabled
&&
9210 dc
->pc
< next_page_start
&&
9211 num_insns
< max_insns
);
9213 if (tb
->cflags
& CF_LAST_IO
) {
9215 /* FIXME: This can theoretically happen with self-modifying
9217 cpu_abort(env
, "IO on conditional branch instruction");
9222 /* At this stage dc->condjmp will only be set when the skipped
9223 instruction was a conditional branch or trap, and the PC has
9224 already been written. */
9225 if (unlikely(env
->singlestep_enabled
)) {
9226 /* Make sure the pc is updated, and raise a debug exception. */
9228 gen_set_condexec(dc
);
9229 if (dc
->is_jmp
== DISAS_SWI
) {
9230 gen_exception(EXCP_SWI
);
9232 gen_exception(EXCP_DEBUG
);
9234 gen_set_label(dc
->condlabel
);
9236 if (dc
->condjmp
|| !dc
->is_jmp
) {
9237 gen_set_pc_im(dc
->pc
);
9240 gen_set_condexec(dc
);
9241 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9242 gen_exception(EXCP_SWI
);
9244 /* FIXME: Single stepping a WFI insn will not halt
9246 gen_exception(EXCP_DEBUG
);
9249 /* While branches must always occur at the end of an IT block,
9250 there are a few other things that can cause us to terminate
9251 the TB in the middel of an IT block:
9252 - Exception generating instructions (bkpt, swi, undefined).
9254 - Hardware watchpoints.
9255 Hardware breakpoints have already been handled and skip this code.
9257 gen_set_condexec(dc
);
9258 switch(dc
->is_jmp
) {
9260 gen_goto_tb(dc
, 1, dc
->pc
);
9265 /* indicate that the hash table must be used to find the next TB */
9269 /* nothing more to generate */
9275 gen_exception(EXCP_SWI
);
9279 gen_set_label(dc
->condlabel
);
9280 gen_set_condexec(dc
);
9281 gen_goto_tb(dc
, 1, dc
->pc
);
9287 gen_icount_end(tb
, num_insns
);
9288 *gen_opc_ptr
= INDEX_op_end
;
9291 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9292 qemu_log("----------------\n");
9293 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9294 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9299 j
= gen_opc_ptr
- gen_opc_buf
;
9302 gen_opc_instr_start
[lj
++] = 0;
9304 tb
->size
= dc
->pc
- pc_start
;
9305 tb
->icount
= num_insns
;
9309 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9311 gen_intermediate_code_internal(env
, tb
, 0);
9314 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9316 gen_intermediate_code_internal(env
, tb
, 1);
9319 static const char *cpu_mode_names
[16] = {
9320 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9321 "???", "???", "???", "und", "???", "???", "???", "sys"
9324 void cpu_dump_state(CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
9334 /* ??? This assumes float64 and double have the same layout.
9335 Oh well, it's only debug dumps. */
9344 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9346 cpu_fprintf(f
, "\n");
9348 cpu_fprintf(f
, " ");
9350 psr
= cpsr_read(env
);
9351 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9353 psr
& (1 << 31) ? 'N' : '-',
9354 psr
& (1 << 30) ? 'Z' : '-',
9355 psr
& (1 << 29) ? 'C' : '-',
9356 psr
& (1 << 28) ? 'V' : '-',
9357 psr
& CPSR_T
? 'T' : 'A',
9358 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9361 for (i
= 0; i
< 16; i
++) {
9362 d
.d
= env
->vfp
.regs
[i
];
9366 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9367 i
* 2, (int)s0
.i
, s0
.s
,
9368 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9369 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9372 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9376 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9377 unsigned long searched_pc
, int pc_pos
, void *puc
)
9379 env
->regs
[15] = gen_opc_pc
[pc_pos
];