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 /* Round the top 32 bits of a 64-bit value. */
291 static void gen_roundqd(TCGv a
, TCGv b
)
293 tcg_gen_shri_i32(a
, a
, 31);
294 tcg_gen_add_i32(a
, a
, b
);
297 /* FIXME: Most targets have native widening multiplication.
298 It would be good to use that instead of a full wide multiply. */
299 /* 32x32->64 multiply. Marks inputs as dead. */
300 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
302 TCGv_i64 tmp1
= tcg_temp_new_i64();
303 TCGv_i64 tmp2
= tcg_temp_new_i64();
305 tcg_gen_extu_i32_i64(tmp1
, a
);
307 tcg_gen_extu_i32_i64(tmp2
, b
);
309 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
310 tcg_temp_free_i64(tmp2
);
314 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1
, a
);
321 tcg_gen_ext_i32_i64(tmp2
, b
);
323 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
324 tcg_temp_free_i64(tmp2
);
328 /* Signed 32x32->64 multiply. */
329 static void gen_imull(TCGv a
, TCGv b
)
331 TCGv_i64 tmp1
= tcg_temp_new_i64();
332 TCGv_i64 tmp2
= tcg_temp_new_i64();
334 tcg_gen_ext_i32_i64(tmp1
, a
);
335 tcg_gen_ext_i32_i64(tmp2
, b
);
336 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
337 tcg_temp_free_i64(tmp2
);
338 tcg_gen_trunc_i64_i32(a
, tmp1
);
339 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
340 tcg_gen_trunc_i64_i32(b
, tmp1
);
341 tcg_temp_free_i64(tmp1
);
344 /* Swap low and high halfwords. */
345 static void gen_swap_half(TCGv var
)
347 TCGv tmp
= new_tmp();
348 tcg_gen_shri_i32(tmp
, var
, 16);
349 tcg_gen_shli_i32(var
, var
, 16);
350 tcg_gen_or_i32(var
, var
, tmp
);
354 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
355 tmp = (t0 ^ t1) & 0x8000;
358 t0 = (t0 + t1) ^ tmp;
361 static void gen_add16(TCGv t0
, TCGv t1
)
363 TCGv tmp
= new_tmp();
364 tcg_gen_xor_i32(tmp
, t0
, t1
);
365 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
366 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
367 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
368 tcg_gen_add_i32(t0
, t0
, t1
);
369 tcg_gen_xor_i32(t0
, t0
, tmp
);
374 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
376 /* Set CF to the top bit of var. */
377 static void gen_set_CF_bit31(TCGv var
)
379 TCGv tmp
= new_tmp();
380 tcg_gen_shri_i32(tmp
, var
, 31);
385 /* Set N and Z flags from var. */
386 static inline void gen_logic_CC(TCGv var
)
388 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
389 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
393 static void gen_adc(TCGv t0
, TCGv t1
)
396 tcg_gen_add_i32(t0
, t0
, t1
);
397 tmp
= load_cpu_field(CF
);
398 tcg_gen_add_i32(t0
, t0
, tmp
);
402 /* dest = T0 + T1 + CF. */
403 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
406 tcg_gen_add_i32(dest
, t0
, t1
);
407 tmp
= load_cpu_field(CF
);
408 tcg_gen_add_i32(dest
, dest
, tmp
);
412 /* dest = T0 - T1 + CF - 1. */
413 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
416 tcg_gen_sub_i32(dest
, t0
, t1
);
417 tmp
= load_cpu_field(CF
);
418 tcg_gen_add_i32(dest
, dest
, tmp
);
419 tcg_gen_subi_i32(dest
, dest
, 1);
423 /* FIXME: Implement this natively. */
424 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
426 static void shifter_out_im(TCGv var
, int shift
)
428 TCGv tmp
= new_tmp();
430 tcg_gen_andi_i32(tmp
, var
, 1);
432 tcg_gen_shri_i32(tmp
, var
, shift
);
434 tcg_gen_andi_i32(tmp
, tmp
, 1);
440 /* Shift by immediate. Includes special handling for shift == 0. */
441 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
447 shifter_out_im(var
, 32 - shift
);
448 tcg_gen_shli_i32(var
, var
, shift
);
454 tcg_gen_shri_i32(var
, var
, 31);
457 tcg_gen_movi_i32(var
, 0);
460 shifter_out_im(var
, shift
- 1);
461 tcg_gen_shri_i32(var
, var
, shift
);
468 shifter_out_im(var
, shift
- 1);
471 tcg_gen_sari_i32(var
, var
, shift
);
473 case 3: /* ROR/RRX */
476 shifter_out_im(var
, shift
- 1);
477 tcg_gen_rotri_i32(var
, var
, shift
); break;
479 TCGv tmp
= load_cpu_field(CF
);
481 shifter_out_im(var
, 0);
482 tcg_gen_shri_i32(var
, var
, 1);
483 tcg_gen_shli_i32(tmp
, tmp
, 31);
484 tcg_gen_or_i32(var
, var
, tmp
);
490 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
491 TCGv shift
, int flags
)
495 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
496 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
497 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
498 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
502 case 0: gen_helper_shl(var
, var
, shift
); break;
503 case 1: gen_helper_shr(var
, var
, shift
); break;
504 case 2: gen_helper_sar(var
, var
, shift
); break;
505 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
506 tcg_gen_rotr_i32(var
, var
, shift
); break;
512 #define PAS_OP(pfx) \
514 case 0: gen_pas_helper(glue(pfx,add16)); break; \
515 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
516 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
517 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
518 case 4: gen_pas_helper(glue(pfx,add8)); break; \
519 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
521 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
526 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
528 tmp
= tcg_temp_new_ptr();
529 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
531 tcg_temp_free_ptr(tmp
);
534 tmp
= tcg_temp_new_ptr();
535 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
537 tcg_temp_free_ptr(tmp
);
539 #undef gen_pas_helper
540 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
553 #undef gen_pas_helper
558 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
559 #define PAS_OP(pfx) \
561 case 0: gen_pas_helper(glue(pfx,add8)); break; \
562 case 1: gen_pas_helper(glue(pfx,add16)); break; \
563 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
564 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
565 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
566 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
568 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
573 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
575 tmp
= tcg_temp_new_ptr();
576 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
578 tcg_temp_free_ptr(tmp
);
581 tmp
= tcg_temp_new_ptr();
582 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
584 tcg_temp_free_ptr(tmp
);
586 #undef gen_pas_helper
587 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
600 #undef gen_pas_helper
605 static void gen_test_cc(int cc
, int label
)
613 tmp
= load_cpu_field(ZF
);
614 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
617 tmp
= load_cpu_field(ZF
);
618 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
621 tmp
= load_cpu_field(CF
);
622 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
625 tmp
= load_cpu_field(CF
);
626 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
629 tmp
= load_cpu_field(NF
);
630 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
633 tmp
= load_cpu_field(NF
);
634 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
637 tmp
= load_cpu_field(VF
);
638 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
641 tmp
= load_cpu_field(VF
);
642 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
644 case 8: /* hi: C && !Z */
645 inv
= gen_new_label();
646 tmp
= load_cpu_field(CF
);
647 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
649 tmp
= load_cpu_field(ZF
);
650 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
653 case 9: /* ls: !C || Z */
654 tmp
= load_cpu_field(CF
);
655 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
657 tmp
= load_cpu_field(ZF
);
658 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
660 case 10: /* ge: N == V -> N ^ V == 0 */
661 tmp
= load_cpu_field(VF
);
662 tmp2
= load_cpu_field(NF
);
663 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
665 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
667 case 11: /* lt: N != V -> N ^ V != 0 */
668 tmp
= load_cpu_field(VF
);
669 tmp2
= load_cpu_field(NF
);
670 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
672 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
674 case 12: /* gt: !Z && N == V */
675 inv
= gen_new_label();
676 tmp
= load_cpu_field(ZF
);
677 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
679 tmp
= load_cpu_field(VF
);
680 tmp2
= load_cpu_field(NF
);
681 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
683 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
686 case 13: /* le: Z || N != V */
687 tmp
= load_cpu_field(ZF
);
688 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
690 tmp
= load_cpu_field(VF
);
691 tmp2
= load_cpu_field(NF
);
692 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
694 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
697 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
703 static const uint8_t table_logic_cc
[16] = {
722 /* Set PC and Thumb state from an immediate address. */
723 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
727 s
->is_jmp
= DISAS_UPDATE
;
728 if (s
->thumb
!= (addr
& 1)) {
730 tcg_gen_movi_i32(tmp
, addr
& 1);
731 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
734 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
737 /* Set PC and Thumb state from var. var is marked as dead. */
738 static inline void gen_bx(DisasContext
*s
, TCGv var
)
740 s
->is_jmp
= DISAS_UPDATE
;
741 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
742 tcg_gen_andi_i32(var
, var
, 1);
743 store_cpu_field(var
, thumb
);
746 /* Variant of store_reg which uses branch&exchange logic when storing
747 to r15 in ARM architecture v7 and above. The source must be a temporary
748 and will be marked as dead. */
749 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
752 if (reg
== 15 && ENABLE_ARCH_7
) {
755 store_reg(s
, reg
, var
);
759 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
761 TCGv tmp
= new_tmp();
762 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
765 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
767 TCGv tmp
= new_tmp();
768 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
771 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
773 TCGv tmp
= new_tmp();
774 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
777 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
779 TCGv tmp
= new_tmp();
780 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
783 static inline TCGv
gen_ld32(TCGv addr
, int index
)
785 TCGv tmp
= new_tmp();
786 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
789 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
791 TCGv_i64 tmp
= tcg_temp_new_i64();
792 tcg_gen_qemu_ld64(tmp
, addr
, index
);
795 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
797 tcg_gen_qemu_st8(val
, addr
, index
);
800 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
802 tcg_gen_qemu_st16(val
, addr
, index
);
805 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
807 tcg_gen_qemu_st32(val
, addr
, index
);
810 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
812 tcg_gen_qemu_st64(val
, addr
, index
);
813 tcg_temp_free_i64(val
);
816 static inline void gen_set_pc_im(uint32_t val
)
818 tcg_gen_movi_i32(cpu_R
[15], val
);
821 /* Force a TB lookup after an instruction that changes the CPU state. */
822 static inline void gen_lookup_tb(DisasContext
*s
)
824 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
825 s
->is_jmp
= DISAS_UPDATE
;
828 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
831 int val
, rm
, shift
, shiftop
;
834 if (!(insn
& (1 << 25))) {
837 if (!(insn
& (1 << 23)))
840 tcg_gen_addi_i32(var
, var
, val
);
844 shift
= (insn
>> 7) & 0x1f;
845 shiftop
= (insn
>> 5) & 3;
846 offset
= load_reg(s
, rm
);
847 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
848 if (!(insn
& (1 << 23)))
849 tcg_gen_sub_i32(var
, var
, offset
);
851 tcg_gen_add_i32(var
, var
, offset
);
856 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
862 if (insn
& (1 << 22)) {
864 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
865 if (!(insn
& (1 << 23)))
869 tcg_gen_addi_i32(var
, var
, val
);
873 tcg_gen_addi_i32(var
, var
, extra
);
875 offset
= load_reg(s
, rm
);
876 if (!(insn
& (1 << 23)))
877 tcg_gen_sub_i32(var
, var
, offset
);
879 tcg_gen_add_i32(var
, var
, offset
);
884 #define VFP_OP2(name) \
885 static inline void gen_vfp_##name(int dp) \
888 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
890 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
900 static inline void gen_vfp_abs(int dp
)
903 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
905 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
908 static inline void gen_vfp_neg(int dp
)
911 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
913 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
916 static inline void gen_vfp_sqrt(int dp
)
919 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
921 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
924 static inline void gen_vfp_cmp(int dp
)
927 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
929 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
932 static inline void gen_vfp_cmpe(int dp
)
935 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
937 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
940 static inline void gen_vfp_F1_ld0(int dp
)
943 tcg_gen_movi_i64(cpu_F1d
, 0);
945 tcg_gen_movi_i32(cpu_F1s
, 0);
948 static inline void gen_vfp_uito(int dp
)
951 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
953 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
956 static inline void gen_vfp_sito(int dp
)
959 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
961 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
964 static inline void gen_vfp_toui(int dp
)
967 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
969 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
972 static inline void gen_vfp_touiz(int dp
)
975 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
977 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
980 static inline void gen_vfp_tosi(int dp
)
983 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
985 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
988 static inline void gen_vfp_tosiz(int dp
)
991 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
993 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
996 #define VFP_GEN_FIX(name) \
997 static inline void gen_vfp_##name(int dp, int shift) \
999 TCGv tmp_shift = tcg_const_i32(shift); \
1001 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1003 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1004 tcg_temp_free_i32(tmp_shift); \
1016 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1019 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1021 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1024 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1027 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1029 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1033 vfp_reg_offset (int dp
, int reg
)
1036 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1038 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1039 + offsetof(CPU_DoubleU
, l
.upper
);
1041 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1042 + offsetof(CPU_DoubleU
, l
.lower
);
1046 /* Return the offset of a 32-bit piece of a NEON register.
1047 zero is the least significant end of the register. */
1049 neon_reg_offset (int reg
, int n
)
1053 return vfp_reg_offset(0, sreg
);
1056 static TCGv
neon_load_reg(int reg
, int pass
)
1058 TCGv tmp
= new_tmp();
1059 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1063 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1065 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1069 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1071 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1074 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1076 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1079 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1080 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1081 #define tcg_gen_st_f32 tcg_gen_st_i32
1082 #define tcg_gen_st_f64 tcg_gen_st_i64
1084 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1087 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1089 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1092 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1095 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1097 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1100 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1103 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1105 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1108 #define ARM_CP_RW_BIT (1 << 20)
1110 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1112 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1115 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1117 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1120 static inline TCGv
iwmmxt_load_creg(int reg
)
1122 TCGv var
= new_tmp();
1123 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1127 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1129 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1133 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1135 iwmmxt_store_reg(cpu_M0
, rn
);
1138 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1140 iwmmxt_load_reg(cpu_M0
, rn
);
1143 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1145 iwmmxt_load_reg(cpu_V1
, rn
);
1146 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1149 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1151 iwmmxt_load_reg(cpu_V1
, rn
);
1152 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1155 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1157 iwmmxt_load_reg(cpu_V1
, rn
);
1158 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1161 #define IWMMXT_OP(name) \
1162 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1164 iwmmxt_load_reg(cpu_V1, rn); \
1165 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1168 #define IWMMXT_OP_ENV(name) \
1169 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1171 iwmmxt_load_reg(cpu_V1, rn); \
1172 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1175 #define IWMMXT_OP_ENV_SIZE(name) \
1176 IWMMXT_OP_ENV(name##b) \
1177 IWMMXT_OP_ENV(name##w) \
1178 IWMMXT_OP_ENV(name##l)
1180 #define IWMMXT_OP_ENV1(name) \
1181 static inline void gen_op_iwmmxt_##name##_M0(void) \
1183 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1197 IWMMXT_OP_ENV_SIZE(unpackl
)
1198 IWMMXT_OP_ENV_SIZE(unpackh
)
1200 IWMMXT_OP_ENV1(unpacklub
)
1201 IWMMXT_OP_ENV1(unpackluw
)
1202 IWMMXT_OP_ENV1(unpacklul
)
1203 IWMMXT_OP_ENV1(unpackhub
)
1204 IWMMXT_OP_ENV1(unpackhuw
)
1205 IWMMXT_OP_ENV1(unpackhul
)
1206 IWMMXT_OP_ENV1(unpacklsb
)
1207 IWMMXT_OP_ENV1(unpacklsw
)
1208 IWMMXT_OP_ENV1(unpacklsl
)
1209 IWMMXT_OP_ENV1(unpackhsb
)
1210 IWMMXT_OP_ENV1(unpackhsw
)
1211 IWMMXT_OP_ENV1(unpackhsl
)
1213 IWMMXT_OP_ENV_SIZE(cmpeq
)
1214 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1215 IWMMXT_OP_ENV_SIZE(cmpgts
)
1217 IWMMXT_OP_ENV_SIZE(mins
)
1218 IWMMXT_OP_ENV_SIZE(minu
)
1219 IWMMXT_OP_ENV_SIZE(maxs
)
1220 IWMMXT_OP_ENV_SIZE(maxu
)
1222 IWMMXT_OP_ENV_SIZE(subn
)
1223 IWMMXT_OP_ENV_SIZE(addn
)
1224 IWMMXT_OP_ENV_SIZE(subu
)
1225 IWMMXT_OP_ENV_SIZE(addu
)
1226 IWMMXT_OP_ENV_SIZE(subs
)
1227 IWMMXT_OP_ENV_SIZE(adds
)
1229 IWMMXT_OP_ENV(avgb0
)
1230 IWMMXT_OP_ENV(avgb1
)
1231 IWMMXT_OP_ENV(avgw0
)
1232 IWMMXT_OP_ENV(avgw1
)
1236 IWMMXT_OP_ENV(packuw
)
1237 IWMMXT_OP_ENV(packul
)
1238 IWMMXT_OP_ENV(packuq
)
1239 IWMMXT_OP_ENV(packsw
)
1240 IWMMXT_OP_ENV(packsl
)
1241 IWMMXT_OP_ENV(packsq
)
1243 static void gen_op_iwmmxt_set_mup(void)
1246 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1247 tcg_gen_ori_i32(tmp
, tmp
, 2);
1248 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1251 static void gen_op_iwmmxt_set_cup(void)
1254 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1255 tcg_gen_ori_i32(tmp
, tmp
, 1);
1256 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1259 static void gen_op_iwmmxt_setpsr_nz(void)
1261 TCGv tmp
= new_tmp();
1262 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1263 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1266 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1268 iwmmxt_load_reg(cpu_V1
, rn
);
1269 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1270 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1273 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1279 rd
= (insn
>> 16) & 0xf;
1280 tmp
= load_reg(s
, rd
);
1282 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1283 if (insn
& (1 << 24)) {
1285 if (insn
& (1 << 23))
1286 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1288 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1289 tcg_gen_mov_i32(dest
, tmp
);
1290 if (insn
& (1 << 21))
1291 store_reg(s
, rd
, tmp
);
1294 } else if (insn
& (1 << 21)) {
1296 tcg_gen_mov_i32(dest
, tmp
);
1297 if (insn
& (1 << 23))
1298 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1300 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1301 store_reg(s
, rd
, tmp
);
1302 } else if (!(insn
& (1 << 23)))
1307 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1309 int rd
= (insn
>> 0) & 0xf;
1312 if (insn
& (1 << 8)) {
1313 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1316 tmp
= iwmmxt_load_creg(rd
);
1320 iwmmxt_load_reg(cpu_V0
, rd
);
1321 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1323 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1324 tcg_gen_mov_i32(dest
, tmp
);
1329 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1330 (ie. an undefined instruction). */
1331 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1334 int rdhi
, rdlo
, rd0
, rd1
, i
;
1336 TCGv tmp
, tmp2
, tmp3
;
1338 if ((insn
& 0x0e000e00) == 0x0c000000) {
1339 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1341 rdlo
= (insn
>> 12) & 0xf;
1342 rdhi
= (insn
>> 16) & 0xf;
1343 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1344 iwmmxt_load_reg(cpu_V0
, wrd
);
1345 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1346 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1347 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1348 } else { /* TMCRR */
1349 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1350 iwmmxt_store_reg(cpu_V0
, wrd
);
1351 gen_op_iwmmxt_set_mup();
1356 wrd
= (insn
>> 12) & 0xf;
1358 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1362 if (insn
& ARM_CP_RW_BIT
) {
1363 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1365 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1366 iwmmxt_store_creg(wrd
, tmp
);
1369 if (insn
& (1 << 8)) {
1370 if (insn
& (1 << 22)) { /* WLDRD */
1371 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1373 } else { /* WLDRW wRd */
1374 tmp
= gen_ld32(addr
, IS_USER(s
));
1377 if (insn
& (1 << 22)) { /* WLDRH */
1378 tmp
= gen_ld16u(addr
, IS_USER(s
));
1379 } else { /* WLDRB */
1380 tmp
= gen_ld8u(addr
, IS_USER(s
));
1384 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1387 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1390 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1391 tmp
= iwmmxt_load_creg(wrd
);
1392 gen_st32(tmp
, addr
, IS_USER(s
));
1394 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1396 if (insn
& (1 << 8)) {
1397 if (insn
& (1 << 22)) { /* WSTRD */
1399 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1400 } else { /* WSTRW wRd */
1401 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1402 gen_st32(tmp
, addr
, IS_USER(s
));
1405 if (insn
& (1 << 22)) { /* WSTRH */
1406 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1407 gen_st16(tmp
, addr
, IS_USER(s
));
1408 } else { /* WSTRB */
1409 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1410 gen_st8(tmp
, addr
, IS_USER(s
));
1419 if ((insn
& 0x0f000000) != 0x0e000000)
1422 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1423 case 0x000: /* WOR */
1424 wrd
= (insn
>> 12) & 0xf;
1425 rd0
= (insn
>> 0) & 0xf;
1426 rd1
= (insn
>> 16) & 0xf;
1427 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1428 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1429 gen_op_iwmmxt_setpsr_nz();
1430 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1431 gen_op_iwmmxt_set_mup();
1432 gen_op_iwmmxt_set_cup();
1434 case 0x011: /* TMCR */
1437 rd
= (insn
>> 12) & 0xf;
1438 wrd
= (insn
>> 16) & 0xf;
1440 case ARM_IWMMXT_wCID
:
1441 case ARM_IWMMXT_wCASF
:
1443 case ARM_IWMMXT_wCon
:
1444 gen_op_iwmmxt_set_cup();
1446 case ARM_IWMMXT_wCSSF
:
1447 tmp
= iwmmxt_load_creg(wrd
);
1448 tmp2
= load_reg(s
, rd
);
1449 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1451 iwmmxt_store_creg(wrd
, tmp
);
1453 case ARM_IWMMXT_wCGR0
:
1454 case ARM_IWMMXT_wCGR1
:
1455 case ARM_IWMMXT_wCGR2
:
1456 case ARM_IWMMXT_wCGR3
:
1457 gen_op_iwmmxt_set_cup();
1458 tmp
= load_reg(s
, rd
);
1459 iwmmxt_store_creg(wrd
, tmp
);
1465 case 0x100: /* WXOR */
1466 wrd
= (insn
>> 12) & 0xf;
1467 rd0
= (insn
>> 0) & 0xf;
1468 rd1
= (insn
>> 16) & 0xf;
1469 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1470 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1471 gen_op_iwmmxt_setpsr_nz();
1472 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1473 gen_op_iwmmxt_set_mup();
1474 gen_op_iwmmxt_set_cup();
1476 case 0x111: /* TMRC */
1479 rd
= (insn
>> 12) & 0xf;
1480 wrd
= (insn
>> 16) & 0xf;
1481 tmp
= iwmmxt_load_creg(wrd
);
1482 store_reg(s
, rd
, tmp
);
1484 case 0x300: /* WANDN */
1485 wrd
= (insn
>> 12) & 0xf;
1486 rd0
= (insn
>> 0) & 0xf;
1487 rd1
= (insn
>> 16) & 0xf;
1488 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1489 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1490 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1491 gen_op_iwmmxt_setpsr_nz();
1492 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1493 gen_op_iwmmxt_set_mup();
1494 gen_op_iwmmxt_set_cup();
1496 case 0x200: /* WAND */
1497 wrd
= (insn
>> 12) & 0xf;
1498 rd0
= (insn
>> 0) & 0xf;
1499 rd1
= (insn
>> 16) & 0xf;
1500 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1501 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1502 gen_op_iwmmxt_setpsr_nz();
1503 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1504 gen_op_iwmmxt_set_mup();
1505 gen_op_iwmmxt_set_cup();
1507 case 0x810: case 0xa10: /* WMADD */
1508 wrd
= (insn
>> 12) & 0xf;
1509 rd0
= (insn
>> 0) & 0xf;
1510 rd1
= (insn
>> 16) & 0xf;
1511 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1512 if (insn
& (1 << 21))
1513 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1515 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1516 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1517 gen_op_iwmmxt_set_mup();
1519 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1520 wrd
= (insn
>> 12) & 0xf;
1521 rd0
= (insn
>> 16) & 0xf;
1522 rd1
= (insn
>> 0) & 0xf;
1523 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1524 switch ((insn
>> 22) & 3) {
1526 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1529 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1532 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1537 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1538 gen_op_iwmmxt_set_mup();
1539 gen_op_iwmmxt_set_cup();
1541 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1542 wrd
= (insn
>> 12) & 0xf;
1543 rd0
= (insn
>> 16) & 0xf;
1544 rd1
= (insn
>> 0) & 0xf;
1545 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1546 switch ((insn
>> 22) & 3) {
1548 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1551 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1554 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1559 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1560 gen_op_iwmmxt_set_mup();
1561 gen_op_iwmmxt_set_cup();
1563 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1564 wrd
= (insn
>> 12) & 0xf;
1565 rd0
= (insn
>> 16) & 0xf;
1566 rd1
= (insn
>> 0) & 0xf;
1567 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1568 if (insn
& (1 << 22))
1569 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1571 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1572 if (!(insn
& (1 << 20)))
1573 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1574 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1575 gen_op_iwmmxt_set_mup();
1577 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1578 wrd
= (insn
>> 12) & 0xf;
1579 rd0
= (insn
>> 16) & 0xf;
1580 rd1
= (insn
>> 0) & 0xf;
1581 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1582 if (insn
& (1 << 21)) {
1583 if (insn
& (1 << 20))
1584 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1586 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1588 if (insn
& (1 << 20))
1589 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1591 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1593 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1594 gen_op_iwmmxt_set_mup();
1596 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1597 wrd
= (insn
>> 12) & 0xf;
1598 rd0
= (insn
>> 16) & 0xf;
1599 rd1
= (insn
>> 0) & 0xf;
1600 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1601 if (insn
& (1 << 21))
1602 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1604 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1605 if (!(insn
& (1 << 20))) {
1606 iwmmxt_load_reg(cpu_V1
, wrd
);
1607 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1609 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1610 gen_op_iwmmxt_set_mup();
1612 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1613 wrd
= (insn
>> 12) & 0xf;
1614 rd0
= (insn
>> 16) & 0xf;
1615 rd1
= (insn
>> 0) & 0xf;
1616 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1617 switch ((insn
>> 22) & 3) {
1619 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1622 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1625 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1630 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1631 gen_op_iwmmxt_set_mup();
1632 gen_op_iwmmxt_set_cup();
1634 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1635 wrd
= (insn
>> 12) & 0xf;
1636 rd0
= (insn
>> 16) & 0xf;
1637 rd1
= (insn
>> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1639 if (insn
& (1 << 22)) {
1640 if (insn
& (1 << 20))
1641 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1643 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1645 if (insn
& (1 << 20))
1646 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1648 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1650 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1651 gen_op_iwmmxt_set_mup();
1652 gen_op_iwmmxt_set_cup();
1654 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1655 wrd
= (insn
>> 12) & 0xf;
1656 rd0
= (insn
>> 16) & 0xf;
1657 rd1
= (insn
>> 0) & 0xf;
1658 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1659 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1660 tcg_gen_andi_i32(tmp
, tmp
, 7);
1661 iwmmxt_load_reg(cpu_V1
, rd1
);
1662 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1664 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1665 gen_op_iwmmxt_set_mup();
1667 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1668 if (((insn
>> 6) & 3) == 3)
1670 rd
= (insn
>> 12) & 0xf;
1671 wrd
= (insn
>> 16) & 0xf;
1672 tmp
= load_reg(s
, rd
);
1673 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1674 switch ((insn
>> 6) & 3) {
1676 tmp2
= tcg_const_i32(0xff);
1677 tmp3
= tcg_const_i32((insn
& 7) << 3);
1680 tmp2
= tcg_const_i32(0xffff);
1681 tmp3
= tcg_const_i32((insn
& 3) << 4);
1684 tmp2
= tcg_const_i32(0xffffffff);
1685 tmp3
= tcg_const_i32((insn
& 1) << 5);
1691 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1692 tcg_temp_free(tmp3
);
1693 tcg_temp_free(tmp2
);
1695 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1696 gen_op_iwmmxt_set_mup();
1698 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1699 rd
= (insn
>> 12) & 0xf;
1700 wrd
= (insn
>> 16) & 0xf;
1701 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1703 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1705 switch ((insn
>> 22) & 3) {
1707 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1708 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1710 tcg_gen_ext8s_i32(tmp
, tmp
);
1712 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1716 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1717 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1719 tcg_gen_ext16s_i32(tmp
, tmp
);
1721 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1725 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1726 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1729 store_reg(s
, rd
, tmp
);
1731 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1732 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1734 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1735 switch ((insn
>> 22) & 3) {
1737 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1740 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1743 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1746 tcg_gen_shli_i32(tmp
, tmp
, 28);
1750 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1751 if (((insn
>> 6) & 3) == 3)
1753 rd
= (insn
>> 12) & 0xf;
1754 wrd
= (insn
>> 16) & 0xf;
1755 tmp
= load_reg(s
, rd
);
1756 switch ((insn
>> 6) & 3) {
1758 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1761 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1764 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1768 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1769 gen_op_iwmmxt_set_mup();
1771 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1772 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1774 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1776 tcg_gen_mov_i32(tmp2
, tmp
);
1777 switch ((insn
>> 22) & 3) {
1779 for (i
= 0; i
< 7; i
++) {
1780 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1781 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1785 for (i
= 0; i
< 3; i
++) {
1786 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1787 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1791 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1792 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1799 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1800 wrd
= (insn
>> 12) & 0xf;
1801 rd0
= (insn
>> 16) & 0xf;
1802 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1803 switch ((insn
>> 22) & 3) {
1805 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1808 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1811 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1816 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1817 gen_op_iwmmxt_set_mup();
1819 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1820 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1822 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1824 tcg_gen_mov_i32(tmp2
, tmp
);
1825 switch ((insn
>> 22) & 3) {
1827 for (i
= 0; i
< 7; i
++) {
1828 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1829 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1833 for (i
= 0; i
< 3; i
++) {
1834 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1835 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1839 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1840 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1847 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1848 rd
= (insn
>> 12) & 0xf;
1849 rd0
= (insn
>> 16) & 0xf;
1850 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1852 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1854 switch ((insn
>> 22) & 3) {
1856 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1859 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1862 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1865 store_reg(s
, rd
, tmp
);
1867 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1868 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1869 wrd
= (insn
>> 12) & 0xf;
1870 rd0
= (insn
>> 16) & 0xf;
1871 rd1
= (insn
>> 0) & 0xf;
1872 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1873 switch ((insn
>> 22) & 3) {
1875 if (insn
& (1 << 21))
1876 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1878 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1881 if (insn
& (1 << 21))
1882 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1884 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1887 if (insn
& (1 << 21))
1888 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1890 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1895 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1896 gen_op_iwmmxt_set_mup();
1897 gen_op_iwmmxt_set_cup();
1899 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1900 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1901 wrd
= (insn
>> 12) & 0xf;
1902 rd0
= (insn
>> 16) & 0xf;
1903 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1904 switch ((insn
>> 22) & 3) {
1906 if (insn
& (1 << 21))
1907 gen_op_iwmmxt_unpacklsb_M0();
1909 gen_op_iwmmxt_unpacklub_M0();
1912 if (insn
& (1 << 21))
1913 gen_op_iwmmxt_unpacklsw_M0();
1915 gen_op_iwmmxt_unpackluw_M0();
1918 if (insn
& (1 << 21))
1919 gen_op_iwmmxt_unpacklsl_M0();
1921 gen_op_iwmmxt_unpacklul_M0();
1926 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1927 gen_op_iwmmxt_set_mup();
1928 gen_op_iwmmxt_set_cup();
1930 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1931 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1932 wrd
= (insn
>> 12) & 0xf;
1933 rd0
= (insn
>> 16) & 0xf;
1934 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1935 switch ((insn
>> 22) & 3) {
1937 if (insn
& (1 << 21))
1938 gen_op_iwmmxt_unpackhsb_M0();
1940 gen_op_iwmmxt_unpackhub_M0();
1943 if (insn
& (1 << 21))
1944 gen_op_iwmmxt_unpackhsw_M0();
1946 gen_op_iwmmxt_unpackhuw_M0();
1949 if (insn
& (1 << 21))
1950 gen_op_iwmmxt_unpackhsl_M0();
1952 gen_op_iwmmxt_unpackhul_M0();
1957 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1958 gen_op_iwmmxt_set_mup();
1959 gen_op_iwmmxt_set_cup();
1961 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1962 case 0x214: case 0x614: case 0xa14: case 0xe14:
1963 if (((insn
>> 22) & 3) == 0)
1965 wrd
= (insn
>> 12) & 0xf;
1966 rd0
= (insn
>> 16) & 0xf;
1967 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1969 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1973 switch ((insn
>> 22) & 3) {
1975 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1978 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1981 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1985 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1986 gen_op_iwmmxt_set_mup();
1987 gen_op_iwmmxt_set_cup();
1989 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1990 case 0x014: case 0x414: case 0x814: case 0xc14:
1991 if (((insn
>> 22) & 3) == 0)
1993 wrd
= (insn
>> 12) & 0xf;
1994 rd0
= (insn
>> 16) & 0xf;
1995 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1997 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2001 switch ((insn
>> 22) & 3) {
2003 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2006 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2009 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2013 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2014 gen_op_iwmmxt_set_mup();
2015 gen_op_iwmmxt_set_cup();
2017 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2018 case 0x114: case 0x514: case 0x914: case 0xd14:
2019 if (((insn
>> 22) & 3) == 0)
2021 wrd
= (insn
>> 12) & 0xf;
2022 rd0
= (insn
>> 16) & 0xf;
2023 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2025 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2029 switch ((insn
>> 22) & 3) {
2031 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2034 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2037 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2041 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2042 gen_op_iwmmxt_set_mup();
2043 gen_op_iwmmxt_set_cup();
2045 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2046 case 0x314: case 0x714: case 0xb14: case 0xf14:
2047 if (((insn
>> 22) & 3) == 0)
2049 wrd
= (insn
>> 12) & 0xf;
2050 rd0
= (insn
>> 16) & 0xf;
2051 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2053 switch ((insn
>> 22) & 3) {
2055 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2059 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2062 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2066 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2069 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2073 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2077 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2078 gen_op_iwmmxt_set_mup();
2079 gen_op_iwmmxt_set_cup();
2081 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2082 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2083 wrd
= (insn
>> 12) & 0xf;
2084 rd0
= (insn
>> 16) & 0xf;
2085 rd1
= (insn
>> 0) & 0xf;
2086 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2087 switch ((insn
>> 22) & 3) {
2089 if (insn
& (1 << 21))
2090 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2092 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2095 if (insn
& (1 << 21))
2096 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2098 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2101 if (insn
& (1 << 21))
2102 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2104 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2109 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2110 gen_op_iwmmxt_set_mup();
2112 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2113 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2114 wrd
= (insn
>> 12) & 0xf;
2115 rd0
= (insn
>> 16) & 0xf;
2116 rd1
= (insn
>> 0) & 0xf;
2117 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2118 switch ((insn
>> 22) & 3) {
2120 if (insn
& (1 << 21))
2121 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2123 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2126 if (insn
& (1 << 21))
2127 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2129 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2132 if (insn
& (1 << 21))
2133 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2135 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2140 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2141 gen_op_iwmmxt_set_mup();
2143 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2144 case 0x402: case 0x502: case 0x602: case 0x702:
2145 wrd
= (insn
>> 12) & 0xf;
2146 rd0
= (insn
>> 16) & 0xf;
2147 rd1
= (insn
>> 0) & 0xf;
2148 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2149 tmp
= tcg_const_i32((insn
>> 20) & 3);
2150 iwmmxt_load_reg(cpu_V1
, rd1
);
2151 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2153 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2154 gen_op_iwmmxt_set_mup();
2156 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2157 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2158 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2159 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2160 wrd
= (insn
>> 12) & 0xf;
2161 rd0
= (insn
>> 16) & 0xf;
2162 rd1
= (insn
>> 0) & 0xf;
2163 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2164 switch ((insn
>> 20) & 0xf) {
2166 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2169 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2172 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2175 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2178 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2181 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2184 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2187 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2190 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2195 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2196 gen_op_iwmmxt_set_mup();
2197 gen_op_iwmmxt_set_cup();
2199 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2200 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2201 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2202 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2203 wrd
= (insn
>> 12) & 0xf;
2204 rd0
= (insn
>> 16) & 0xf;
2205 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2206 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2207 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2209 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2210 gen_op_iwmmxt_set_mup();
2211 gen_op_iwmmxt_set_cup();
2213 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2214 case 0x418: case 0x518: case 0x618: case 0x718:
2215 case 0x818: case 0x918: case 0xa18: case 0xb18:
2216 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2217 wrd
= (insn
>> 12) & 0xf;
2218 rd0
= (insn
>> 16) & 0xf;
2219 rd1
= (insn
>> 0) & 0xf;
2220 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2221 switch ((insn
>> 20) & 0xf) {
2223 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2226 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2229 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2232 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2235 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2238 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2241 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2244 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2247 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2252 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2253 gen_op_iwmmxt_set_mup();
2254 gen_op_iwmmxt_set_cup();
2256 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2257 case 0x408: case 0x508: case 0x608: case 0x708:
2258 case 0x808: case 0x908: case 0xa08: case 0xb08:
2259 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2260 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2262 wrd
= (insn
>> 12) & 0xf;
2263 rd0
= (insn
>> 16) & 0xf;
2264 rd1
= (insn
>> 0) & 0xf;
2265 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2266 switch ((insn
>> 22) & 3) {
2268 if (insn
& (1 << 21))
2269 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2271 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2274 if (insn
& (1 << 21))
2275 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2277 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2280 if (insn
& (1 << 21))
2281 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2283 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2286 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2287 gen_op_iwmmxt_set_mup();
2288 gen_op_iwmmxt_set_cup();
2290 case 0x201: case 0x203: case 0x205: case 0x207:
2291 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2292 case 0x211: case 0x213: case 0x215: case 0x217:
2293 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2294 wrd
= (insn
>> 5) & 0xf;
2295 rd0
= (insn
>> 12) & 0xf;
2296 rd1
= (insn
>> 0) & 0xf;
2297 if (rd0
== 0xf || rd1
== 0xf)
2299 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2300 tmp
= load_reg(s
, rd0
);
2301 tmp2
= load_reg(s
, rd1
);
2302 switch ((insn
>> 16) & 0xf) {
2303 case 0x0: /* TMIA */
2304 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2306 case 0x8: /* TMIAPH */
2307 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2309 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2310 if (insn
& (1 << 16))
2311 tcg_gen_shri_i32(tmp
, tmp
, 16);
2312 if (insn
& (1 << 17))
2313 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2314 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2323 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2324 gen_op_iwmmxt_set_mup();
2333 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2334 (ie. an undefined instruction). */
2335 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2337 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2340 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2341 /* Multiply with Internal Accumulate Format */
2342 rd0
= (insn
>> 12) & 0xf;
2344 acc
= (insn
>> 5) & 7;
2349 tmp
= load_reg(s
, rd0
);
2350 tmp2
= load_reg(s
, rd1
);
2351 switch ((insn
>> 16) & 0xf) {
2353 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2355 case 0x8: /* MIAPH */
2356 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2358 case 0xc: /* MIABB */
2359 case 0xd: /* MIABT */
2360 case 0xe: /* MIATB */
2361 case 0xf: /* MIATT */
2362 if (insn
& (1 << 16))
2363 tcg_gen_shri_i32(tmp
, tmp
, 16);
2364 if (insn
& (1 << 17))
2365 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2366 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2374 gen_op_iwmmxt_movq_wRn_M0(acc
);
2378 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2379 /* Internal Accumulator Access Format */
2380 rdhi
= (insn
>> 16) & 0xf;
2381 rdlo
= (insn
>> 12) & 0xf;
2387 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2388 iwmmxt_load_reg(cpu_V0
, acc
);
2389 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2390 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2391 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2392 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2394 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2395 iwmmxt_store_reg(cpu_V0
, acc
);
2403 /* Disassemble system coprocessor instruction. Return nonzero if
2404 instruction is not defined. */
2405 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2408 uint32_t rd
= (insn
>> 12) & 0xf;
2409 uint32_t cp
= (insn
>> 8) & 0xf;
2414 if (insn
& ARM_CP_RW_BIT
) {
2415 if (!env
->cp
[cp
].cp_read
)
2417 gen_set_pc_im(s
->pc
);
2419 tmp2
= tcg_const_i32(insn
);
2420 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2421 tcg_temp_free(tmp2
);
2422 store_reg(s
, rd
, tmp
);
2424 if (!env
->cp
[cp
].cp_write
)
2426 gen_set_pc_im(s
->pc
);
2427 tmp
= load_reg(s
, rd
);
2428 tmp2
= tcg_const_i32(insn
);
2429 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2430 tcg_temp_free(tmp2
);
2436 static int cp15_user_ok(uint32_t insn
)
2438 int cpn
= (insn
>> 16) & 0xf;
2439 int cpm
= insn
& 0xf;
2440 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2442 if (cpn
== 13 && cpm
== 0) {
2444 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2448 /* ISB, DSB, DMB. */
2449 if ((cpm
== 5 && op
== 4)
2450 || (cpm
== 10 && (op
== 4 || op
== 5)))
2456 static int cp15_tls_load_store(CPUState
*env
, DisasContext
*s
, uint32_t insn
, uint32_t rd
)
2459 int cpn
= (insn
>> 16) & 0xf;
2460 int cpm
= insn
& 0xf;
2461 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2463 if (!arm_feature(env
, ARM_FEATURE_V6K
))
2466 if (!(cpn
== 13 && cpm
== 0))
2469 if (insn
& ARM_CP_RW_BIT
) {
2472 tmp
= load_cpu_field(cp15
.c13_tls1
);
2475 tmp
= load_cpu_field(cp15
.c13_tls2
);
2478 tmp
= load_cpu_field(cp15
.c13_tls3
);
2483 store_reg(s
, rd
, tmp
);
2486 tmp
= load_reg(s
, rd
);
2489 store_cpu_field(tmp
, cp15
.c13_tls1
);
2492 store_cpu_field(tmp
, cp15
.c13_tls2
);
2495 store_cpu_field(tmp
, cp15
.c13_tls3
);
2505 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2506 instruction is not defined. */
2507 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2512 /* M profile cores use memory mapped registers instead of cp15. */
2513 if (arm_feature(env
, ARM_FEATURE_M
))
2516 if ((insn
& (1 << 25)) == 0) {
2517 if (insn
& (1 << 20)) {
2521 /* mcrr. Used for block cache operations, so implement as no-op. */
2524 if ((insn
& (1 << 4)) == 0) {
2528 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2531 if ((insn
& 0x0fff0fff) == 0x0e070f90
2532 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2533 /* Wait for interrupt. */
2534 gen_set_pc_im(s
->pc
);
2535 s
->is_jmp
= DISAS_WFI
;
2538 rd
= (insn
>> 12) & 0xf;
2540 if (cp15_tls_load_store(env
, s
, insn
, rd
))
2543 tmp2
= tcg_const_i32(insn
);
2544 if (insn
& ARM_CP_RW_BIT
) {
2546 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2547 /* If the destination register is r15 then sets condition codes. */
2549 store_reg(s
, rd
, tmp
);
2553 tmp
= load_reg(s
, rd
);
2554 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2556 /* Normally we would always end the TB here, but Linux
2557 * arch/arm/mach-pxa/sleep.S expects two instructions following
2558 * an MMU enable to execute from cache. Imitate this behaviour. */
2559 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2560 (insn
& 0x0fff0fff) != 0x0e010f10)
2563 tcg_temp_free_i32(tmp2
);
2567 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2568 #define VFP_SREG(insn, bigbit, smallbit) \
2569 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2570 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2571 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2572 reg = (((insn) >> (bigbit)) & 0x0f) \
2573 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2575 if (insn & (1 << (smallbit))) \
2577 reg = ((insn) >> (bigbit)) & 0x0f; \
2580 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2581 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2582 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2583 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2584 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2585 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2587 /* Move between integer and VFP cores. */
2588 static TCGv
gen_vfp_mrs(void)
2590 TCGv tmp
= new_tmp();
2591 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2595 static void gen_vfp_msr(TCGv tmp
)
2597 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2602 vfp_enabled(CPUState
* env
)
2604 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2607 static void gen_neon_dup_u8(TCGv var
, int shift
)
2609 TCGv tmp
= new_tmp();
2611 tcg_gen_shri_i32(var
, var
, shift
);
2612 tcg_gen_ext8u_i32(var
, var
);
2613 tcg_gen_shli_i32(tmp
, var
, 8);
2614 tcg_gen_or_i32(var
, var
, tmp
);
2615 tcg_gen_shli_i32(tmp
, var
, 16);
2616 tcg_gen_or_i32(var
, var
, tmp
);
2620 static void gen_neon_dup_low16(TCGv var
)
2622 TCGv tmp
= new_tmp();
2623 tcg_gen_ext16u_i32(var
, var
);
2624 tcg_gen_shli_i32(tmp
, var
, 16);
2625 tcg_gen_or_i32(var
, var
, tmp
);
2629 static void gen_neon_dup_high16(TCGv var
)
2631 TCGv tmp
= new_tmp();
2632 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2633 tcg_gen_shri_i32(tmp
, var
, 16);
2634 tcg_gen_or_i32(var
, var
, tmp
);
2638 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2639 (ie. an undefined instruction). */
2640 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2642 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2648 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2651 if (!vfp_enabled(env
)) {
2652 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2653 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2655 rn
= (insn
>> 16) & 0xf;
2656 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2657 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2660 dp
= ((insn
& 0xf00) == 0xb00);
2661 switch ((insn
>> 24) & 0xf) {
2663 if (insn
& (1 << 4)) {
2664 /* single register transfer */
2665 rd
= (insn
>> 12) & 0xf;
2670 VFP_DREG_N(rn
, insn
);
2673 if (insn
& 0x00c00060
2674 && !arm_feature(env
, ARM_FEATURE_NEON
))
2677 pass
= (insn
>> 21) & 1;
2678 if (insn
& (1 << 22)) {
2680 offset
= ((insn
>> 5) & 3) * 8;
2681 } else if (insn
& (1 << 5)) {
2683 offset
= (insn
& (1 << 6)) ? 16 : 0;
2688 if (insn
& ARM_CP_RW_BIT
) {
2690 tmp
= neon_load_reg(rn
, pass
);
2694 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2695 if (insn
& (1 << 23))
2701 if (insn
& (1 << 23)) {
2703 tcg_gen_shri_i32(tmp
, tmp
, 16);
2709 tcg_gen_sari_i32(tmp
, tmp
, 16);
2718 store_reg(s
, rd
, tmp
);
2721 tmp
= load_reg(s
, rd
);
2722 if (insn
& (1 << 23)) {
2725 gen_neon_dup_u8(tmp
, 0);
2726 } else if (size
== 1) {
2727 gen_neon_dup_low16(tmp
);
2729 for (n
= 0; n
<= pass
* 2; n
++) {
2731 tcg_gen_mov_i32(tmp2
, tmp
);
2732 neon_store_reg(rn
, n
, tmp2
);
2734 neon_store_reg(rn
, n
, tmp
);
2739 tmp2
= neon_load_reg(rn
, pass
);
2740 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2744 tmp2
= neon_load_reg(rn
, pass
);
2745 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2751 neon_store_reg(rn
, pass
, tmp
);
2755 if ((insn
& 0x6f) != 0x00)
2757 rn
= VFP_SREG_N(insn
);
2758 if (insn
& ARM_CP_RW_BIT
) {
2760 if (insn
& (1 << 21)) {
2761 /* system register */
2766 /* VFP2 allows access to FSID from userspace.
2767 VFP3 restricts all id registers to privileged
2770 && arm_feature(env
, ARM_FEATURE_VFP3
))
2772 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2777 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2779 case ARM_VFP_FPINST
:
2780 case ARM_VFP_FPINST2
:
2781 /* Not present in VFP3. */
2783 || arm_feature(env
, ARM_FEATURE_VFP3
))
2785 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2789 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2790 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2793 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2799 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2801 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2807 gen_mov_F0_vreg(0, rn
);
2808 tmp
= gen_vfp_mrs();
2811 /* Set the 4 flag bits in the CPSR. */
2815 store_reg(s
, rd
, tmp
);
2819 tmp
= load_reg(s
, rd
);
2820 if (insn
& (1 << 21)) {
2822 /* system register */
2827 /* Writes are ignored. */
2830 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2837 /* TODO: VFP subarchitecture support.
2838 * For now, keep the EN bit only */
2839 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2840 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2843 case ARM_VFP_FPINST
:
2844 case ARM_VFP_FPINST2
:
2845 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2852 gen_mov_vreg_F0(0, rn
);
2857 /* data processing */
2858 /* The opcode is in bits 23, 21, 20 and 6. */
2859 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2863 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2865 /* rn is register number */
2866 VFP_DREG_N(rn
, insn
);
2869 if (op
== 15 && (rn
== 15 || ((rn
& 0x1c) == 0x18))) {
2870 /* Integer or single precision destination. */
2871 rd
= VFP_SREG_D(insn
);
2873 VFP_DREG_D(rd
, insn
);
2876 (((rn
& 0x1c) == 0x10) || ((rn
& 0x14) == 0x14))) {
2877 /* VCVT from int is always from S reg regardless of dp bit.
2878 * VCVT with immediate frac_bits has same format as SREG_M
2880 rm
= VFP_SREG_M(insn
);
2882 VFP_DREG_M(rm
, insn
);
2885 rn
= VFP_SREG_N(insn
);
2886 if (op
== 15 && rn
== 15) {
2887 /* Double precision destination. */
2888 VFP_DREG_D(rd
, insn
);
2890 rd
= VFP_SREG_D(insn
);
2892 /* NB that we implicitly rely on the encoding for the frac_bits
2893 * in VCVT of fixed to float being the same as that of an SREG_M
2895 rm
= VFP_SREG_M(insn
);
2898 veclen
= env
->vfp
.vec_len
;
2899 if (op
== 15 && rn
> 3)
2902 /* Shut up compiler warnings. */
2913 /* Figure out what type of vector operation this is. */
2914 if ((rd
& bank_mask
) == 0) {
2919 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2921 delta_d
= env
->vfp
.vec_stride
+ 1;
2923 if ((rm
& bank_mask
) == 0) {
2924 /* mixed scalar/vector */
2933 /* Load the initial operands. */
2938 /* Integer source */
2939 gen_mov_F0_vreg(0, rm
);
2944 gen_mov_F0_vreg(dp
, rd
);
2945 gen_mov_F1_vreg(dp
, rm
);
2949 /* Compare with zero */
2950 gen_mov_F0_vreg(dp
, rd
);
2961 /* Source and destination the same. */
2962 gen_mov_F0_vreg(dp
, rd
);
2965 /* One source operand. */
2966 gen_mov_F0_vreg(dp
, rm
);
2970 /* Two source operands. */
2971 gen_mov_F0_vreg(dp
, rn
);
2972 gen_mov_F1_vreg(dp
, rm
);
2976 /* Perform the calculation. */
2978 case 0: /* mac: fd + (fn * fm) */
2980 gen_mov_F1_vreg(dp
, rd
);
2983 case 1: /* nmac: fd - (fn * fm) */
2986 gen_mov_F1_vreg(dp
, rd
);
2989 case 2: /* msc: -fd + (fn * fm) */
2991 gen_mov_F1_vreg(dp
, rd
);
2994 case 3: /* nmsc: -fd - (fn * fm) */
2997 gen_mov_F1_vreg(dp
, rd
);
3000 case 4: /* mul: fn * fm */
3003 case 5: /* nmul: -(fn * fm) */
3007 case 6: /* add: fn + fm */
3010 case 7: /* sub: fn - fm */
3013 case 8: /* div: fn / fm */
3016 case 14: /* fconst */
3017 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3020 n
= (insn
<< 12) & 0x80000000;
3021 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3028 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3035 tcg_gen_movi_i32(cpu_F0s
, n
);
3038 case 15: /* extension space */
3052 case 4: /* vcvtb.f32.f16 */
3053 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3055 tmp
= gen_vfp_mrs();
3056 tcg_gen_ext16u_i32(tmp
, tmp
);
3057 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3060 case 5: /* vcvtt.f32.f16 */
3061 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3063 tmp
= gen_vfp_mrs();
3064 tcg_gen_shri_i32(tmp
, tmp
, 16);
3065 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3068 case 6: /* vcvtb.f16.f32 */
3069 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3072 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3073 gen_mov_F0_vreg(0, rd
);
3074 tmp2
= gen_vfp_mrs();
3075 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3076 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3080 case 7: /* vcvtt.f16.f32 */
3081 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3084 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3085 tcg_gen_shli_i32(tmp
, tmp
, 16);
3086 gen_mov_F0_vreg(0, rd
);
3087 tmp2
= gen_vfp_mrs();
3088 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3089 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3102 case 11: /* cmpez */
3106 case 15: /* single<->double conversion */
3108 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3110 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3112 case 16: /* fuito */
3115 case 17: /* fsito */
3118 case 20: /* fshto */
3119 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3121 gen_vfp_shto(dp
, 16 - rm
);
3123 case 21: /* fslto */
3124 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3126 gen_vfp_slto(dp
, 32 - rm
);
3128 case 22: /* fuhto */
3129 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3131 gen_vfp_uhto(dp
, 16 - rm
);
3133 case 23: /* fulto */
3134 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3136 gen_vfp_ulto(dp
, 32 - rm
);
3138 case 24: /* ftoui */
3141 case 25: /* ftouiz */
3144 case 26: /* ftosi */
3147 case 27: /* ftosiz */
3150 case 28: /* ftosh */
3151 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3153 gen_vfp_tosh(dp
, 16 - rm
);
3155 case 29: /* ftosl */
3156 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3158 gen_vfp_tosl(dp
, 32 - rm
);
3160 case 30: /* ftouh */
3161 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3163 gen_vfp_touh(dp
, 16 - rm
);
3165 case 31: /* ftoul */
3166 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3168 gen_vfp_toul(dp
, 32 - rm
);
3170 default: /* undefined */
3171 printf ("rn:%d\n", rn
);
3175 default: /* undefined */
3176 printf ("op:%d\n", op
);
3180 /* Write back the result. */
3181 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3182 ; /* Comparison, do nothing. */
3183 else if (op
== 15 && dp
&& ((rn
& 0x1c) == 0x18))
3184 /* VCVT double to int: always integer result. */
3185 gen_mov_vreg_F0(0, rd
);
3186 else if (op
== 15 && rn
== 15)
3188 gen_mov_vreg_F0(!dp
, rd
);
3190 gen_mov_vreg_F0(dp
, rd
);
3192 /* break out of the loop if we have finished */
3196 if (op
== 15 && delta_m
== 0) {
3197 /* single source one-many */
3199 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3201 gen_mov_vreg_F0(dp
, rd
);
3205 /* Setup the next operands. */
3207 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3211 /* One source operand. */
3212 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3214 gen_mov_F0_vreg(dp
, rm
);
3216 /* Two source operands. */
3217 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3219 gen_mov_F0_vreg(dp
, rn
);
3221 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3223 gen_mov_F1_vreg(dp
, rm
);
3231 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3232 /* two-register transfer */
3233 rn
= (insn
>> 16) & 0xf;
3234 rd
= (insn
>> 12) & 0xf;
3236 VFP_DREG_M(rm
, insn
);
3238 rm
= VFP_SREG_M(insn
);
3241 if (insn
& ARM_CP_RW_BIT
) {
3244 gen_mov_F0_vreg(0, rm
* 2);
3245 tmp
= gen_vfp_mrs();
3246 store_reg(s
, rd
, tmp
);
3247 gen_mov_F0_vreg(0, rm
* 2 + 1);
3248 tmp
= gen_vfp_mrs();
3249 store_reg(s
, rn
, tmp
);
3251 gen_mov_F0_vreg(0, rm
);
3252 tmp
= gen_vfp_mrs();
3253 store_reg(s
, rn
, tmp
);
3254 gen_mov_F0_vreg(0, rm
+ 1);
3255 tmp
= gen_vfp_mrs();
3256 store_reg(s
, rd
, tmp
);
3261 tmp
= load_reg(s
, rd
);
3263 gen_mov_vreg_F0(0, rm
* 2);
3264 tmp
= load_reg(s
, rn
);
3266 gen_mov_vreg_F0(0, rm
* 2 + 1);
3268 tmp
= load_reg(s
, rn
);
3270 gen_mov_vreg_F0(0, rm
);
3271 tmp
= load_reg(s
, rd
);
3273 gen_mov_vreg_F0(0, rm
+ 1);
3278 rn
= (insn
>> 16) & 0xf;
3280 VFP_DREG_D(rd
, insn
);
3282 rd
= VFP_SREG_D(insn
);
3283 if (s
->thumb
&& rn
== 15) {
3285 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3287 addr
= load_reg(s
, rn
);
3289 if ((insn
& 0x01200000) == 0x01000000) {
3290 /* Single load/store */
3291 offset
= (insn
& 0xff) << 2;
3292 if ((insn
& (1 << 23)) == 0)
3294 tcg_gen_addi_i32(addr
, addr
, offset
);
3295 if (insn
& (1 << 20)) {
3296 gen_vfp_ld(s
, dp
, addr
);
3297 gen_mov_vreg_F0(dp
, rd
);
3299 gen_mov_F0_vreg(dp
, rd
);
3300 gen_vfp_st(s
, dp
, addr
);
3304 /* load/store multiple */
3306 n
= (insn
>> 1) & 0x7f;
3310 if (insn
& (1 << 24)) /* pre-decrement */
3311 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3317 for (i
= 0; i
< n
; i
++) {
3318 if (insn
& ARM_CP_RW_BIT
) {
3320 gen_vfp_ld(s
, dp
, addr
);
3321 gen_mov_vreg_F0(dp
, rd
+ i
);
3324 gen_mov_F0_vreg(dp
, rd
+ i
);
3325 gen_vfp_st(s
, dp
, addr
);
3327 tcg_gen_addi_i32(addr
, addr
, offset
);
3329 if (insn
& (1 << 21)) {
3331 if (insn
& (1 << 24))
3332 offset
= -offset
* n
;
3333 else if (dp
&& (insn
& 1))
3339 tcg_gen_addi_i32(addr
, addr
, offset
);
3340 store_reg(s
, rn
, addr
);
3348 /* Should never happen. */
3354 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3356 TranslationBlock
*tb
;
3359 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3361 gen_set_pc_im(dest
);
3362 tcg_gen_exit_tb((long)tb
+ n
);
3364 gen_set_pc_im(dest
);
3369 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3371 if (unlikely(s
->singlestep_enabled
)) {
3372 /* An indirect jump so that we still trigger the debug exception. */
3377 gen_goto_tb(s
, 0, dest
);
3378 s
->is_jmp
= DISAS_TB_JUMP
;
3382 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3385 tcg_gen_sari_i32(t0
, t0
, 16);
3389 tcg_gen_sari_i32(t1
, t1
, 16);
3392 tcg_gen_mul_i32(t0
, t0
, t1
);
3395 /* Return the mask of PSR bits set by a MSR instruction. */
3396 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3400 if (flags
& (1 << 0))
3402 if (flags
& (1 << 1))
3404 if (flags
& (1 << 2))
3406 if (flags
& (1 << 3))
3409 /* Mask out undefined bits. */
3410 mask
&= ~CPSR_RESERVED
;
3411 if (!arm_feature(env
, ARM_FEATURE_V6
))
3412 mask
&= ~(CPSR_E
| CPSR_GE
);
3413 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3415 /* Mask out execution state bits. */
3418 /* Mask out privileged bits. */
3424 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3425 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3429 /* ??? This is also undefined in system mode. */
3433 tmp
= load_cpu_field(spsr
);
3434 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3435 tcg_gen_andi_i32(t0
, t0
, mask
);
3436 tcg_gen_or_i32(tmp
, tmp
, t0
);
3437 store_cpu_field(tmp
, spsr
);
3439 gen_set_cpsr(t0
, mask
);
3446 /* Returns nonzero if access to the PSR is not permitted. */
3447 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3451 tcg_gen_movi_i32(tmp
, val
);
3452 return gen_set_psr(s
, mask
, spsr
, tmp
);
3455 /* Generate an old-style exception return. Marks pc as dead. */
3456 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3459 store_reg(s
, 15, pc
);
3460 tmp
= load_cpu_field(spsr
);
3461 gen_set_cpsr(tmp
, 0xffffffff);
3463 s
->is_jmp
= DISAS_UPDATE
;
3466 /* Generate a v6 exception return. Marks both values as dead. */
3467 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3469 gen_set_cpsr(cpsr
, 0xffffffff);
3471 store_reg(s
, 15, pc
);
3472 s
->is_jmp
= DISAS_UPDATE
;
3476 gen_set_condexec (DisasContext
*s
)
3478 if (s
->condexec_mask
) {
3479 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3480 TCGv tmp
= new_tmp();
3481 tcg_gen_movi_i32(tmp
, val
);
3482 store_cpu_field(tmp
, condexec_bits
);
3486 static void gen_nop_hint(DisasContext
*s
, int val
)
3490 gen_set_pc_im(s
->pc
);
3491 s
->is_jmp
= DISAS_WFI
;
3495 /* TODO: Implement SEV and WFE. May help SMP performance. */
3501 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3503 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3506 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3507 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3508 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3514 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3517 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3518 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3519 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3524 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3525 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3526 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3527 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3528 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3530 /* FIXME: This is wrong. They set the wrong overflow bit. */
3531 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3532 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3533 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3534 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3536 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3537 switch ((size << 1) | u) { \
3539 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3542 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3545 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3548 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3551 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3554 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3556 default: return 1; \
3559 #define GEN_NEON_INTEGER_OP(name) do { \
3560 switch ((size << 1) | u) { \
3562 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3565 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3568 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3571 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3574 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3577 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3579 default: return 1; \
3582 static TCGv
neon_load_scratch(int scratch
)
3584 TCGv tmp
= new_tmp();
3585 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3589 static void neon_store_scratch(int scratch
, TCGv var
)
3591 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3595 static inline TCGv
neon_get_scalar(int size
, int reg
)
3599 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3601 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3603 gen_neon_dup_low16(tmp
);
3605 gen_neon_dup_high16(tmp
);
3611 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3619 tcg_gen_andi_i32(rd
, t0
, 0xff);
3620 tcg_gen_shri_i32(tmp
, t0
, 8);
3621 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3622 tcg_gen_or_i32(rd
, rd
, tmp
);
3623 tcg_gen_shli_i32(tmp
, t1
, 16);
3624 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3625 tcg_gen_or_i32(rd
, rd
, tmp
);
3626 tcg_gen_shli_i32(tmp
, t1
, 8);
3627 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3628 tcg_gen_or_i32(rd
, rd
, tmp
);
3630 tcg_gen_shri_i32(rm
, t0
, 8);
3631 tcg_gen_andi_i32(rm
, rm
, 0xff);
3632 tcg_gen_shri_i32(tmp
, t0
, 16);
3633 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3634 tcg_gen_or_i32(rm
, rm
, tmp
);
3635 tcg_gen_shli_i32(tmp
, t1
, 8);
3636 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3637 tcg_gen_or_i32(rm
, rm
, tmp
);
3638 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3639 tcg_gen_or_i32(t1
, rm
, tmp
);
3640 tcg_gen_mov_i32(t0
, rd
);
3647 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3655 tcg_gen_andi_i32(rd
, t0
, 0xff);
3656 tcg_gen_shli_i32(tmp
, t1
, 8);
3657 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3658 tcg_gen_or_i32(rd
, rd
, tmp
);
3659 tcg_gen_shli_i32(tmp
, t0
, 16);
3660 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3661 tcg_gen_or_i32(rd
, rd
, tmp
);
3662 tcg_gen_shli_i32(tmp
, t1
, 24);
3663 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3664 tcg_gen_or_i32(rd
, rd
, tmp
);
3666 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3667 tcg_gen_shri_i32(tmp
, t0
, 8);
3668 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3669 tcg_gen_or_i32(rm
, rm
, tmp
);
3670 tcg_gen_shri_i32(tmp
, t1
, 8);
3671 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3672 tcg_gen_or_i32(rm
, rm
, tmp
);
3673 tcg_gen_shri_i32(tmp
, t0
, 16);
3674 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3675 tcg_gen_or_i32(t1
, rm
, tmp
);
3676 tcg_gen_mov_i32(t0
, rd
);
3683 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3690 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3691 tcg_gen_shli_i32(tmp2
, t1
, 16);
3692 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3693 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3694 tcg_gen_shri_i32(tmp2
, t0
, 16);
3695 tcg_gen_or_i32(t1
, t1
, tmp2
);
3696 tcg_gen_mov_i32(t0
, tmp
);
3702 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3707 for (n
= 0; n
< q
+ 1; n
+= 2) {
3708 t0
= neon_load_reg(reg
, n
);
3709 t1
= neon_load_reg(reg
, n
+ 1);
3711 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3712 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3713 case 2: /* no-op */; break;
3716 neon_store_scratch(tmp
+ n
, t0
);
3717 neon_store_scratch(tmp
+ n
+ 1, t1
);
3721 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3728 tcg_gen_shli_i32(rd
, t0
, 8);
3729 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3730 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3731 tcg_gen_or_i32(rd
, rd
, tmp
);
3733 tcg_gen_shri_i32(t1
, t1
, 8);
3734 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3735 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3736 tcg_gen_or_i32(t1
, t1
, tmp
);
3737 tcg_gen_mov_i32(t0
, rd
);
3743 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3750 tcg_gen_shli_i32(rd
, t0
, 16);
3751 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3752 tcg_gen_or_i32(rd
, rd
, tmp
);
3753 tcg_gen_shri_i32(t1
, t1
, 16);
3754 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3755 tcg_gen_or_i32(t1
, t1
, tmp
);
3756 tcg_gen_mov_i32(t0
, rd
);
3767 } neon_ls_element_type
[11] = {
3781 /* Translate a NEON load/store element instruction. Return nonzero if the
3782 instruction is invalid. */
3783 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3802 if (!vfp_enabled(env
))
3804 VFP_DREG_D(rd
, insn
);
3805 rn
= (insn
>> 16) & 0xf;
3807 load
= (insn
& (1 << 21)) != 0;
3809 if ((insn
& (1 << 23)) == 0) {
3810 /* Load store all elements. */
3811 op
= (insn
>> 8) & 0xf;
3812 size
= (insn
>> 6) & 3;
3815 nregs
= neon_ls_element_type
[op
].nregs
;
3816 interleave
= neon_ls_element_type
[op
].interleave
;
3817 spacing
= neon_ls_element_type
[op
].spacing
;
3818 if (size
== 3 && (interleave
| spacing
) != 1)
3820 load_reg_var(s
, addr
, rn
);
3821 stride
= (1 << size
) * interleave
;
3822 for (reg
= 0; reg
< nregs
; reg
++) {
3823 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3824 load_reg_var(s
, addr
, rn
);
3825 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3826 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3827 load_reg_var(s
, addr
, rn
);
3828 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3832 tmp64
= gen_ld64(addr
, IS_USER(s
));
3833 neon_store_reg64(tmp64
, rd
);
3834 tcg_temp_free_i64(tmp64
);
3836 tmp64
= tcg_temp_new_i64();
3837 neon_load_reg64(tmp64
, rd
);
3838 gen_st64(tmp64
, addr
, IS_USER(s
));
3840 tcg_gen_addi_i32(addr
, addr
, stride
);
3842 for (pass
= 0; pass
< 2; pass
++) {
3845 tmp
= gen_ld32(addr
, IS_USER(s
));
3846 neon_store_reg(rd
, pass
, tmp
);
3848 tmp
= neon_load_reg(rd
, pass
);
3849 gen_st32(tmp
, addr
, IS_USER(s
));
3851 tcg_gen_addi_i32(addr
, addr
, stride
);
3852 } else if (size
== 1) {
3854 tmp
= gen_ld16u(addr
, IS_USER(s
));
3855 tcg_gen_addi_i32(addr
, addr
, stride
);
3856 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3857 tcg_gen_addi_i32(addr
, addr
, stride
);
3858 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3859 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3861 neon_store_reg(rd
, pass
, tmp
);
3863 tmp
= neon_load_reg(rd
, pass
);
3865 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3866 gen_st16(tmp
, addr
, IS_USER(s
));
3867 tcg_gen_addi_i32(addr
, addr
, stride
);
3868 gen_st16(tmp2
, addr
, IS_USER(s
));
3869 tcg_gen_addi_i32(addr
, addr
, stride
);
3871 } else /* size == 0 */ {
3874 for (n
= 0; n
< 4; n
++) {
3875 tmp
= gen_ld8u(addr
, IS_USER(s
));
3876 tcg_gen_addi_i32(addr
, addr
, stride
);
3880 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3881 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3885 neon_store_reg(rd
, pass
, tmp2
);
3887 tmp2
= neon_load_reg(rd
, pass
);
3888 for (n
= 0; n
< 4; n
++) {
3891 tcg_gen_mov_i32(tmp
, tmp2
);
3893 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3895 gen_st8(tmp
, addr
, IS_USER(s
));
3896 tcg_gen_addi_i32(addr
, addr
, stride
);
3907 size
= (insn
>> 10) & 3;
3909 /* Load single element to all lanes. */
3912 size
= (insn
>> 6) & 3;
3913 nregs
= ((insn
>> 8) & 3) + 1;
3914 stride
= (insn
& (1 << 5)) ? 2 : 1;
3915 load_reg_var(s
, addr
, rn
);
3916 for (reg
= 0; reg
< nregs
; reg
++) {
3919 tmp
= gen_ld8u(addr
, IS_USER(s
));
3920 gen_neon_dup_u8(tmp
, 0);
3923 tmp
= gen_ld16u(addr
, IS_USER(s
));
3924 gen_neon_dup_low16(tmp
);
3927 tmp
= gen_ld32(addr
, IS_USER(s
));
3931 default: /* Avoid compiler warnings. */
3934 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3936 tcg_gen_mov_i32(tmp2
, tmp
);
3937 neon_store_reg(rd
, 0, tmp2
);
3938 neon_store_reg(rd
, 1, tmp
);
3941 stride
= (1 << size
) * nregs
;
3943 /* Single element. */
3944 pass
= (insn
>> 7) & 1;
3947 shift
= ((insn
>> 5) & 3) * 8;
3951 shift
= ((insn
>> 6) & 1) * 16;
3952 stride
= (insn
& (1 << 5)) ? 2 : 1;
3956 stride
= (insn
& (1 << 6)) ? 2 : 1;
3961 nregs
= ((insn
>> 8) & 3) + 1;
3962 load_reg_var(s
, addr
, rn
);
3963 for (reg
= 0; reg
< nregs
; reg
++) {
3967 tmp
= gen_ld8u(addr
, IS_USER(s
));
3970 tmp
= gen_ld16u(addr
, IS_USER(s
));
3973 tmp
= gen_ld32(addr
, IS_USER(s
));
3975 default: /* Avoid compiler warnings. */
3979 tmp2
= neon_load_reg(rd
, pass
);
3980 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3983 neon_store_reg(rd
, pass
, tmp
);
3984 } else { /* Store */
3985 tmp
= neon_load_reg(rd
, pass
);
3987 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3990 gen_st8(tmp
, addr
, IS_USER(s
));
3993 gen_st16(tmp
, addr
, IS_USER(s
));
3996 gen_st32(tmp
, addr
, IS_USER(s
));
4001 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4003 stride
= nregs
* (1 << size
);
4010 base
= load_reg(s
, rn
);
4012 tcg_gen_addi_i32(base
, base
, stride
);
4015 index
= load_reg(s
, rm
);
4016 tcg_gen_add_i32(base
, base
, index
);
4019 store_reg(s
, rn
, base
);
4024 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4025 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4027 tcg_gen_and_i32(t
, t
, c
);
4028 tcg_gen_andc_i32(f
, f
, c
);
4029 tcg_gen_or_i32(dest
, t
, f
);
4032 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4035 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4036 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4037 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4042 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4045 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4046 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4047 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4052 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4055 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4056 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4057 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4062 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4068 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4069 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4074 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4075 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4082 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4083 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4088 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4089 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4096 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4100 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4101 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4102 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4107 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4108 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4109 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4116 static inline void gen_neon_addl(int size
)
4119 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4120 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4121 case 2: tcg_gen_add_i64(CPU_V001
); break;
4126 static inline void gen_neon_subl(int size
)
4129 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4130 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4131 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4136 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4139 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4140 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4141 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4146 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4149 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4150 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4155 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4159 switch ((size
<< 1) | u
) {
4160 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4161 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4162 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4163 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4165 tmp
= gen_muls_i64_i32(a
, b
);
4166 tcg_gen_mov_i64(dest
, tmp
);
4169 tmp
= gen_mulu_i64_i32(a
, b
);
4170 tcg_gen_mov_i64(dest
, tmp
);
4176 /* Translate a NEON data processing instruction. Return nonzero if the
4177 instruction is invalid.
4178 We process data in a mixture of 32-bit and 64-bit chunks.
4179 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4181 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4194 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4197 if (!vfp_enabled(env
))
4199 q
= (insn
& (1 << 6)) != 0;
4200 u
= (insn
>> 24) & 1;
4201 VFP_DREG_D(rd
, insn
);
4202 VFP_DREG_N(rn
, insn
);
4203 VFP_DREG_M(rm
, insn
);
4204 size
= (insn
>> 20) & 3;
4205 if ((insn
& (1 << 23)) == 0) {
4206 /* Three register same length. */
4207 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4208 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4209 || op
== 10 || op
== 11 || op
== 16)) {
4210 /* 64-bit element instructions. */
4211 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4212 neon_load_reg64(cpu_V0
, rn
+ pass
);
4213 neon_load_reg64(cpu_V1
, rm
+ pass
);
4217 gen_helper_neon_add_saturate_u64(CPU_V001
);
4219 gen_helper_neon_add_saturate_s64(CPU_V001
);
4224 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4226 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4231 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4233 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4238 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4241 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4245 case 10: /* VRSHL */
4247 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4249 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4252 case 11: /* VQRSHL */
4254 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4257 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4263 tcg_gen_sub_i64(CPU_V001
);
4265 tcg_gen_add_i64(CPU_V001
);
4271 neon_store_reg64(cpu_V0
, rd
+ pass
);
4278 case 10: /* VRSHL */
4279 case 11: /* VQRSHL */
4282 /* Shift instruction operands are reversed. */
4289 case 20: /* VPMAX */
4290 case 21: /* VPMIN */
4291 case 23: /* VPADD */
4294 case 26: /* VPADD (float) */
4295 pairwise
= (u
&& size
< 2);
4297 case 30: /* VPMIN/VPMAX (float) */
4305 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4314 tmp
= neon_load_reg(rn
, n
);
4315 tmp2
= neon_load_reg(rn
, n
+ 1);
4317 tmp
= neon_load_reg(rm
, n
);
4318 tmp2
= neon_load_reg(rm
, n
+ 1);
4322 tmp
= neon_load_reg(rn
, pass
);
4323 tmp2
= neon_load_reg(rm
, pass
);
4327 GEN_NEON_INTEGER_OP(hadd
);
4330 GEN_NEON_INTEGER_OP_ENV(qadd
);
4332 case 2: /* VRHADD */
4333 GEN_NEON_INTEGER_OP(rhadd
);
4335 case 3: /* Logic ops. */
4336 switch ((u
<< 2) | size
) {
4338 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4341 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4344 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4347 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4350 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4353 tmp3
= neon_load_reg(rd
, pass
);
4354 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4358 tmp3
= neon_load_reg(rd
, pass
);
4359 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4363 tmp3
= neon_load_reg(rd
, pass
);
4364 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4370 GEN_NEON_INTEGER_OP(hsub
);
4373 GEN_NEON_INTEGER_OP_ENV(qsub
);
4376 GEN_NEON_INTEGER_OP(cgt
);
4379 GEN_NEON_INTEGER_OP(cge
);
4382 GEN_NEON_INTEGER_OP(shl
);
4385 GEN_NEON_INTEGER_OP_ENV(qshl
);
4387 case 10: /* VRSHL */
4388 GEN_NEON_INTEGER_OP(rshl
);
4390 case 11: /* VQRSHL */
4391 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4394 GEN_NEON_INTEGER_OP(max
);
4397 GEN_NEON_INTEGER_OP(min
);
4400 GEN_NEON_INTEGER_OP(abd
);
4403 GEN_NEON_INTEGER_OP(abd
);
4405 tmp2
= neon_load_reg(rd
, pass
);
4406 gen_neon_add(size
, tmp
, tmp2
);
4409 if (!u
) { /* VADD */
4410 if (gen_neon_add(size
, tmp
, tmp2
))
4414 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4415 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4416 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4422 if (!u
) { /* VTST */
4424 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4425 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4426 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4431 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4432 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4433 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4438 case 18: /* Multiply. */
4440 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4441 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4442 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4446 tmp2
= neon_load_reg(rd
, pass
);
4448 gen_neon_rsb(size
, tmp
, tmp2
);
4450 gen_neon_add(size
, tmp
, tmp2
);
4454 if (u
) { /* polynomial */
4455 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4456 } else { /* Integer */
4458 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4459 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4460 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4465 case 20: /* VPMAX */
4466 GEN_NEON_INTEGER_OP(pmax
);
4468 case 21: /* VPMIN */
4469 GEN_NEON_INTEGER_OP(pmin
);
4471 case 22: /* Hultiply high. */
4472 if (!u
) { /* VQDMULH */
4474 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4475 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4478 } else { /* VQRDHMUL */
4480 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4481 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4486 case 23: /* VPADD */
4490 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4491 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4492 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4496 case 26: /* Floating point arithnetic. */
4497 switch ((u
<< 2) | size
) {
4499 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4502 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4505 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4508 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4514 case 27: /* Float multiply. */
4515 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4518 tmp2
= neon_load_reg(rd
, pass
);
4520 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4522 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4526 case 28: /* Float compare. */
4528 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4531 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4533 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4536 case 29: /* Float compare absolute. */
4540 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4542 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4544 case 30: /* Float min/max. */
4546 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4548 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4552 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4554 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4561 /* Save the result. For elementwise operations we can put it
4562 straight into the destination register. For pairwise operations
4563 we have to be careful to avoid clobbering the source operands. */
4564 if (pairwise
&& rd
== rm
) {
4565 neon_store_scratch(pass
, tmp
);
4567 neon_store_reg(rd
, pass
, tmp
);
4571 if (pairwise
&& rd
== rm
) {
4572 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4573 tmp
= neon_load_scratch(pass
);
4574 neon_store_reg(rd
, pass
, tmp
);
4577 /* End of 3 register same size operations. */
4578 } else if (insn
& (1 << 4)) {
4579 if ((insn
& 0x00380080) != 0) {
4580 /* Two registers and shift. */
4581 op
= (insn
>> 8) & 0xf;
4582 if (insn
& (1 << 7)) {
4587 while ((insn
& (1 << (size
+ 19))) == 0)
4590 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4591 /* To avoid excessive dumplication of ops we implement shift
4592 by immediate using the variable shift operations. */
4594 /* Shift by immediate:
4595 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4596 /* Right shifts are encoded as N - shift, where N is the
4597 element size in bits. */
4599 shift
= shift
- (1 << (size
+ 3));
4607 imm
= (uint8_t) shift
;
4612 imm
= (uint16_t) shift
;
4623 for (pass
= 0; pass
< count
; pass
++) {
4625 neon_load_reg64(cpu_V0
, rm
+ pass
);
4626 tcg_gen_movi_i64(cpu_V1
, imm
);
4631 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4633 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4638 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4640 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4645 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4647 case 5: /* VSHL, VSLI */
4648 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4652 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4654 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4656 case 7: /* VQSHLU */
4657 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4660 if (op
== 1 || op
== 3) {
4662 neon_load_reg64(cpu_V0
, rd
+ pass
);
4663 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4664 } else if (op
== 4 || (op
== 5 && u
)) {
4666 cpu_abort(env
, "VS[LR]I.64 not implemented");
4668 neon_store_reg64(cpu_V0
, rd
+ pass
);
4669 } else { /* size < 3 */
4670 /* Operands in T0 and T1. */
4671 tmp
= neon_load_reg(rm
, pass
);
4673 tcg_gen_movi_i32(tmp2
, imm
);
4677 GEN_NEON_INTEGER_OP(shl
);
4681 GEN_NEON_INTEGER_OP(rshl
);
4686 GEN_NEON_INTEGER_OP(shl
);
4688 case 5: /* VSHL, VSLI */
4690 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4691 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4692 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4697 GEN_NEON_INTEGER_OP_ENV(qshl
);
4699 case 7: /* VQSHLU */
4701 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4702 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4703 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4710 if (op
== 1 || op
== 3) {
4712 tmp2
= neon_load_reg(rd
, pass
);
4713 gen_neon_add(size
, tmp2
, tmp
);
4715 } else if (op
== 4 || (op
== 5 && u
)) {
4720 mask
= 0xff >> -shift
;
4722 mask
= (uint8_t)(0xff << shift
);
4728 mask
= 0xffff >> -shift
;
4730 mask
= (uint16_t)(0xffff << shift
);
4734 if (shift
< -31 || shift
> 31) {
4738 mask
= 0xffffffffu
>> -shift
;
4740 mask
= 0xffffffffu
<< shift
;
4746 tmp2
= neon_load_reg(rd
, pass
);
4747 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4748 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4749 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4752 neon_store_reg(rd
, pass
, tmp
);
4755 } else if (op
< 10) {
4756 /* Shift by immediate and narrow:
4757 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4758 shift
= shift
- (1 << (size
+ 3));
4762 imm
= (uint16_t)shift
;
4764 tmp2
= tcg_const_i32(imm
);
4765 TCGV_UNUSED_I64(tmp64
);
4768 imm
= (uint32_t)shift
;
4769 tmp2
= tcg_const_i32(imm
);
4770 TCGV_UNUSED_I64(tmp64
);
4773 tmp64
= tcg_const_i64(shift
);
4780 for (pass
= 0; pass
< 2; pass
++) {
4782 neon_load_reg64(cpu_V0
, rm
+ pass
);
4785 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4787 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4790 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4792 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4795 tmp
= neon_load_reg(rm
+ pass
, 0);
4796 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4797 tmp3
= neon_load_reg(rm
+ pass
, 1);
4798 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4799 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4804 if (op
== 8 && !u
) {
4805 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4808 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4810 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4812 neon_store_reg(rd
, pass
, tmp
);
4815 tcg_temp_free_i64(tmp64
);
4819 } else if (op
== 10) {
4823 tmp
= neon_load_reg(rm
, 0);
4824 tmp2
= neon_load_reg(rm
, 1);
4825 for (pass
= 0; pass
< 2; pass
++) {
4829 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4832 /* The shift is less than the width of the source
4833 type, so we can just shift the whole register. */
4834 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4835 if (size
< 2 || !u
) {
4838 imm
= (0xffu
>> (8 - shift
));
4841 imm
= 0xffff >> (16 - shift
);
4843 imm64
= imm
| (((uint64_t)imm
) << 32);
4844 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4847 neon_store_reg64(cpu_V0
, rd
+ pass
);
4849 } else if (op
>= 14) {
4850 /* VCVT fixed-point. */
4851 /* We have already masked out the must-be-1 top bit of imm6,
4852 * hence this 32-shift where the ARM ARM has 64-imm6.
4855 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4856 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4859 gen_vfp_ulto(0, shift
);
4861 gen_vfp_slto(0, shift
);
4864 gen_vfp_toul(0, shift
);
4866 gen_vfp_tosl(0, shift
);
4868 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4873 } else { /* (insn & 0x00380080) == 0 */
4876 op
= (insn
>> 8) & 0xf;
4877 /* One register and immediate. */
4878 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4879 invert
= (insn
& (1 << 5)) != 0;
4897 imm
= (imm
<< 8) | (imm
<< 24);
4900 imm
= (imm
<< 8) | 0xff;
4903 imm
= (imm
<< 16) | 0xffff;
4906 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4911 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4912 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4918 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4919 if (op
& 1 && op
< 12) {
4920 tmp
= neon_load_reg(rd
, pass
);
4922 /* The immediate value has already been inverted, so
4924 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4926 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4931 if (op
== 14 && invert
) {
4934 for (n
= 0; n
< 4; n
++) {
4935 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4936 val
|= 0xff << (n
* 8);
4938 tcg_gen_movi_i32(tmp
, val
);
4940 tcg_gen_movi_i32(tmp
, imm
);
4943 neon_store_reg(rd
, pass
, tmp
);
4946 } else { /* (insn & 0x00800010 == 0x00800000) */
4948 op
= (insn
>> 8) & 0xf;
4949 if ((insn
& (1 << 6)) == 0) {
4950 /* Three registers of different lengths. */
4954 /* prewiden, src1_wide, src2_wide */
4955 static const int neon_3reg_wide
[16][3] = {
4956 {1, 0, 0}, /* VADDL */
4957 {1, 1, 0}, /* VADDW */
4958 {1, 0, 0}, /* VSUBL */
4959 {1, 1, 0}, /* VSUBW */
4960 {0, 1, 1}, /* VADDHN */
4961 {0, 0, 0}, /* VABAL */
4962 {0, 1, 1}, /* VSUBHN */
4963 {0, 0, 0}, /* VABDL */
4964 {0, 0, 0}, /* VMLAL */
4965 {0, 0, 0}, /* VQDMLAL */
4966 {0, 0, 0}, /* VMLSL */
4967 {0, 0, 0}, /* VQDMLSL */
4968 {0, 0, 0}, /* Integer VMULL */
4969 {0, 0, 0}, /* VQDMULL */
4970 {0, 0, 0} /* Polynomial VMULL */
4973 prewiden
= neon_3reg_wide
[op
][0];
4974 src1_wide
= neon_3reg_wide
[op
][1];
4975 src2_wide
= neon_3reg_wide
[op
][2];
4977 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4980 /* Avoid overlapping operands. Wide source operands are
4981 always aligned so will never overlap with wide
4982 destinations in problematic ways. */
4983 if (rd
== rm
&& !src2_wide
) {
4984 tmp
= neon_load_reg(rm
, 1);
4985 neon_store_scratch(2, tmp
);
4986 } else if (rd
== rn
&& !src1_wide
) {
4987 tmp
= neon_load_reg(rn
, 1);
4988 neon_store_scratch(2, tmp
);
4991 for (pass
= 0; pass
< 2; pass
++) {
4993 neon_load_reg64(cpu_V0
, rn
+ pass
);
4996 if (pass
== 1 && rd
== rn
) {
4997 tmp
= neon_load_scratch(2);
4999 tmp
= neon_load_reg(rn
, pass
);
5002 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5006 neon_load_reg64(cpu_V1
, rm
+ pass
);
5009 if (pass
== 1 && rd
== rm
) {
5010 tmp2
= neon_load_scratch(2);
5012 tmp2
= neon_load_reg(rm
, pass
);
5015 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5019 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5020 gen_neon_addl(size
);
5022 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5023 gen_neon_subl(size
);
5025 case 5: case 7: /* VABAL, VABDL */
5026 switch ((size
<< 1) | u
) {
5028 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5031 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5034 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5037 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5040 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5043 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5050 case 8: case 9: case 10: case 11: case 12: case 13:
5051 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5052 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5056 case 14: /* Polynomial VMULL */
5057 cpu_abort(env
, "Polynomial VMULL not implemented");
5059 default: /* 15 is RESERVED. */
5062 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5064 if (op
== 10 || op
== 11) {
5065 gen_neon_negl(cpu_V0
, size
);
5069 neon_load_reg64(cpu_V1
, rd
+ pass
);
5073 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5074 gen_neon_addl(size
);
5076 case 9: case 11: /* VQDMLAL, VQDMLSL */
5077 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5078 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5081 case 13: /* VQDMULL */
5082 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5087 neon_store_reg64(cpu_V0
, rd
+ pass
);
5088 } else if (op
== 4 || op
== 6) {
5089 /* Narrowing operation. */
5094 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5097 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5100 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5101 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5108 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5111 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5114 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5115 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5116 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5124 neon_store_reg(rd
, 0, tmp3
);
5125 neon_store_reg(rd
, 1, tmp
);
5128 /* Write back the result. */
5129 neon_store_reg64(cpu_V0
, rd
+ pass
);
5133 /* Two registers and a scalar. */
5135 case 0: /* Integer VMLA scalar */
5136 case 1: /* Float VMLA scalar */
5137 case 4: /* Integer VMLS scalar */
5138 case 5: /* Floating point VMLS scalar */
5139 case 8: /* Integer VMUL scalar */
5140 case 9: /* Floating point VMUL scalar */
5141 case 12: /* VQDMULH scalar */
5142 case 13: /* VQRDMULH scalar */
5143 tmp
= neon_get_scalar(size
, rm
);
5144 neon_store_scratch(0, tmp
);
5145 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5146 tmp
= neon_load_scratch(0);
5147 tmp2
= neon_load_reg(rn
, pass
);
5150 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5152 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5154 } else if (op
== 13) {
5156 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5158 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5160 } else if (op
& 1) {
5161 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5164 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5165 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5166 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5173 tmp2
= neon_load_reg(rd
, pass
);
5176 gen_neon_add(size
, tmp
, tmp2
);
5179 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5182 gen_neon_rsb(size
, tmp
, tmp2
);
5185 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5192 neon_store_reg(rd
, pass
, tmp
);
5195 case 2: /* VMLAL sclar */
5196 case 3: /* VQDMLAL scalar */
5197 case 6: /* VMLSL scalar */
5198 case 7: /* VQDMLSL scalar */
5199 case 10: /* VMULL scalar */
5200 case 11: /* VQDMULL scalar */
5201 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5204 tmp2
= neon_get_scalar(size
, rm
);
5205 tmp3
= neon_load_reg(rn
, 1);
5207 for (pass
= 0; pass
< 2; pass
++) {
5209 tmp
= neon_load_reg(rn
, 0);
5213 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5215 if (op
== 6 || op
== 7) {
5216 gen_neon_negl(cpu_V0
, size
);
5219 neon_load_reg64(cpu_V1
, rd
+ pass
);
5223 gen_neon_addl(size
);
5226 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5227 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5233 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5238 neon_store_reg64(cpu_V0
, rd
+ pass
);
5244 default: /* 14 and 15 are RESERVED */
5248 } else { /* size == 3 */
5251 imm
= (insn
>> 8) & 0xf;
5257 neon_load_reg64(cpu_V0
, rn
);
5259 neon_load_reg64(cpu_V1
, rn
+ 1);
5261 } else if (imm
== 8) {
5262 neon_load_reg64(cpu_V0
, rn
+ 1);
5264 neon_load_reg64(cpu_V1
, rm
);
5267 tmp64
= tcg_temp_new_i64();
5269 neon_load_reg64(cpu_V0
, rn
);
5270 neon_load_reg64(tmp64
, rn
+ 1);
5272 neon_load_reg64(cpu_V0
, rn
+ 1);
5273 neon_load_reg64(tmp64
, rm
);
5275 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5276 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5277 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5279 neon_load_reg64(cpu_V1
, rm
);
5281 neon_load_reg64(cpu_V1
, rm
+ 1);
5284 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5285 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5286 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5287 tcg_temp_free_i64(tmp64
);
5290 neon_load_reg64(cpu_V0
, rn
);
5291 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5292 neon_load_reg64(cpu_V1
, rm
);
5293 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5294 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5296 neon_store_reg64(cpu_V0
, rd
);
5298 neon_store_reg64(cpu_V1
, rd
+ 1);
5300 } else if ((insn
& (1 << 11)) == 0) {
5301 /* Two register misc. */
5302 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5303 size
= (insn
>> 18) & 3;
5305 case 0: /* VREV64 */
5308 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5309 tmp
= neon_load_reg(rm
, pass
* 2);
5310 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5312 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5313 case 1: gen_swap_half(tmp
); break;
5314 case 2: /* no-op */ break;
5317 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5319 neon_store_reg(rd
, pass
* 2, tmp2
);
5322 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5323 case 1: gen_swap_half(tmp2
); break;
5326 neon_store_reg(rd
, pass
* 2, tmp2
);
5330 case 4: case 5: /* VPADDL */
5331 case 12: case 13: /* VPADAL */
5334 for (pass
= 0; pass
< q
+ 1; pass
++) {
5335 tmp
= neon_load_reg(rm
, pass
* 2);
5336 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5337 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5338 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5340 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5341 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5342 case 2: tcg_gen_add_i64(CPU_V001
); break;
5347 neon_load_reg64(cpu_V1
, rd
+ pass
);
5348 gen_neon_addl(size
);
5350 neon_store_reg64(cpu_V0
, rd
+ pass
);
5355 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5356 tmp
= neon_load_reg(rm
, n
);
5357 tmp2
= neon_load_reg(rd
, n
+ 1);
5358 neon_store_reg(rm
, n
, tmp2
);
5359 neon_store_reg(rd
, n
+ 1, tmp
);
5367 Rd A3 A2 A1 A0 B2 B0 A2 A0
5368 Rm B3 B2 B1 B0 B3 B1 A3 A1
5372 gen_neon_unzip(rd
, q
, 0, size
);
5373 gen_neon_unzip(rm
, q
, 4, size
);
5375 static int unzip_order_q
[8] =
5376 {0, 2, 4, 6, 1, 3, 5, 7};
5377 for (n
= 0; n
< 8; n
++) {
5378 int reg
= (n
< 4) ? rd
: rm
;
5379 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5380 neon_store_reg(reg
, n
% 4, tmp
);
5383 static int unzip_order
[4] =
5385 for (n
= 0; n
< 4; n
++) {
5386 int reg
= (n
< 2) ? rd
: rm
;
5387 tmp
= neon_load_scratch(unzip_order
[n
]);
5388 neon_store_reg(reg
, n
% 2, tmp
);
5394 Rd A3 A2 A1 A0 B1 A1 B0 A0
5395 Rm B3 B2 B1 B0 B3 A3 B2 A2
5399 count
= (q
? 4 : 2);
5400 for (n
= 0; n
< count
; n
++) {
5401 tmp
= neon_load_reg(rd
, n
);
5402 tmp2
= neon_load_reg(rd
, n
);
5404 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5405 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5406 case 2: /* no-op */; break;
5409 neon_store_scratch(n
* 2, tmp
);
5410 neon_store_scratch(n
* 2 + 1, tmp2
);
5412 for (n
= 0; n
< count
* 2; n
++) {
5413 int reg
= (n
< count
) ? rd
: rm
;
5414 tmp
= neon_load_scratch(n
);
5415 neon_store_reg(reg
, n
% count
, tmp
);
5418 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5422 for (pass
= 0; pass
< 2; pass
++) {
5423 neon_load_reg64(cpu_V0
, rm
+ pass
);
5425 if (op
== 36 && q
== 0) {
5426 gen_neon_narrow(size
, tmp
, cpu_V0
);
5428 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5430 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5435 neon_store_reg(rd
, 0, tmp2
);
5436 neon_store_reg(rd
, 1, tmp
);
5440 case 38: /* VSHLL */
5443 tmp
= neon_load_reg(rm
, 0);
5444 tmp2
= neon_load_reg(rm
, 1);
5445 for (pass
= 0; pass
< 2; pass
++) {
5448 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5449 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5450 neon_store_reg64(cpu_V0
, rd
+ pass
);
5453 case 44: /* VCVT.F16.F32 */
5454 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5458 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5459 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5460 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5461 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5462 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5463 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5464 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5465 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5466 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5467 neon_store_reg(rd
, 0, tmp2
);
5469 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5470 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5471 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5472 neon_store_reg(rd
, 1, tmp2
);
5475 case 46: /* VCVT.F32.F16 */
5476 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5479 tmp
= neon_load_reg(rm
, 0);
5480 tmp2
= neon_load_reg(rm
, 1);
5481 tcg_gen_ext16u_i32(tmp3
, tmp
);
5482 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5483 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5484 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5485 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5486 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5488 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5489 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5490 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5491 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5492 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5493 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5499 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5500 if (op
== 30 || op
== 31 || op
>= 58) {
5501 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5502 neon_reg_offset(rm
, pass
));
5505 tmp
= neon_load_reg(rm
, pass
);
5508 case 1: /* VREV32 */
5510 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5511 case 1: gen_swap_half(tmp
); break;
5515 case 2: /* VREV16 */
5522 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5523 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5524 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5530 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5531 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5532 case 2: gen_helper_clz(tmp
, tmp
); break;
5539 gen_helper_neon_cnt_u8(tmp
, tmp
);
5544 tcg_gen_not_i32(tmp
, tmp
);
5546 case 14: /* VQABS */
5548 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5549 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5550 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5554 case 15: /* VQNEG */
5556 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5557 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5558 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5562 case 16: case 19: /* VCGT #0, VCLE #0 */
5563 tmp2
= tcg_const_i32(0);
5565 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5566 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5567 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5570 tcg_temp_free(tmp2
);
5572 tcg_gen_not_i32(tmp
, tmp
);
5574 case 17: case 20: /* VCGE #0, VCLT #0 */
5575 tmp2
= tcg_const_i32(0);
5577 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5578 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5579 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5582 tcg_temp_free(tmp2
);
5584 tcg_gen_not_i32(tmp
, tmp
);
5586 case 18: /* VCEQ #0 */
5587 tmp2
= tcg_const_i32(0);
5589 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5590 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5591 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5594 tcg_temp_free(tmp2
);
5598 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5599 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5600 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5607 tmp2
= tcg_const_i32(0);
5608 gen_neon_rsb(size
, tmp
, tmp2
);
5609 tcg_temp_free(tmp2
);
5611 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5612 tmp2
= tcg_const_i32(0);
5613 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5614 tcg_temp_free(tmp2
);
5616 tcg_gen_not_i32(tmp
, tmp
);
5618 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5619 tmp2
= tcg_const_i32(0);
5620 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5621 tcg_temp_free(tmp2
);
5623 tcg_gen_not_i32(tmp
, tmp
);
5625 case 26: /* Float VCEQ #0 */
5626 tmp2
= tcg_const_i32(0);
5627 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5628 tcg_temp_free(tmp2
);
5630 case 30: /* Float VABS */
5633 case 31: /* Float VNEG */
5637 tmp2
= neon_load_reg(rd
, pass
);
5638 neon_store_reg(rm
, pass
, tmp2
);
5641 tmp2
= neon_load_reg(rd
, pass
);
5643 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5644 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5648 neon_store_reg(rm
, pass
, tmp2
);
5650 case 56: /* Integer VRECPE */
5651 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5653 case 57: /* Integer VRSQRTE */
5654 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5656 case 58: /* Float VRECPE */
5657 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5659 case 59: /* Float VRSQRTE */
5660 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5662 case 60: /* VCVT.F32.S32 */
5665 case 61: /* VCVT.F32.U32 */
5668 case 62: /* VCVT.S32.F32 */
5671 case 63: /* VCVT.U32.F32 */
5675 /* Reserved: 21, 29, 39-56 */
5678 if (op
== 30 || op
== 31 || op
>= 58) {
5679 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5680 neon_reg_offset(rd
, pass
));
5682 neon_store_reg(rd
, pass
, tmp
);
5687 } else if ((insn
& (1 << 10)) == 0) {
5689 n
= ((insn
>> 5) & 0x18) + 8;
5690 if (insn
& (1 << 6)) {
5691 tmp
= neon_load_reg(rd
, 0);
5694 tcg_gen_movi_i32(tmp
, 0);
5696 tmp2
= neon_load_reg(rm
, 0);
5697 tmp4
= tcg_const_i32(rn
);
5698 tmp5
= tcg_const_i32(n
);
5699 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5701 if (insn
& (1 << 6)) {
5702 tmp
= neon_load_reg(rd
, 1);
5705 tcg_gen_movi_i32(tmp
, 0);
5707 tmp3
= neon_load_reg(rm
, 1);
5708 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5709 tcg_temp_free_i32(tmp5
);
5710 tcg_temp_free_i32(tmp4
);
5711 neon_store_reg(rd
, 0, tmp2
);
5712 neon_store_reg(rd
, 1, tmp3
);
5714 } else if ((insn
& 0x380) == 0) {
5716 if (insn
& (1 << 19)) {
5717 tmp
= neon_load_reg(rm
, 1);
5719 tmp
= neon_load_reg(rm
, 0);
5721 if (insn
& (1 << 16)) {
5722 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5723 } else if (insn
& (1 << 17)) {
5724 if ((insn
>> 18) & 1)
5725 gen_neon_dup_high16(tmp
);
5727 gen_neon_dup_low16(tmp
);
5729 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5731 tcg_gen_mov_i32(tmp2
, tmp
);
5732 neon_store_reg(rd
, pass
, tmp2
);
5743 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5745 int crn
= (insn
>> 16) & 0xf;
5746 int crm
= insn
& 0xf;
5747 int op1
= (insn
>> 21) & 7;
5748 int op2
= (insn
>> 5) & 7;
5749 int rt
= (insn
>> 12) & 0xf;
5752 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5753 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5757 tmp
= load_cpu_field(teecr
);
5758 store_reg(s
, rt
, tmp
);
5761 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5763 if (IS_USER(s
) && (env
->teecr
& 1))
5765 tmp
= load_cpu_field(teehbr
);
5766 store_reg(s
, rt
, tmp
);
5770 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5771 op1
, crn
, crm
, op2
);
5775 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5777 int crn
= (insn
>> 16) & 0xf;
5778 int crm
= insn
& 0xf;
5779 int op1
= (insn
>> 21) & 7;
5780 int op2
= (insn
>> 5) & 7;
5781 int rt
= (insn
>> 12) & 0xf;
5784 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5785 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5789 tmp
= load_reg(s
, rt
);
5790 gen_helper_set_teecr(cpu_env
, tmp
);
5794 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5796 if (IS_USER(s
) && (env
->teecr
& 1))
5798 tmp
= load_reg(s
, rt
);
5799 store_cpu_field(tmp
, teehbr
);
5803 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5804 op1
, crn
, crm
, op2
);
5808 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5812 cpnum
= (insn
>> 8) & 0xf;
5813 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5814 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5820 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5821 return disas_iwmmxt_insn(env
, s
, insn
);
5822 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5823 return disas_dsp_insn(env
, s
, insn
);
5828 return disas_vfp_insn (env
, s
, insn
);
5830 /* Coprocessors 7-15 are architecturally reserved by ARM.
5831 Unfortunately Intel decided to ignore this. */
5832 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5834 if (insn
& (1 << 20))
5835 return disas_cp14_read(env
, s
, insn
);
5837 return disas_cp14_write(env
, s
, insn
);
5839 return disas_cp15_insn (env
, s
, insn
);
5842 /* Unknown coprocessor. See if the board has hooked it. */
5843 return disas_cp_insn (env
, s
, insn
);
5848 /* Store a 64-bit value to a register pair. Clobbers val. */
5849 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5853 tcg_gen_trunc_i64_i32(tmp
, val
);
5854 store_reg(s
, rlow
, tmp
);
5856 tcg_gen_shri_i64(val
, val
, 32);
5857 tcg_gen_trunc_i64_i32(tmp
, val
);
5858 store_reg(s
, rhigh
, tmp
);
5861 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5862 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5867 /* Load value and extend to 64 bits. */
5868 tmp
= tcg_temp_new_i64();
5869 tmp2
= load_reg(s
, rlow
);
5870 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5872 tcg_gen_add_i64(val
, val
, tmp
);
5873 tcg_temp_free_i64(tmp
);
5876 /* load and add a 64-bit value from a register pair. */
5877 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5883 /* Load 64-bit value rd:rn. */
5884 tmpl
= load_reg(s
, rlow
);
5885 tmph
= load_reg(s
, rhigh
);
5886 tmp
= tcg_temp_new_i64();
5887 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5890 tcg_gen_add_i64(val
, val
, tmp
);
5891 tcg_temp_free_i64(tmp
);
5894 /* Set N and Z flags from a 64-bit value. */
5895 static void gen_logicq_cc(TCGv_i64 val
)
5897 TCGv tmp
= new_tmp();
5898 gen_helper_logicq_cc(tmp
, val
);
5903 /* Load/Store exclusive instructions are implemented by remembering
5904 the value/address loaded, and seeing if these are the same
5905 when the store is performed. This should be is sufficient to implement
5906 the architecturally mandated semantics, and avoids having to monitor
5909 In system emulation mode only one CPU will be running at once, so
5910 this sequence is effectively atomic. In user emulation mode we
5911 throw an exception and handle the atomic operation elsewhere. */
5912 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
5913 TCGv addr
, int size
)
5919 tmp
= gen_ld8u(addr
, IS_USER(s
));
5922 tmp
= gen_ld16u(addr
, IS_USER(s
));
5926 tmp
= gen_ld32(addr
, IS_USER(s
));
5931 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
5932 store_reg(s
, rt
, tmp
);
5934 TCGv tmp2
= new_tmp();
5935 tcg_gen_addi_i32(tmp2
, addr
, 4);
5936 tmp
= gen_ld32(tmp2
, IS_USER(s
));
5938 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
5939 store_reg(s
, rt2
, tmp
);
5941 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
5944 static void gen_clrex(DisasContext
*s
)
5946 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
5949 #ifdef CONFIG_USER_ONLY
5950 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5951 TCGv addr
, int size
)
5953 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
5954 tcg_gen_movi_i32(cpu_exclusive_info
,
5955 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
5956 gen_set_condexec(s
);
5957 gen_set_pc_im(s
->pc
- 4);
5958 gen_exception(EXCP_STREX
);
5959 s
->is_jmp
= DISAS_JUMP
;
5962 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5963 TCGv addr
, int size
)
5969 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5975 fail_label
= gen_new_label();
5976 done_label
= gen_new_label();
5977 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
5980 tmp
= gen_ld8u(addr
, IS_USER(s
));
5983 tmp
= gen_ld16u(addr
, IS_USER(s
));
5987 tmp
= gen_ld32(addr
, IS_USER(s
));
5992 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
5995 TCGv tmp2
= new_tmp();
5996 tcg_gen_addi_i32(tmp2
, addr
, 4);
5997 tmp
= gen_ld32(tmp2
, IS_USER(s
));
5999 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6002 tmp
= load_reg(s
, rt
);
6005 gen_st8(tmp
, addr
, IS_USER(s
));
6008 gen_st16(tmp
, addr
, IS_USER(s
));
6012 gen_st32(tmp
, addr
, IS_USER(s
));
6018 tcg_gen_addi_i32(addr
, addr
, 4);
6019 tmp
= load_reg(s
, rt2
);
6020 gen_st32(tmp
, addr
, IS_USER(s
));
6022 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6023 tcg_gen_br(done_label
);
6024 gen_set_label(fail_label
);
6025 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6026 gen_set_label(done_label
);
6027 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6031 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
6033 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6040 insn
= ldl_code(s
->pc
);
6043 /* M variants do not implement ARM mode. */
6048 /* Unconditional instructions. */
6049 if (((insn
>> 25) & 7) == 1) {
6050 /* NEON Data processing. */
6051 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6054 if (disas_neon_data_insn(env
, s
, insn
))
6058 if ((insn
& 0x0f100000) == 0x04000000) {
6059 /* NEON load/store. */
6060 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6063 if (disas_neon_ls_insn(env
, s
, insn
))
6067 if ((insn
& 0x0d70f000) == 0x0550f000)
6069 else if ((insn
& 0x0ffffdff) == 0x01010000) {
6072 if (insn
& (1 << 9)) {
6073 /* BE8 mode not implemented. */
6077 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6078 switch ((insn
>> 4) & 0xf) {
6087 /* We don't emulate caches so these are a no-op. */
6092 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6098 op1
= (insn
& 0x1f);
6099 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6100 addr
= load_reg(s
, 13);
6103 tmp
= tcg_const_i32(op1
);
6104 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6105 tcg_temp_free_i32(tmp
);
6107 i
= (insn
>> 23) & 3;
6109 case 0: offset
= -4; break; /* DA */
6110 case 1: offset
= 0; break; /* IA */
6111 case 2: offset
= -8; break; /* DB */
6112 case 3: offset
= 4; break; /* IB */
6116 tcg_gen_addi_i32(addr
, addr
, offset
);
6117 tmp
= load_reg(s
, 14);
6118 gen_st32(tmp
, addr
, 0);
6119 tmp
= load_cpu_field(spsr
);
6120 tcg_gen_addi_i32(addr
, addr
, 4);
6121 gen_st32(tmp
, addr
, 0);
6122 if (insn
& (1 << 21)) {
6123 /* Base writeback. */
6125 case 0: offset
= -8; break;
6126 case 1: offset
= 4; break;
6127 case 2: offset
= -4; break;
6128 case 3: offset
= 0; break;
6132 tcg_gen_addi_i32(addr
, addr
, offset
);
6133 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6134 store_reg(s
, 13, addr
);
6136 tmp
= tcg_const_i32(op1
);
6137 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6138 tcg_temp_free_i32(tmp
);
6145 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6151 rn
= (insn
>> 16) & 0xf;
6152 addr
= load_reg(s
, rn
);
6153 i
= (insn
>> 23) & 3;
6155 case 0: offset
= -4; break; /* DA */
6156 case 1: offset
= 0; break; /* IA */
6157 case 2: offset
= -8; break; /* DB */
6158 case 3: offset
= 4; break; /* IB */
6162 tcg_gen_addi_i32(addr
, addr
, offset
);
6163 /* Load PC into tmp and CPSR into tmp2. */
6164 tmp
= gen_ld32(addr
, 0);
6165 tcg_gen_addi_i32(addr
, addr
, 4);
6166 tmp2
= gen_ld32(addr
, 0);
6167 if (insn
& (1 << 21)) {
6168 /* Base writeback. */
6170 case 0: offset
= -8; break;
6171 case 1: offset
= 4; break;
6172 case 2: offset
= -4; break;
6173 case 3: offset
= 0; break;
6177 tcg_gen_addi_i32(addr
, addr
, offset
);
6178 store_reg(s
, rn
, addr
);
6182 gen_rfe(s
, tmp
, tmp2
);
6184 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6185 /* branch link and change to thumb (blx <offset>) */
6188 val
= (uint32_t)s
->pc
;
6190 tcg_gen_movi_i32(tmp
, val
);
6191 store_reg(s
, 14, tmp
);
6192 /* Sign-extend the 24-bit offset */
6193 offset
= (((int32_t)insn
) << 8) >> 8;
6194 /* offset * 4 + bit24 * 2 + (thumb bit) */
6195 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6196 /* pipeline offset */
6200 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6201 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6202 /* iWMMXt register transfer. */
6203 if (env
->cp15
.c15_cpar
& (1 << 1))
6204 if (!disas_iwmmxt_insn(env
, s
, insn
))
6207 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6208 /* Coprocessor double register transfer. */
6209 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6210 /* Additional coprocessor register transfer. */
6211 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6214 /* cps (privileged) */
6218 if (insn
& (1 << 19)) {
6219 if (insn
& (1 << 8))
6221 if (insn
& (1 << 7))
6223 if (insn
& (1 << 6))
6225 if (insn
& (1 << 18))
6228 if (insn
& (1 << 17)) {
6230 val
|= (insn
& 0x1f);
6233 gen_set_psr_im(s
, mask
, 0, val
);
6240 /* if not always execute, we generate a conditional jump to
6242 s
->condlabel
= gen_new_label();
6243 gen_test_cc(cond
^ 1, s
->condlabel
);
6246 if ((insn
& 0x0f900000) == 0x03000000) {
6247 if ((insn
& (1 << 21)) == 0) {
6249 rd
= (insn
>> 12) & 0xf;
6250 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6251 if ((insn
& (1 << 22)) == 0) {
6254 tcg_gen_movi_i32(tmp
, val
);
6257 tmp
= load_reg(s
, rd
);
6258 tcg_gen_ext16u_i32(tmp
, tmp
);
6259 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6261 store_reg(s
, rd
, tmp
);
6263 if (((insn
>> 12) & 0xf) != 0xf)
6265 if (((insn
>> 16) & 0xf) == 0) {
6266 gen_nop_hint(s
, insn
& 0xff);
6268 /* CPSR = immediate */
6270 shift
= ((insn
>> 8) & 0xf) * 2;
6272 val
= (val
>> shift
) | (val
<< (32 - shift
));
6273 i
= ((insn
& (1 << 22)) != 0);
6274 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6278 } else if ((insn
& 0x0f900000) == 0x01000000
6279 && (insn
& 0x00000090) != 0x00000090) {
6280 /* miscellaneous instructions */
6281 op1
= (insn
>> 21) & 3;
6282 sh
= (insn
>> 4) & 0xf;
6285 case 0x0: /* move program status register */
6288 tmp
= load_reg(s
, rm
);
6289 i
= ((op1
& 2) != 0);
6290 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6294 rd
= (insn
>> 12) & 0xf;
6298 tmp
= load_cpu_field(spsr
);
6301 gen_helper_cpsr_read(tmp
);
6303 store_reg(s
, rd
, tmp
);
6308 /* branch/exchange thumb (bx). */
6309 tmp
= load_reg(s
, rm
);
6311 } else if (op1
== 3) {
6313 rd
= (insn
>> 12) & 0xf;
6314 tmp
= load_reg(s
, rm
);
6315 gen_helper_clz(tmp
, tmp
);
6316 store_reg(s
, rd
, tmp
);
6324 /* Trivial implementation equivalent to bx. */
6325 tmp
= load_reg(s
, rm
);
6335 /* branch link/exchange thumb (blx) */
6336 tmp
= load_reg(s
, rm
);
6338 tcg_gen_movi_i32(tmp2
, s
->pc
);
6339 store_reg(s
, 14, tmp2
);
6342 case 0x5: /* saturating add/subtract */
6343 rd
= (insn
>> 12) & 0xf;
6344 rn
= (insn
>> 16) & 0xf;
6345 tmp
= load_reg(s
, rm
);
6346 tmp2
= load_reg(s
, rn
);
6348 gen_helper_double_saturate(tmp2
, tmp2
);
6350 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6352 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6354 store_reg(s
, rd
, tmp
);
6357 /* SMC instruction (op1 == 3)
6358 and undefined instructions (op1 == 0 || op1 == 2)
6364 gen_set_condexec(s
);
6365 gen_set_pc_im(s
->pc
- 4);
6366 gen_exception(EXCP_BKPT
);
6367 s
->is_jmp
= DISAS_JUMP
;
6369 case 0x8: /* signed multiply */
6373 rs
= (insn
>> 8) & 0xf;
6374 rn
= (insn
>> 12) & 0xf;
6375 rd
= (insn
>> 16) & 0xf;
6377 /* (32 * 16) >> 16 */
6378 tmp
= load_reg(s
, rm
);
6379 tmp2
= load_reg(s
, rs
);
6381 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6384 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6385 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6387 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6388 tcg_temp_free_i64(tmp64
);
6389 if ((sh
& 2) == 0) {
6390 tmp2
= load_reg(s
, rn
);
6391 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6394 store_reg(s
, rd
, tmp
);
6397 tmp
= load_reg(s
, rm
);
6398 tmp2
= load_reg(s
, rs
);
6399 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6402 tmp64
= tcg_temp_new_i64();
6403 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6405 gen_addq(s
, tmp64
, rn
, rd
);
6406 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6407 tcg_temp_free_i64(tmp64
);
6410 tmp2
= load_reg(s
, rn
);
6411 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6414 store_reg(s
, rd
, tmp
);
6421 } else if (((insn
& 0x0e000000) == 0 &&
6422 (insn
& 0x00000090) != 0x90) ||
6423 ((insn
& 0x0e000000) == (1 << 25))) {
6424 int set_cc
, logic_cc
, shiftop
;
6426 op1
= (insn
>> 21) & 0xf;
6427 set_cc
= (insn
>> 20) & 1;
6428 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6430 /* data processing instruction */
6431 if (insn
& (1 << 25)) {
6432 /* immediate operand */
6434 shift
= ((insn
>> 8) & 0xf) * 2;
6436 val
= (val
>> shift
) | (val
<< (32 - shift
));
6439 tcg_gen_movi_i32(tmp2
, val
);
6440 if (logic_cc
&& shift
) {
6441 gen_set_CF_bit31(tmp2
);
6446 tmp2
= load_reg(s
, rm
);
6447 shiftop
= (insn
>> 5) & 3;
6448 if (!(insn
& (1 << 4))) {
6449 shift
= (insn
>> 7) & 0x1f;
6450 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6452 rs
= (insn
>> 8) & 0xf;
6453 tmp
= load_reg(s
, rs
);
6454 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6457 if (op1
!= 0x0f && op1
!= 0x0d) {
6458 rn
= (insn
>> 16) & 0xf;
6459 tmp
= load_reg(s
, rn
);
6463 rd
= (insn
>> 12) & 0xf;
6466 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6470 store_reg_bx(env
, s
, rd
, tmp
);
6473 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6477 store_reg_bx(env
, s
, rd
, tmp
);
6480 if (set_cc
&& rd
== 15) {
6481 /* SUBS r15, ... is used for exception return. */
6485 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6486 gen_exception_return(s
, tmp
);
6489 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6491 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6493 store_reg_bx(env
, s
, rd
, tmp
);
6498 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6500 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6502 store_reg_bx(env
, s
, rd
, tmp
);
6506 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6508 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6510 store_reg_bx(env
, s
, rd
, tmp
);
6514 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6516 gen_add_carry(tmp
, tmp
, tmp2
);
6518 store_reg_bx(env
, s
, rd
, tmp
);
6522 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6524 gen_sub_carry(tmp
, tmp
, tmp2
);
6526 store_reg_bx(env
, s
, rd
, tmp
);
6530 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6532 gen_sub_carry(tmp
, tmp2
, tmp
);
6534 store_reg_bx(env
, s
, rd
, tmp
);
6538 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6545 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6552 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6558 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6563 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6567 store_reg_bx(env
, s
, rd
, tmp
);
6570 if (logic_cc
&& rd
== 15) {
6571 /* MOVS r15, ... is used for exception return. */
6575 gen_exception_return(s
, tmp2
);
6580 store_reg_bx(env
, s
, rd
, tmp2
);
6584 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6588 store_reg_bx(env
, s
, rd
, tmp
);
6592 tcg_gen_not_i32(tmp2
, tmp2
);
6596 store_reg_bx(env
, s
, rd
, tmp2
);
6599 if (op1
!= 0x0f && op1
!= 0x0d) {
6603 /* other instructions */
6604 op1
= (insn
>> 24) & 0xf;
6608 /* multiplies, extra load/stores */
6609 sh
= (insn
>> 5) & 3;
6612 rd
= (insn
>> 16) & 0xf;
6613 rn
= (insn
>> 12) & 0xf;
6614 rs
= (insn
>> 8) & 0xf;
6616 op1
= (insn
>> 20) & 0xf;
6618 case 0: case 1: case 2: case 3: case 6:
6620 tmp
= load_reg(s
, rs
);
6621 tmp2
= load_reg(s
, rm
);
6622 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6624 if (insn
& (1 << 22)) {
6625 /* Subtract (mls) */
6627 tmp2
= load_reg(s
, rn
);
6628 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6630 } else if (insn
& (1 << 21)) {
6632 tmp2
= load_reg(s
, rn
);
6633 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6636 if (insn
& (1 << 20))
6638 store_reg(s
, rd
, tmp
);
6642 tmp
= load_reg(s
, rs
);
6643 tmp2
= load_reg(s
, rm
);
6644 if (insn
& (1 << 22))
6645 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6647 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6648 if (insn
& (1 << 21)) /* mult accumulate */
6649 gen_addq(s
, tmp64
, rn
, rd
);
6650 if (!(insn
& (1 << 23))) { /* double accumulate */
6652 gen_addq_lo(s
, tmp64
, rn
);
6653 gen_addq_lo(s
, tmp64
, rd
);
6655 if (insn
& (1 << 20))
6656 gen_logicq_cc(tmp64
);
6657 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6658 tcg_temp_free_i64(tmp64
);
6662 rn
= (insn
>> 16) & 0xf;
6663 rd
= (insn
>> 12) & 0xf;
6664 if (insn
& (1 << 23)) {
6665 /* load/store exclusive */
6666 op1
= (insn
>> 21) & 0x3;
6671 addr
= tcg_temp_local_new_i32();
6672 load_reg_var(s
, addr
, rn
);
6673 if (insn
& (1 << 20)) {
6676 gen_load_exclusive(s
, rd
, 15, addr
, 2);
6678 case 1: /* ldrexd */
6679 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
6681 case 2: /* ldrexb */
6682 gen_load_exclusive(s
, rd
, 15, addr
, 0);
6684 case 3: /* ldrexh */
6685 gen_load_exclusive(s
, rd
, 15, addr
, 1);
6694 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
6696 case 1: /* strexd */
6697 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
6699 case 2: /* strexb */
6700 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
6702 case 3: /* strexh */
6703 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
6709 tcg_temp_free(addr
);
6711 /* SWP instruction */
6714 /* ??? This is not really atomic. However we know
6715 we never have multiple CPUs running in parallel,
6716 so it is good enough. */
6717 addr
= load_reg(s
, rn
);
6718 tmp
= load_reg(s
, rm
);
6719 if (insn
& (1 << 22)) {
6720 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6721 gen_st8(tmp
, addr
, IS_USER(s
));
6723 tmp2
= gen_ld32(addr
, IS_USER(s
));
6724 gen_st32(tmp
, addr
, IS_USER(s
));
6727 store_reg(s
, rd
, tmp2
);
6733 /* Misc load/store */
6734 rn
= (insn
>> 16) & 0xf;
6735 rd
= (insn
>> 12) & 0xf;
6736 addr
= load_reg(s
, rn
);
6737 if (insn
& (1 << 24))
6738 gen_add_datah_offset(s
, insn
, 0, addr
);
6740 if (insn
& (1 << 20)) {
6744 tmp
= gen_ld16u(addr
, IS_USER(s
));
6747 tmp
= gen_ld8s(addr
, IS_USER(s
));
6751 tmp
= gen_ld16s(addr
, IS_USER(s
));
6755 } else if (sh
& 2) {
6759 tmp
= load_reg(s
, rd
);
6760 gen_st32(tmp
, addr
, IS_USER(s
));
6761 tcg_gen_addi_i32(addr
, addr
, 4);
6762 tmp
= load_reg(s
, rd
+ 1);
6763 gen_st32(tmp
, addr
, IS_USER(s
));
6767 tmp
= gen_ld32(addr
, IS_USER(s
));
6768 store_reg(s
, rd
, tmp
);
6769 tcg_gen_addi_i32(addr
, addr
, 4);
6770 tmp
= gen_ld32(addr
, IS_USER(s
));
6774 address_offset
= -4;
6777 tmp
= load_reg(s
, rd
);
6778 gen_st16(tmp
, addr
, IS_USER(s
));
6781 /* Perform base writeback before the loaded value to
6782 ensure correct behavior with overlapping index registers.
6783 ldrd with base writeback is is undefined if the
6784 destination and index registers overlap. */
6785 if (!(insn
& (1 << 24))) {
6786 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6787 store_reg(s
, rn
, addr
);
6788 } else if (insn
& (1 << 21)) {
6790 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6791 store_reg(s
, rn
, addr
);
6796 /* Complete the load. */
6797 store_reg(s
, rd
, tmp
);
6806 if (insn
& (1 << 4)) {
6808 /* Armv6 Media instructions. */
6810 rn
= (insn
>> 16) & 0xf;
6811 rd
= (insn
>> 12) & 0xf;
6812 rs
= (insn
>> 8) & 0xf;
6813 switch ((insn
>> 23) & 3) {
6814 case 0: /* Parallel add/subtract. */
6815 op1
= (insn
>> 20) & 7;
6816 tmp
= load_reg(s
, rn
);
6817 tmp2
= load_reg(s
, rm
);
6818 sh
= (insn
>> 5) & 7;
6819 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6821 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6823 store_reg(s
, rd
, tmp
);
6826 if ((insn
& 0x00700020) == 0) {
6827 /* Halfword pack. */
6828 tmp
= load_reg(s
, rn
);
6829 tmp2
= load_reg(s
, rm
);
6830 shift
= (insn
>> 7) & 0x1f;
6831 if (insn
& (1 << 6)) {
6835 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6836 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6837 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6841 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6842 tcg_gen_ext16u_i32(tmp
, tmp
);
6843 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6845 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6847 store_reg(s
, rd
, tmp
);
6848 } else if ((insn
& 0x00200020) == 0x00200000) {
6850 tmp
= load_reg(s
, rm
);
6851 shift
= (insn
>> 7) & 0x1f;
6852 if (insn
& (1 << 6)) {
6855 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6857 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6859 sh
= (insn
>> 16) & 0x1f;
6861 tmp2
= tcg_const_i32(sh
);
6862 if (insn
& (1 << 22))
6863 gen_helper_usat(tmp
, tmp
, tmp2
);
6865 gen_helper_ssat(tmp
, tmp
, tmp2
);
6866 tcg_temp_free_i32(tmp2
);
6868 store_reg(s
, rd
, tmp
);
6869 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6871 tmp
= load_reg(s
, rm
);
6872 sh
= (insn
>> 16) & 0x1f;
6874 tmp2
= tcg_const_i32(sh
);
6875 if (insn
& (1 << 22))
6876 gen_helper_usat16(tmp
, tmp
, tmp2
);
6878 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6879 tcg_temp_free_i32(tmp2
);
6881 store_reg(s
, rd
, tmp
);
6882 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6884 tmp
= load_reg(s
, rn
);
6885 tmp2
= load_reg(s
, rm
);
6887 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6888 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6891 store_reg(s
, rd
, tmp
);
6892 } else if ((insn
& 0x000003e0) == 0x00000060) {
6893 tmp
= load_reg(s
, rm
);
6894 shift
= (insn
>> 10) & 3;
6895 /* ??? In many cases it's not neccessary to do a
6896 rotate, a shift is sufficient. */
6898 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6899 op1
= (insn
>> 20) & 7;
6901 case 0: gen_sxtb16(tmp
); break;
6902 case 2: gen_sxtb(tmp
); break;
6903 case 3: gen_sxth(tmp
); break;
6904 case 4: gen_uxtb16(tmp
); break;
6905 case 6: gen_uxtb(tmp
); break;
6906 case 7: gen_uxth(tmp
); break;
6907 default: goto illegal_op
;
6910 tmp2
= load_reg(s
, rn
);
6911 if ((op1
& 3) == 0) {
6912 gen_add16(tmp
, tmp2
);
6914 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6918 store_reg(s
, rd
, tmp
);
6919 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6921 tmp
= load_reg(s
, rm
);
6922 if (insn
& (1 << 22)) {
6923 if (insn
& (1 << 7)) {
6927 gen_helper_rbit(tmp
, tmp
);
6930 if (insn
& (1 << 7))
6933 tcg_gen_bswap32_i32(tmp
, tmp
);
6935 store_reg(s
, rd
, tmp
);
6940 case 2: /* Multiplies (Type 3). */
6941 tmp
= load_reg(s
, rm
);
6942 tmp2
= load_reg(s
, rs
);
6943 if (insn
& (1 << 20)) {
6944 /* Signed multiply most significant [accumulate]. */
6945 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6946 if (insn
& (1 << 5))
6947 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6948 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6950 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6951 tcg_temp_free_i64(tmp64
);
6953 tmp2
= load_reg(s
, rd
);
6954 if (insn
& (1 << 6)) {
6955 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6957 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6961 store_reg(s
, rn
, tmp
);
6963 if (insn
& (1 << 5))
6964 gen_swap_half(tmp2
);
6965 gen_smul_dual(tmp
, tmp2
);
6966 /* This addition cannot overflow. */
6967 if (insn
& (1 << 6)) {
6968 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6970 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6973 if (insn
& (1 << 22)) {
6974 /* smlald, smlsld */
6975 tmp64
= tcg_temp_new_i64();
6976 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6978 gen_addq(s
, tmp64
, rd
, rn
);
6979 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6980 tcg_temp_free_i64(tmp64
);
6982 /* smuad, smusd, smlad, smlsd */
6985 tmp2
= load_reg(s
, rd
);
6986 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6989 store_reg(s
, rn
, tmp
);
6994 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6996 case 0: /* Unsigned sum of absolute differences. */
6998 tmp
= load_reg(s
, rm
);
6999 tmp2
= load_reg(s
, rs
);
7000 gen_helper_usad8(tmp
, tmp
, tmp2
);
7003 tmp2
= load_reg(s
, rd
);
7004 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7007 store_reg(s
, rn
, tmp
);
7009 case 0x20: case 0x24: case 0x28: case 0x2c:
7010 /* Bitfield insert/clear. */
7012 shift
= (insn
>> 7) & 0x1f;
7013 i
= (insn
>> 16) & 0x1f;
7017 tcg_gen_movi_i32(tmp
, 0);
7019 tmp
= load_reg(s
, rm
);
7022 tmp2
= load_reg(s
, rd
);
7023 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
7026 store_reg(s
, rd
, tmp
);
7028 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7029 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7031 tmp
= load_reg(s
, rm
);
7032 shift
= (insn
>> 7) & 0x1f;
7033 i
= ((insn
>> 16) & 0x1f) + 1;
7038 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7040 gen_sbfx(tmp
, shift
, i
);
7043 store_reg(s
, rd
, tmp
);
7053 /* Check for undefined extension instructions
7054 * per the ARM Bible IE:
7055 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7057 sh
= (0xf << 20) | (0xf << 4);
7058 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7062 /* load/store byte/word */
7063 rn
= (insn
>> 16) & 0xf;
7064 rd
= (insn
>> 12) & 0xf;
7065 tmp2
= load_reg(s
, rn
);
7066 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7067 if (insn
& (1 << 24))
7068 gen_add_data_offset(s
, insn
, tmp2
);
7069 if (insn
& (1 << 20)) {
7071 if (insn
& (1 << 22)) {
7072 tmp
= gen_ld8u(tmp2
, i
);
7074 tmp
= gen_ld32(tmp2
, i
);
7078 tmp
= load_reg(s
, rd
);
7079 if (insn
& (1 << 22))
7080 gen_st8(tmp
, tmp2
, i
);
7082 gen_st32(tmp
, tmp2
, i
);
7084 if (!(insn
& (1 << 24))) {
7085 gen_add_data_offset(s
, insn
, tmp2
);
7086 store_reg(s
, rn
, tmp2
);
7087 } else if (insn
& (1 << 21)) {
7088 store_reg(s
, rn
, tmp2
);
7092 if (insn
& (1 << 20)) {
7093 /* Complete the load. */
7097 store_reg(s
, rd
, tmp
);
7103 int j
, n
, user
, loaded_base
;
7105 /* load/store multiple words */
7106 /* XXX: store correct base if write back */
7108 if (insn
& (1 << 22)) {
7110 goto illegal_op
; /* only usable in supervisor mode */
7112 if ((insn
& (1 << 15)) == 0)
7115 rn
= (insn
>> 16) & 0xf;
7116 addr
= load_reg(s
, rn
);
7118 /* compute total size */
7120 TCGV_UNUSED(loaded_var
);
7123 if (insn
& (1 << i
))
7126 /* XXX: test invalid n == 0 case ? */
7127 if (insn
& (1 << 23)) {
7128 if (insn
& (1 << 24)) {
7130 tcg_gen_addi_i32(addr
, addr
, 4);
7132 /* post increment */
7135 if (insn
& (1 << 24)) {
7137 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7139 /* post decrement */
7141 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7146 if (insn
& (1 << i
)) {
7147 if (insn
& (1 << 20)) {
7149 tmp
= gen_ld32(addr
, IS_USER(s
));
7153 tmp2
= tcg_const_i32(i
);
7154 gen_helper_set_user_reg(tmp2
, tmp
);
7155 tcg_temp_free_i32(tmp2
);
7157 } else if (i
== rn
) {
7161 store_reg(s
, i
, tmp
);
7166 /* special case: r15 = PC + 8 */
7167 val
= (long)s
->pc
+ 4;
7169 tcg_gen_movi_i32(tmp
, val
);
7172 tmp2
= tcg_const_i32(i
);
7173 gen_helper_get_user_reg(tmp
, tmp2
);
7174 tcg_temp_free_i32(tmp2
);
7176 tmp
= load_reg(s
, i
);
7178 gen_st32(tmp
, addr
, IS_USER(s
));
7181 /* no need to add after the last transfer */
7183 tcg_gen_addi_i32(addr
, addr
, 4);
7186 if (insn
& (1 << 21)) {
7188 if (insn
& (1 << 23)) {
7189 if (insn
& (1 << 24)) {
7192 /* post increment */
7193 tcg_gen_addi_i32(addr
, addr
, 4);
7196 if (insn
& (1 << 24)) {
7199 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7201 /* post decrement */
7202 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7205 store_reg(s
, rn
, addr
);
7210 store_reg(s
, rn
, loaded_var
);
7212 if ((insn
& (1 << 22)) && !user
) {
7213 /* Restore CPSR from SPSR. */
7214 tmp
= load_cpu_field(spsr
);
7215 gen_set_cpsr(tmp
, 0xffffffff);
7217 s
->is_jmp
= DISAS_UPDATE
;
7226 /* branch (and link) */
7227 val
= (int32_t)s
->pc
;
7228 if (insn
& (1 << 24)) {
7230 tcg_gen_movi_i32(tmp
, val
);
7231 store_reg(s
, 14, tmp
);
7233 offset
= (((int32_t)insn
<< 8) >> 8);
7234 val
+= (offset
<< 2) + 4;
7242 if (disas_coproc_insn(env
, s
, insn
))
7247 gen_set_pc_im(s
->pc
);
7248 s
->is_jmp
= DISAS_SWI
;
7252 gen_set_condexec(s
);
7253 gen_set_pc_im(s
->pc
- 4);
7254 gen_exception(EXCP_UDEF
);
7255 s
->is_jmp
= DISAS_JUMP
;
7261 /* Return true if this is a Thumb-2 logical op. */
7263 thumb2_logic_op(int op
)
7268 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7269 then set condition code flags based on the result of the operation.
7270 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7271 to the high bit of T1.
7272 Returns zero if the opcode is valid. */
7275 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7282 tcg_gen_and_i32(t0
, t0
, t1
);
7286 tcg_gen_andc_i32(t0
, t0
, t1
);
7290 tcg_gen_or_i32(t0
, t0
, t1
);
7294 tcg_gen_not_i32(t1
, t1
);
7295 tcg_gen_or_i32(t0
, t0
, t1
);
7299 tcg_gen_xor_i32(t0
, t0
, t1
);
7304 gen_helper_add_cc(t0
, t0
, t1
);
7306 tcg_gen_add_i32(t0
, t0
, t1
);
7310 gen_helper_adc_cc(t0
, t0
, t1
);
7316 gen_helper_sbc_cc(t0
, t0
, t1
);
7318 gen_sub_carry(t0
, t0
, t1
);
7322 gen_helper_sub_cc(t0
, t0
, t1
);
7324 tcg_gen_sub_i32(t0
, t0
, t1
);
7328 gen_helper_sub_cc(t0
, t1
, t0
);
7330 tcg_gen_sub_i32(t0
, t1
, t0
);
7332 default: /* 5, 6, 7, 9, 12, 15. */
7338 gen_set_CF_bit31(t1
);
7343 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7345 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7347 uint32_t insn
, imm
, shift
, offset
;
7348 uint32_t rd
, rn
, rm
, rs
;
7359 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7360 || arm_feature (env
, ARM_FEATURE_M
))) {
7361 /* Thumb-1 cores may need to treat bl and blx as a pair of
7362 16-bit instructions to get correct prefetch abort behavior. */
7364 if ((insn
& (1 << 12)) == 0) {
7365 /* Second half of blx. */
7366 offset
= ((insn
& 0x7ff) << 1);
7367 tmp
= load_reg(s
, 14);
7368 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7369 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7372 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7373 store_reg(s
, 14, tmp2
);
7377 if (insn
& (1 << 11)) {
7378 /* Second half of bl. */
7379 offset
= ((insn
& 0x7ff) << 1) | 1;
7380 tmp
= load_reg(s
, 14);
7381 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7384 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7385 store_reg(s
, 14, tmp2
);
7389 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7390 /* Instruction spans a page boundary. Implement it as two
7391 16-bit instructions in case the second half causes an
7393 offset
= ((int32_t)insn
<< 21) >> 9;
7394 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7397 /* Fall through to 32-bit decode. */
7400 insn
= lduw_code(s
->pc
);
7402 insn
|= (uint32_t)insn_hw1
<< 16;
7404 if ((insn
& 0xf800e800) != 0xf000e800) {
7408 rn
= (insn
>> 16) & 0xf;
7409 rs
= (insn
>> 12) & 0xf;
7410 rd
= (insn
>> 8) & 0xf;
7412 switch ((insn
>> 25) & 0xf) {
7413 case 0: case 1: case 2: case 3:
7414 /* 16-bit instructions. Should never happen. */
7417 if (insn
& (1 << 22)) {
7418 /* Other load/store, table branch. */
7419 if (insn
& 0x01200000) {
7420 /* Load/store doubleword. */
7423 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7425 addr
= load_reg(s
, rn
);
7427 offset
= (insn
& 0xff) * 4;
7428 if ((insn
& (1 << 23)) == 0)
7430 if (insn
& (1 << 24)) {
7431 tcg_gen_addi_i32(addr
, addr
, offset
);
7434 if (insn
& (1 << 20)) {
7436 tmp
= gen_ld32(addr
, IS_USER(s
));
7437 store_reg(s
, rs
, tmp
);
7438 tcg_gen_addi_i32(addr
, addr
, 4);
7439 tmp
= gen_ld32(addr
, IS_USER(s
));
7440 store_reg(s
, rd
, tmp
);
7443 tmp
= load_reg(s
, rs
);
7444 gen_st32(tmp
, addr
, IS_USER(s
));
7445 tcg_gen_addi_i32(addr
, addr
, 4);
7446 tmp
= load_reg(s
, rd
);
7447 gen_st32(tmp
, addr
, IS_USER(s
));
7449 if (insn
& (1 << 21)) {
7450 /* Base writeback. */
7453 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7454 store_reg(s
, rn
, addr
);
7458 } else if ((insn
& (1 << 23)) == 0) {
7459 /* Load/store exclusive word. */
7460 addr
= tcg_temp_local_new();
7461 load_reg_var(s
, addr
, rn
);
7462 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
7463 if (insn
& (1 << 20)) {
7464 gen_load_exclusive(s
, rs
, 15, addr
, 2);
7466 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
7468 tcg_temp_free(addr
);
7469 } else if ((insn
& (1 << 6)) == 0) {
7473 tcg_gen_movi_i32(addr
, s
->pc
);
7475 addr
= load_reg(s
, rn
);
7477 tmp
= load_reg(s
, rm
);
7478 tcg_gen_add_i32(addr
, addr
, tmp
);
7479 if (insn
& (1 << 4)) {
7481 tcg_gen_add_i32(addr
, addr
, tmp
);
7483 tmp
= gen_ld16u(addr
, IS_USER(s
));
7486 tmp
= gen_ld8u(addr
, IS_USER(s
));
7489 tcg_gen_shli_i32(tmp
, tmp
, 1);
7490 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7491 store_reg(s
, 15, tmp
);
7493 /* Load/store exclusive byte/halfword/doubleword. */
7495 op
= (insn
>> 4) & 0x3;
7499 addr
= tcg_temp_local_new();
7500 load_reg_var(s
, addr
, rn
);
7501 if (insn
& (1 << 20)) {
7502 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
7504 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
7506 tcg_temp_free(addr
);
7509 /* Load/store multiple, RFE, SRS. */
7510 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7511 /* Not available in user mode. */
7514 if (insn
& (1 << 20)) {
7516 addr
= load_reg(s
, rn
);
7517 if ((insn
& (1 << 24)) == 0)
7518 tcg_gen_addi_i32(addr
, addr
, -8);
7519 /* Load PC into tmp and CPSR into tmp2. */
7520 tmp
= gen_ld32(addr
, 0);
7521 tcg_gen_addi_i32(addr
, addr
, 4);
7522 tmp2
= gen_ld32(addr
, 0);
7523 if (insn
& (1 << 21)) {
7524 /* Base writeback. */
7525 if (insn
& (1 << 24)) {
7526 tcg_gen_addi_i32(addr
, addr
, 4);
7528 tcg_gen_addi_i32(addr
, addr
, -4);
7530 store_reg(s
, rn
, addr
);
7534 gen_rfe(s
, tmp
, tmp2
);
7538 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7539 addr
= load_reg(s
, 13);
7542 tmp
= tcg_const_i32(op
);
7543 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7544 tcg_temp_free_i32(tmp
);
7546 if ((insn
& (1 << 24)) == 0) {
7547 tcg_gen_addi_i32(addr
, addr
, -8);
7549 tmp
= load_reg(s
, 14);
7550 gen_st32(tmp
, addr
, 0);
7551 tcg_gen_addi_i32(addr
, addr
, 4);
7553 gen_helper_cpsr_read(tmp
);
7554 gen_st32(tmp
, addr
, 0);
7555 if (insn
& (1 << 21)) {
7556 if ((insn
& (1 << 24)) == 0) {
7557 tcg_gen_addi_i32(addr
, addr
, -4);
7559 tcg_gen_addi_i32(addr
, addr
, 4);
7561 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7562 store_reg(s
, 13, addr
);
7564 tmp
= tcg_const_i32(op
);
7565 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7566 tcg_temp_free_i32(tmp
);
7574 /* Load/store multiple. */
7575 addr
= load_reg(s
, rn
);
7577 for (i
= 0; i
< 16; i
++) {
7578 if (insn
& (1 << i
))
7581 if (insn
& (1 << 24)) {
7582 tcg_gen_addi_i32(addr
, addr
, -offset
);
7585 for (i
= 0; i
< 16; i
++) {
7586 if ((insn
& (1 << i
)) == 0)
7588 if (insn
& (1 << 20)) {
7590 tmp
= gen_ld32(addr
, IS_USER(s
));
7594 store_reg(s
, i
, tmp
);
7598 tmp
= load_reg(s
, i
);
7599 gen_st32(tmp
, addr
, IS_USER(s
));
7601 tcg_gen_addi_i32(addr
, addr
, 4);
7603 if (insn
& (1 << 21)) {
7604 /* Base register writeback. */
7605 if (insn
& (1 << 24)) {
7606 tcg_gen_addi_i32(addr
, addr
, -offset
);
7608 /* Fault if writeback register is in register list. */
7609 if (insn
& (1 << rn
))
7611 store_reg(s
, rn
, addr
);
7620 op
= (insn
>> 21) & 0xf;
7622 /* Halfword pack. */
7623 tmp
= load_reg(s
, rn
);
7624 tmp2
= load_reg(s
, rm
);
7625 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
7626 if (insn
& (1 << 5)) {
7630 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7631 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7632 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7636 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7637 tcg_gen_ext16u_i32(tmp
, tmp
);
7638 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7640 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7642 store_reg(s
, rd
, tmp
);
7644 /* Data processing register constant shift. */
7647 tcg_gen_movi_i32(tmp
, 0);
7649 tmp
= load_reg(s
, rn
);
7651 tmp2
= load_reg(s
, rm
);
7653 shiftop
= (insn
>> 4) & 3;
7654 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7655 conds
= (insn
& (1 << 20)) != 0;
7656 logic_cc
= (conds
&& thumb2_logic_op(op
));
7657 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7658 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7662 store_reg(s
, rd
, tmp
);
7668 case 13: /* Misc data processing. */
7669 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7670 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7673 case 0: /* Register controlled shift. */
7674 tmp
= load_reg(s
, rn
);
7675 tmp2
= load_reg(s
, rm
);
7676 if ((insn
& 0x70) != 0)
7678 op
= (insn
>> 21) & 3;
7679 logic_cc
= (insn
& (1 << 20)) != 0;
7680 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7683 store_reg_bx(env
, s
, rd
, tmp
);
7685 case 1: /* Sign/zero extend. */
7686 tmp
= load_reg(s
, rm
);
7687 shift
= (insn
>> 4) & 3;
7688 /* ??? In many cases it's not neccessary to do a
7689 rotate, a shift is sufficient. */
7691 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7692 op
= (insn
>> 20) & 7;
7694 case 0: gen_sxth(tmp
); break;
7695 case 1: gen_uxth(tmp
); break;
7696 case 2: gen_sxtb16(tmp
); break;
7697 case 3: gen_uxtb16(tmp
); break;
7698 case 4: gen_sxtb(tmp
); break;
7699 case 5: gen_uxtb(tmp
); break;
7700 default: goto illegal_op
;
7703 tmp2
= load_reg(s
, rn
);
7704 if ((op
>> 1) == 1) {
7705 gen_add16(tmp
, tmp2
);
7707 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7711 store_reg(s
, rd
, tmp
);
7713 case 2: /* SIMD add/subtract. */
7714 op
= (insn
>> 20) & 7;
7715 shift
= (insn
>> 4) & 7;
7716 if ((op
& 3) == 3 || (shift
& 3) == 3)
7718 tmp
= load_reg(s
, rn
);
7719 tmp2
= load_reg(s
, rm
);
7720 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7722 store_reg(s
, rd
, tmp
);
7724 case 3: /* Other data processing. */
7725 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7727 /* Saturating add/subtract. */
7728 tmp
= load_reg(s
, rn
);
7729 tmp2
= load_reg(s
, rm
);
7731 gen_helper_double_saturate(tmp
, tmp
);
7733 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7735 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7738 tmp
= load_reg(s
, rn
);
7740 case 0x0a: /* rbit */
7741 gen_helper_rbit(tmp
, tmp
);
7743 case 0x08: /* rev */
7744 tcg_gen_bswap32_i32(tmp
, tmp
);
7746 case 0x09: /* rev16 */
7749 case 0x0b: /* revsh */
7752 case 0x10: /* sel */
7753 tmp2
= load_reg(s
, rm
);
7755 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7756 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7760 case 0x18: /* clz */
7761 gen_helper_clz(tmp
, tmp
);
7767 store_reg(s
, rd
, tmp
);
7769 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7770 op
= (insn
>> 4) & 0xf;
7771 tmp
= load_reg(s
, rn
);
7772 tmp2
= load_reg(s
, rm
);
7773 switch ((insn
>> 20) & 7) {
7774 case 0: /* 32 x 32 -> 32 */
7775 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7778 tmp2
= load_reg(s
, rs
);
7780 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7782 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7786 case 1: /* 16 x 16 -> 32 */
7787 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7790 tmp2
= load_reg(s
, rs
);
7791 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7795 case 2: /* Dual multiply add. */
7796 case 4: /* Dual multiply subtract. */
7798 gen_swap_half(tmp2
);
7799 gen_smul_dual(tmp
, tmp2
);
7800 /* This addition cannot overflow. */
7801 if (insn
& (1 << 22)) {
7802 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7804 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7809 tmp2
= load_reg(s
, rs
);
7810 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7814 case 3: /* 32 * 16 -> 32msb */
7816 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7819 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7820 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7822 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7823 tcg_temp_free_i64(tmp64
);
7826 tmp2
= load_reg(s
, rs
);
7827 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7831 case 5: case 6: /* 32 * 32 -> 32msb */
7832 gen_imull(tmp
, tmp2
);
7833 if (insn
& (1 << 5)) {
7834 gen_roundqd(tmp
, tmp2
);
7841 tmp2
= load_reg(s
, rs
);
7842 if (insn
& (1 << 21)) {
7843 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7845 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7850 case 7: /* Unsigned sum of absolute differences. */
7851 gen_helper_usad8(tmp
, tmp
, tmp2
);
7854 tmp2
= load_reg(s
, rs
);
7855 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7860 store_reg(s
, rd
, tmp
);
7862 case 6: case 7: /* 64-bit multiply, Divide. */
7863 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7864 tmp
= load_reg(s
, rn
);
7865 tmp2
= load_reg(s
, rm
);
7866 if ((op
& 0x50) == 0x10) {
7868 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7871 gen_helper_udiv(tmp
, tmp
, tmp2
);
7873 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7875 store_reg(s
, rd
, tmp
);
7876 } else if ((op
& 0xe) == 0xc) {
7877 /* Dual multiply accumulate long. */
7879 gen_swap_half(tmp2
);
7880 gen_smul_dual(tmp
, tmp2
);
7882 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7884 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7888 tmp64
= tcg_temp_new_i64();
7889 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7891 gen_addq(s
, tmp64
, rs
, rd
);
7892 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7893 tcg_temp_free_i64(tmp64
);
7896 /* Unsigned 64-bit multiply */
7897 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7901 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7903 tmp64
= tcg_temp_new_i64();
7904 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7907 /* Signed 64-bit multiply */
7908 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7913 gen_addq_lo(s
, tmp64
, rs
);
7914 gen_addq_lo(s
, tmp64
, rd
);
7915 } else if (op
& 0x40) {
7916 /* 64-bit accumulate. */
7917 gen_addq(s
, tmp64
, rs
, rd
);
7919 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7920 tcg_temp_free_i64(tmp64
);
7925 case 6: case 7: case 14: case 15:
7927 if (((insn
>> 24) & 3) == 3) {
7928 /* Translate into the equivalent ARM encoding. */
7929 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7930 if (disas_neon_data_insn(env
, s
, insn
))
7933 if (insn
& (1 << 28))
7935 if (disas_coproc_insn (env
, s
, insn
))
7939 case 8: case 9: case 10: case 11:
7940 if (insn
& (1 << 15)) {
7941 /* Branches, misc control. */
7942 if (insn
& 0x5000) {
7943 /* Unconditional branch. */
7944 /* signextend(hw1[10:0]) -> offset[:12]. */
7945 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7946 /* hw1[10:0] -> offset[11:1]. */
7947 offset
|= (insn
& 0x7ff) << 1;
7948 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7949 offset[24:22] already have the same value because of the
7950 sign extension above. */
7951 offset
^= ((~insn
) & (1 << 13)) << 10;
7952 offset
^= ((~insn
) & (1 << 11)) << 11;
7954 if (insn
& (1 << 14)) {
7955 /* Branch and link. */
7956 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7960 if (insn
& (1 << 12)) {
7965 offset
&= ~(uint32_t)2;
7966 gen_bx_im(s
, offset
);
7968 } else if (((insn
>> 23) & 7) == 7) {
7970 if (insn
& (1 << 13))
7973 if (insn
& (1 << 26)) {
7974 /* Secure monitor call (v6Z) */
7975 goto illegal_op
; /* not implemented. */
7977 op
= (insn
>> 20) & 7;
7979 case 0: /* msr cpsr. */
7981 tmp
= load_reg(s
, rn
);
7982 addr
= tcg_const_i32(insn
& 0xff);
7983 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7984 tcg_temp_free_i32(addr
);
7990 case 1: /* msr spsr. */
7993 tmp
= load_reg(s
, rn
);
7995 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7999 case 2: /* cps, nop-hint. */
8000 if (((insn
>> 8) & 7) == 0) {
8001 gen_nop_hint(s
, insn
& 0xff);
8003 /* Implemented as NOP in user mode. */
8008 if (insn
& (1 << 10)) {
8009 if (insn
& (1 << 7))
8011 if (insn
& (1 << 6))
8013 if (insn
& (1 << 5))
8015 if (insn
& (1 << 9))
8016 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8018 if (insn
& (1 << 8)) {
8020 imm
|= (insn
& 0x1f);
8023 gen_set_psr_im(s
, offset
, 0, imm
);
8026 case 3: /* Special control operations. */
8028 op
= (insn
>> 4) & 0xf;
8036 /* These execute as NOPs. */
8043 /* Trivial implementation equivalent to bx. */
8044 tmp
= load_reg(s
, rn
);
8047 case 5: /* Exception return. */
8051 if (rn
!= 14 || rd
!= 15) {
8054 tmp
= load_reg(s
, rn
);
8055 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8056 gen_exception_return(s
, tmp
);
8058 case 6: /* mrs cpsr. */
8061 addr
= tcg_const_i32(insn
& 0xff);
8062 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8063 tcg_temp_free_i32(addr
);
8065 gen_helper_cpsr_read(tmp
);
8067 store_reg(s
, rd
, tmp
);
8069 case 7: /* mrs spsr. */
8070 /* Not accessible in user mode. */
8071 if (IS_USER(s
) || IS_M(env
))
8073 tmp
= load_cpu_field(spsr
);
8074 store_reg(s
, rd
, tmp
);
8079 /* Conditional branch. */
8080 op
= (insn
>> 22) & 0xf;
8081 /* Generate a conditional jump to next instruction. */
8082 s
->condlabel
= gen_new_label();
8083 gen_test_cc(op
^ 1, s
->condlabel
);
8086 /* offset[11:1] = insn[10:0] */
8087 offset
= (insn
& 0x7ff) << 1;
8088 /* offset[17:12] = insn[21:16]. */
8089 offset
|= (insn
& 0x003f0000) >> 4;
8090 /* offset[31:20] = insn[26]. */
8091 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8092 /* offset[18] = insn[13]. */
8093 offset
|= (insn
& (1 << 13)) << 5;
8094 /* offset[19] = insn[11]. */
8095 offset
|= (insn
& (1 << 11)) << 8;
8097 /* jump to the offset */
8098 gen_jmp(s
, s
->pc
+ offset
);
8101 /* Data processing immediate. */
8102 if (insn
& (1 << 25)) {
8103 if (insn
& (1 << 24)) {
8104 if (insn
& (1 << 20))
8106 /* Bitfield/Saturate. */
8107 op
= (insn
>> 21) & 7;
8109 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8112 tcg_gen_movi_i32(tmp
, 0);
8114 tmp
= load_reg(s
, rn
);
8117 case 2: /* Signed bitfield extract. */
8119 if (shift
+ imm
> 32)
8122 gen_sbfx(tmp
, shift
, imm
);
8124 case 6: /* Unsigned bitfield extract. */
8126 if (shift
+ imm
> 32)
8129 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8131 case 3: /* Bitfield insert/clear. */
8134 imm
= imm
+ 1 - shift
;
8136 tmp2
= load_reg(s
, rd
);
8137 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
8143 default: /* Saturate. */
8146 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8148 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8150 tmp2
= tcg_const_i32(imm
);
8153 if ((op
& 1) && shift
== 0)
8154 gen_helper_usat16(tmp
, tmp
, tmp2
);
8156 gen_helper_usat(tmp
, tmp
, tmp2
);
8159 if ((op
& 1) && shift
== 0)
8160 gen_helper_ssat16(tmp
, tmp
, tmp2
);
8162 gen_helper_ssat(tmp
, tmp
, tmp2
);
8164 tcg_temp_free_i32(tmp2
);
8167 store_reg(s
, rd
, tmp
);
8169 imm
= ((insn
& 0x04000000) >> 15)
8170 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8171 if (insn
& (1 << 22)) {
8172 /* 16-bit immediate. */
8173 imm
|= (insn
>> 4) & 0xf000;
8174 if (insn
& (1 << 23)) {
8176 tmp
= load_reg(s
, rd
);
8177 tcg_gen_ext16u_i32(tmp
, tmp
);
8178 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8182 tcg_gen_movi_i32(tmp
, imm
);
8185 /* Add/sub 12-bit immediate. */
8187 offset
= s
->pc
& ~(uint32_t)3;
8188 if (insn
& (1 << 23))
8193 tcg_gen_movi_i32(tmp
, offset
);
8195 tmp
= load_reg(s
, rn
);
8196 if (insn
& (1 << 23))
8197 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8199 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8202 store_reg(s
, rd
, tmp
);
8205 int shifter_out
= 0;
8206 /* modified 12-bit immediate. */
8207 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8208 imm
= (insn
& 0xff);
8211 /* Nothing to do. */
8213 case 1: /* 00XY00XY */
8216 case 2: /* XY00XY00 */
8220 case 3: /* XYXYXYXY */
8224 default: /* Rotated constant. */
8225 shift
= (shift
<< 1) | (imm
>> 7);
8227 imm
= imm
<< (32 - shift
);
8232 tcg_gen_movi_i32(tmp2
, imm
);
8233 rn
= (insn
>> 16) & 0xf;
8236 tcg_gen_movi_i32(tmp
, 0);
8238 tmp
= load_reg(s
, rn
);
8240 op
= (insn
>> 21) & 0xf;
8241 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8242 shifter_out
, tmp
, tmp2
))
8245 rd
= (insn
>> 8) & 0xf;
8247 store_reg(s
, rd
, tmp
);
8254 case 12: /* Load/store single data item. */
8259 if ((insn
& 0x01100000) == 0x01000000) {
8260 if (disas_neon_ls_insn(env
, s
, insn
))
8268 /* s->pc has already been incremented by 4. */
8269 imm
= s
->pc
& 0xfffffffc;
8270 if (insn
& (1 << 23))
8271 imm
+= insn
& 0xfff;
8273 imm
-= insn
& 0xfff;
8274 tcg_gen_movi_i32(addr
, imm
);
8276 addr
= load_reg(s
, rn
);
8277 if (insn
& (1 << 23)) {
8278 /* Positive offset. */
8280 tcg_gen_addi_i32(addr
, addr
, imm
);
8282 op
= (insn
>> 8) & 7;
8285 case 0: case 8: /* Shifted Register. */
8286 shift
= (insn
>> 4) & 0xf;
8289 tmp
= load_reg(s
, rm
);
8291 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8292 tcg_gen_add_i32(addr
, addr
, tmp
);
8295 case 4: /* Negative offset. */
8296 tcg_gen_addi_i32(addr
, addr
, -imm
);
8298 case 6: /* User privilege. */
8299 tcg_gen_addi_i32(addr
, addr
, imm
);
8302 case 1: /* Post-decrement. */
8305 case 3: /* Post-increment. */
8309 case 5: /* Pre-decrement. */
8312 case 7: /* Pre-increment. */
8313 tcg_gen_addi_i32(addr
, addr
, imm
);
8321 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8322 if (insn
& (1 << 20)) {
8324 if (rs
== 15 && op
!= 2) {
8327 /* Memory hint. Implemented as NOP. */
8330 case 0: tmp
= gen_ld8u(addr
, user
); break;
8331 case 4: tmp
= gen_ld8s(addr
, user
); break;
8332 case 1: tmp
= gen_ld16u(addr
, user
); break;
8333 case 5: tmp
= gen_ld16s(addr
, user
); break;
8334 case 2: tmp
= gen_ld32(addr
, user
); break;
8335 default: goto illegal_op
;
8340 store_reg(s
, rs
, tmp
);
8347 tmp
= load_reg(s
, rs
);
8349 case 0: gen_st8(tmp
, addr
, user
); break;
8350 case 1: gen_st16(tmp
, addr
, user
); break;
8351 case 2: gen_st32(tmp
, addr
, user
); break;
8352 default: goto illegal_op
;
8356 tcg_gen_addi_i32(addr
, addr
, imm
);
8358 store_reg(s
, rn
, addr
);
8372 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8374 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8381 if (s
->condexec_mask
) {
8382 cond
= s
->condexec_cond
;
8383 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
8384 s
->condlabel
= gen_new_label();
8385 gen_test_cc(cond
^ 1, s
->condlabel
);
8390 insn
= lduw_code(s
->pc
);
8393 switch (insn
>> 12) {
8397 op
= (insn
>> 11) & 3;
8400 rn
= (insn
>> 3) & 7;
8401 tmp
= load_reg(s
, rn
);
8402 if (insn
& (1 << 10)) {
8405 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8408 rm
= (insn
>> 6) & 7;
8409 tmp2
= load_reg(s
, rm
);
8411 if (insn
& (1 << 9)) {
8412 if (s
->condexec_mask
)
8413 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8415 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8417 if (s
->condexec_mask
)
8418 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8420 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8423 store_reg(s
, rd
, tmp
);
8425 /* shift immediate */
8426 rm
= (insn
>> 3) & 7;
8427 shift
= (insn
>> 6) & 0x1f;
8428 tmp
= load_reg(s
, rm
);
8429 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8430 if (!s
->condexec_mask
)
8432 store_reg(s
, rd
, tmp
);
8436 /* arithmetic large immediate */
8437 op
= (insn
>> 11) & 3;
8438 rd
= (insn
>> 8) & 0x7;
8439 if (op
== 0) { /* mov */
8441 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8442 if (!s
->condexec_mask
)
8444 store_reg(s
, rd
, tmp
);
8446 tmp
= load_reg(s
, rd
);
8448 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8451 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8456 if (s
->condexec_mask
)
8457 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8459 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8461 store_reg(s
, rd
, tmp
);
8464 if (s
->condexec_mask
)
8465 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8467 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8469 store_reg(s
, rd
, tmp
);
8475 if (insn
& (1 << 11)) {
8476 rd
= (insn
>> 8) & 7;
8477 /* load pc-relative. Bit 1 of PC is ignored. */
8478 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8479 val
&= ~(uint32_t)2;
8481 tcg_gen_movi_i32(addr
, val
);
8482 tmp
= gen_ld32(addr
, IS_USER(s
));
8484 store_reg(s
, rd
, tmp
);
8487 if (insn
& (1 << 10)) {
8488 /* data processing extended or blx */
8489 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8490 rm
= (insn
>> 3) & 0xf;
8491 op
= (insn
>> 8) & 3;
8494 tmp
= load_reg(s
, rd
);
8495 tmp2
= load_reg(s
, rm
);
8496 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8498 store_reg(s
, rd
, tmp
);
8501 tmp
= load_reg(s
, rd
);
8502 tmp2
= load_reg(s
, rm
);
8503 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8507 case 2: /* mov/cpy */
8508 tmp
= load_reg(s
, rm
);
8509 store_reg(s
, rd
, tmp
);
8511 case 3:/* branch [and link] exchange thumb register */
8512 tmp
= load_reg(s
, rm
);
8513 if (insn
& (1 << 7)) {
8514 val
= (uint32_t)s
->pc
| 1;
8516 tcg_gen_movi_i32(tmp2
, val
);
8517 store_reg(s
, 14, tmp2
);
8525 /* data processing register */
8527 rm
= (insn
>> 3) & 7;
8528 op
= (insn
>> 6) & 0xf;
8529 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8530 /* the shift/rotate ops want the operands backwards */
8539 if (op
== 9) { /* neg */
8541 tcg_gen_movi_i32(tmp
, 0);
8542 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8543 tmp
= load_reg(s
, rd
);
8548 tmp2
= load_reg(s
, rm
);
8551 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8552 if (!s
->condexec_mask
)
8556 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8557 if (!s
->condexec_mask
)
8561 if (s
->condexec_mask
) {
8562 gen_helper_shl(tmp2
, tmp2
, tmp
);
8564 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8569 if (s
->condexec_mask
) {
8570 gen_helper_shr(tmp2
, tmp2
, tmp
);
8572 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8577 if (s
->condexec_mask
) {
8578 gen_helper_sar(tmp2
, tmp2
, tmp
);
8580 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8585 if (s
->condexec_mask
)
8588 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8591 if (s
->condexec_mask
)
8592 gen_sub_carry(tmp
, tmp
, tmp2
);
8594 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8597 if (s
->condexec_mask
) {
8598 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8599 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8601 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8606 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8611 if (s
->condexec_mask
)
8612 tcg_gen_neg_i32(tmp
, tmp2
);
8614 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8617 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8621 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8625 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8626 if (!s
->condexec_mask
)
8630 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8631 if (!s
->condexec_mask
)
8635 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8636 if (!s
->condexec_mask
)
8640 tcg_gen_not_i32(tmp2
, tmp2
);
8641 if (!s
->condexec_mask
)
8649 store_reg(s
, rm
, tmp2
);
8653 store_reg(s
, rd
, tmp
);
8663 /* load/store register offset. */
8665 rn
= (insn
>> 3) & 7;
8666 rm
= (insn
>> 6) & 7;
8667 op
= (insn
>> 9) & 7;
8668 addr
= load_reg(s
, rn
);
8669 tmp
= load_reg(s
, rm
);
8670 tcg_gen_add_i32(addr
, addr
, tmp
);
8673 if (op
< 3) /* store */
8674 tmp
= load_reg(s
, rd
);
8678 gen_st32(tmp
, addr
, IS_USER(s
));
8681 gen_st16(tmp
, addr
, IS_USER(s
));
8684 gen_st8(tmp
, addr
, IS_USER(s
));
8687 tmp
= gen_ld8s(addr
, IS_USER(s
));
8690 tmp
= gen_ld32(addr
, IS_USER(s
));
8693 tmp
= gen_ld16u(addr
, IS_USER(s
));
8696 tmp
= gen_ld8u(addr
, IS_USER(s
));
8699 tmp
= gen_ld16s(addr
, IS_USER(s
));
8702 if (op
>= 3) /* load */
8703 store_reg(s
, rd
, tmp
);
8708 /* load/store word immediate offset */
8710 rn
= (insn
>> 3) & 7;
8711 addr
= load_reg(s
, rn
);
8712 val
= (insn
>> 4) & 0x7c;
8713 tcg_gen_addi_i32(addr
, addr
, val
);
8715 if (insn
& (1 << 11)) {
8717 tmp
= gen_ld32(addr
, IS_USER(s
));
8718 store_reg(s
, rd
, tmp
);
8721 tmp
= load_reg(s
, rd
);
8722 gen_st32(tmp
, addr
, IS_USER(s
));
8728 /* load/store byte immediate offset */
8730 rn
= (insn
>> 3) & 7;
8731 addr
= load_reg(s
, rn
);
8732 val
= (insn
>> 6) & 0x1f;
8733 tcg_gen_addi_i32(addr
, addr
, val
);
8735 if (insn
& (1 << 11)) {
8737 tmp
= gen_ld8u(addr
, IS_USER(s
));
8738 store_reg(s
, rd
, tmp
);
8741 tmp
= load_reg(s
, rd
);
8742 gen_st8(tmp
, addr
, IS_USER(s
));
8748 /* load/store halfword immediate offset */
8750 rn
= (insn
>> 3) & 7;
8751 addr
= load_reg(s
, rn
);
8752 val
= (insn
>> 5) & 0x3e;
8753 tcg_gen_addi_i32(addr
, addr
, val
);
8755 if (insn
& (1 << 11)) {
8757 tmp
= gen_ld16u(addr
, IS_USER(s
));
8758 store_reg(s
, rd
, tmp
);
8761 tmp
= load_reg(s
, rd
);
8762 gen_st16(tmp
, addr
, IS_USER(s
));
8768 /* load/store from stack */
8769 rd
= (insn
>> 8) & 7;
8770 addr
= load_reg(s
, 13);
8771 val
= (insn
& 0xff) * 4;
8772 tcg_gen_addi_i32(addr
, addr
, val
);
8774 if (insn
& (1 << 11)) {
8776 tmp
= gen_ld32(addr
, IS_USER(s
));
8777 store_reg(s
, rd
, tmp
);
8780 tmp
= load_reg(s
, rd
);
8781 gen_st32(tmp
, addr
, IS_USER(s
));
8787 /* add to high reg */
8788 rd
= (insn
>> 8) & 7;
8789 if (insn
& (1 << 11)) {
8791 tmp
= load_reg(s
, 13);
8793 /* PC. bit 1 is ignored. */
8795 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8797 val
= (insn
& 0xff) * 4;
8798 tcg_gen_addi_i32(tmp
, tmp
, val
);
8799 store_reg(s
, rd
, tmp
);
8804 op
= (insn
>> 8) & 0xf;
8807 /* adjust stack pointer */
8808 tmp
= load_reg(s
, 13);
8809 val
= (insn
& 0x7f) * 4;
8810 if (insn
& (1 << 7))
8811 val
= -(int32_t)val
;
8812 tcg_gen_addi_i32(tmp
, tmp
, val
);
8813 store_reg(s
, 13, tmp
);
8816 case 2: /* sign/zero extend. */
8819 rm
= (insn
>> 3) & 7;
8820 tmp
= load_reg(s
, rm
);
8821 switch ((insn
>> 6) & 3) {
8822 case 0: gen_sxth(tmp
); break;
8823 case 1: gen_sxtb(tmp
); break;
8824 case 2: gen_uxth(tmp
); break;
8825 case 3: gen_uxtb(tmp
); break;
8827 store_reg(s
, rd
, tmp
);
8829 case 4: case 5: case 0xc: case 0xd:
8831 addr
= load_reg(s
, 13);
8832 if (insn
& (1 << 8))
8836 for (i
= 0; i
< 8; i
++) {
8837 if (insn
& (1 << i
))
8840 if ((insn
& (1 << 11)) == 0) {
8841 tcg_gen_addi_i32(addr
, addr
, -offset
);
8843 for (i
= 0; i
< 8; i
++) {
8844 if (insn
& (1 << i
)) {
8845 if (insn
& (1 << 11)) {
8847 tmp
= gen_ld32(addr
, IS_USER(s
));
8848 store_reg(s
, i
, tmp
);
8851 tmp
= load_reg(s
, i
);
8852 gen_st32(tmp
, addr
, IS_USER(s
));
8854 /* advance to the next address. */
8855 tcg_gen_addi_i32(addr
, addr
, 4);
8859 if (insn
& (1 << 8)) {
8860 if (insn
& (1 << 11)) {
8862 tmp
= gen_ld32(addr
, IS_USER(s
));
8863 /* don't set the pc until the rest of the instruction
8867 tmp
= load_reg(s
, 14);
8868 gen_st32(tmp
, addr
, IS_USER(s
));
8870 tcg_gen_addi_i32(addr
, addr
, 4);
8872 if ((insn
& (1 << 11)) == 0) {
8873 tcg_gen_addi_i32(addr
, addr
, -offset
);
8875 /* write back the new stack pointer */
8876 store_reg(s
, 13, addr
);
8877 /* set the new PC value */
8878 if ((insn
& 0x0900) == 0x0900)
8882 case 1: case 3: case 9: case 11: /* czb */
8884 tmp
= load_reg(s
, rm
);
8885 s
->condlabel
= gen_new_label();
8887 if (insn
& (1 << 11))
8888 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8890 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8892 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8893 val
= (uint32_t)s
->pc
+ 2;
8898 case 15: /* IT, nop-hint. */
8899 if ((insn
& 0xf) == 0) {
8900 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8904 s
->condexec_cond
= (insn
>> 4) & 0xe;
8905 s
->condexec_mask
= insn
& 0x1f;
8906 /* No actual code generated for this insn, just setup state. */
8909 case 0xe: /* bkpt */
8910 gen_set_condexec(s
);
8911 gen_set_pc_im(s
->pc
- 2);
8912 gen_exception(EXCP_BKPT
);
8913 s
->is_jmp
= DISAS_JUMP
;
8918 rn
= (insn
>> 3) & 0x7;
8920 tmp
= load_reg(s
, rn
);
8921 switch ((insn
>> 6) & 3) {
8922 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8923 case 1: gen_rev16(tmp
); break;
8924 case 3: gen_revsh(tmp
); break;
8925 default: goto illegal_op
;
8927 store_reg(s
, rd
, tmp
);
8935 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8938 addr
= tcg_const_i32(16);
8939 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8940 tcg_temp_free_i32(addr
);
8944 addr
= tcg_const_i32(17);
8945 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8946 tcg_temp_free_i32(addr
);
8948 tcg_temp_free_i32(tmp
);
8951 if (insn
& (1 << 4))
8952 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8955 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
8965 /* load/store multiple */
8966 rn
= (insn
>> 8) & 0x7;
8967 addr
= load_reg(s
, rn
);
8968 for (i
= 0; i
< 8; i
++) {
8969 if (insn
& (1 << i
)) {
8970 if (insn
& (1 << 11)) {
8972 tmp
= gen_ld32(addr
, IS_USER(s
));
8973 store_reg(s
, i
, tmp
);
8976 tmp
= load_reg(s
, i
);
8977 gen_st32(tmp
, addr
, IS_USER(s
));
8979 /* advance to the next address */
8980 tcg_gen_addi_i32(addr
, addr
, 4);
8983 /* Base register writeback. */
8984 if ((insn
& (1 << rn
)) == 0) {
8985 store_reg(s
, rn
, addr
);
8992 /* conditional branch or swi */
8993 cond
= (insn
>> 8) & 0xf;
8999 gen_set_condexec(s
);
9000 gen_set_pc_im(s
->pc
);
9001 s
->is_jmp
= DISAS_SWI
;
9004 /* generate a conditional jump to next instruction */
9005 s
->condlabel
= gen_new_label();
9006 gen_test_cc(cond
^ 1, s
->condlabel
);
9009 /* jump to the offset */
9010 val
= (uint32_t)s
->pc
+ 2;
9011 offset
= ((int32_t)insn
<< 24) >> 24;
9017 if (insn
& (1 << 11)) {
9018 if (disas_thumb2_insn(env
, s
, insn
))
9022 /* unconditional branch */
9023 val
= (uint32_t)s
->pc
;
9024 offset
= ((int32_t)insn
<< 21) >> 21;
9025 val
+= (offset
<< 1) + 2;
9030 if (disas_thumb2_insn(env
, s
, insn
))
9036 gen_set_condexec(s
);
9037 gen_set_pc_im(s
->pc
- 4);
9038 gen_exception(EXCP_UDEF
);
9039 s
->is_jmp
= DISAS_JUMP
;
9043 gen_set_condexec(s
);
9044 gen_set_pc_im(s
->pc
- 2);
9045 gen_exception(EXCP_UDEF
);
9046 s
->is_jmp
= DISAS_JUMP
;
9049 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9050 basic block 'tb'. If search_pc is TRUE, also generate PC
9051 information for each intermediate instruction. */
9052 static inline void gen_intermediate_code_internal(CPUState
*env
,
9053 TranslationBlock
*tb
,
9056 DisasContext dc1
, *dc
= &dc1
;
9058 uint16_t *gen_opc_end
;
9060 target_ulong pc_start
;
9061 uint32_t next_page_start
;
9065 /* generate intermediate code */
9072 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
9074 dc
->is_jmp
= DISAS_NEXT
;
9076 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9078 dc
->thumb
= env
->thumb
;
9079 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
9080 dc
->condexec_cond
= env
->condexec_bits
>> 4;
9081 #if !defined(CONFIG_USER_ONLY)
9083 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
9085 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
9088 cpu_F0s
= tcg_temp_new_i32();
9089 cpu_F1s
= tcg_temp_new_i32();
9090 cpu_F0d
= tcg_temp_new_i64();
9091 cpu_F1d
= tcg_temp_new_i64();
9094 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9095 cpu_M0
= tcg_temp_new_i64();
9096 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9099 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9101 max_insns
= CF_COUNT_MASK
;
9104 /* Reset the conditional execution bits immediately. This avoids
9105 complications trying to do it at the end of the block. */
9106 if (env
->condexec_bits
)
9108 TCGv tmp
= new_tmp();
9109 tcg_gen_movi_i32(tmp
, 0);
9110 store_cpu_field(tmp
, condexec_bits
);
9113 #ifdef CONFIG_USER_ONLY
9114 /* Intercept jump to the magic kernel page. */
9115 if (dc
->pc
>= 0xffff0000) {
9116 /* We always get here via a jump, so know we are not in a
9117 conditional execution block. */
9118 gen_exception(EXCP_KERNEL_TRAP
);
9119 dc
->is_jmp
= DISAS_UPDATE
;
9123 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9124 /* We always get here via a jump, so know we are not in a
9125 conditional execution block. */
9126 gen_exception(EXCP_EXCEPTION_EXIT
);
9127 dc
->is_jmp
= DISAS_UPDATE
;
9132 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9133 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9134 if (bp
->pc
== dc
->pc
) {
9135 gen_set_condexec(dc
);
9136 gen_set_pc_im(dc
->pc
);
9137 gen_exception(EXCP_DEBUG
);
9138 dc
->is_jmp
= DISAS_JUMP
;
9139 /* Advance PC so that clearing the breakpoint will
9140 invalidate this TB. */
9142 goto done_generating
;
9148 j
= gen_opc_ptr
- gen_opc_buf
;
9152 gen_opc_instr_start
[lj
++] = 0;
9154 gen_opc_pc
[lj
] = dc
->pc
;
9155 gen_opc_instr_start
[lj
] = 1;
9156 gen_opc_icount
[lj
] = num_insns
;
9159 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9163 disas_thumb_insn(env
, dc
);
9164 if (dc
->condexec_mask
) {
9165 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9166 | ((dc
->condexec_mask
>> 4) & 1);
9167 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9168 if (dc
->condexec_mask
== 0) {
9169 dc
->condexec_cond
= 0;
9173 disas_arm_insn(env
, dc
);
9176 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
9180 if (dc
->condjmp
&& !dc
->is_jmp
) {
9181 gen_set_label(dc
->condlabel
);
9184 /* Translation stops when a conditional branch is encountered.
9185 * Otherwise the subsequent code could get translated several times.
9186 * Also stop translation when a page boundary is reached. This
9187 * ensures prefetch aborts occur at the right place. */
9189 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9190 !env
->singlestep_enabled
&&
9192 dc
->pc
< next_page_start
&&
9193 num_insns
< max_insns
);
9195 if (tb
->cflags
& CF_LAST_IO
) {
9197 /* FIXME: This can theoretically happen with self-modifying
9199 cpu_abort(env
, "IO on conditional branch instruction");
9204 /* At this stage dc->condjmp will only be set when the skipped
9205 instruction was a conditional branch or trap, and the PC has
9206 already been written. */
9207 if (unlikely(env
->singlestep_enabled
)) {
9208 /* Make sure the pc is updated, and raise a debug exception. */
9210 gen_set_condexec(dc
);
9211 if (dc
->is_jmp
== DISAS_SWI
) {
9212 gen_exception(EXCP_SWI
);
9214 gen_exception(EXCP_DEBUG
);
9216 gen_set_label(dc
->condlabel
);
9218 if (dc
->condjmp
|| !dc
->is_jmp
) {
9219 gen_set_pc_im(dc
->pc
);
9222 gen_set_condexec(dc
);
9223 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9224 gen_exception(EXCP_SWI
);
9226 /* FIXME: Single stepping a WFI insn will not halt
9228 gen_exception(EXCP_DEBUG
);
9231 /* While branches must always occur at the end of an IT block,
9232 there are a few other things that can cause us to terminate
9233 the TB in the middel of an IT block:
9234 - Exception generating instructions (bkpt, swi, undefined).
9236 - Hardware watchpoints.
9237 Hardware breakpoints have already been handled and skip this code.
9239 gen_set_condexec(dc
);
9240 switch(dc
->is_jmp
) {
9242 gen_goto_tb(dc
, 1, dc
->pc
);
9247 /* indicate that the hash table must be used to find the next TB */
9251 /* nothing more to generate */
9257 gen_exception(EXCP_SWI
);
9261 gen_set_label(dc
->condlabel
);
9262 gen_set_condexec(dc
);
9263 gen_goto_tb(dc
, 1, dc
->pc
);
9269 gen_icount_end(tb
, num_insns
);
9270 *gen_opc_ptr
= INDEX_op_end
;
9273 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9274 qemu_log("----------------\n");
9275 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9276 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9281 j
= gen_opc_ptr
- gen_opc_buf
;
9284 gen_opc_instr_start
[lj
++] = 0;
9286 tb
->size
= dc
->pc
- pc_start
;
9287 tb
->icount
= num_insns
;
9291 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9293 gen_intermediate_code_internal(env
, tb
, 0);
9296 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9298 gen_intermediate_code_internal(env
, tb
, 1);
9301 static const char *cpu_mode_names
[16] = {
9302 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9303 "???", "???", "???", "und", "???", "???", "???", "sys"
9306 void cpu_dump_state(CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
9316 /* ??? This assumes float64 and double have the same layout.
9317 Oh well, it's only debug dumps. */
9326 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9328 cpu_fprintf(f
, "\n");
9330 cpu_fprintf(f
, " ");
9332 psr
= cpsr_read(env
);
9333 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9335 psr
& (1 << 31) ? 'N' : '-',
9336 psr
& (1 << 30) ? 'Z' : '-',
9337 psr
& (1 << 29) ? 'C' : '-',
9338 psr
& (1 << 28) ? 'V' : '-',
9339 psr
& CPSR_T
? 'T' : 'A',
9340 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9343 for (i
= 0; i
< 16; i
++) {
9344 d
.d
= env
->vfp
.regs
[i
];
9348 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9349 i
* 2, (int)s0
.i
, s0
.s
,
9350 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9351 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9354 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9358 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9359 unsigned long searched_pc
, int pc_pos
, void *puc
)
9361 env
->regs
[15] = gen_opc_pc
[pc_pos
];