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)
65 #if defined(CONFIG_USER_ONLY)
68 #define IS_USER(s) (s->user)
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
76 static TCGv_ptr cpu_env
;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
79 static TCGv_i32 cpu_R
[16];
80 static TCGv_i32 cpu_exclusive_addr
;
81 static TCGv_i32 cpu_exclusive_val
;
82 static TCGv_i32 cpu_exclusive_high
;
83 #ifdef CONFIG_USER_ONLY
84 static TCGv_i32 cpu_exclusive_test
;
85 static TCGv_i32 cpu_exclusive_info
;
88 /* FIXME: These should be removed. */
89 static TCGv cpu_F0s
, cpu_F1s
;
90 static TCGv_i64 cpu_F0d
, cpu_F1d
;
92 #include "gen-icount.h"
94 static const char *regnames
[] =
95 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
96 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
98 /* initialize TCG globals. */
99 void arm_translate_init(void)
103 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
105 for (i
= 0; i
< 16; i
++) {
106 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
107 offsetof(CPUState
, regs
[i
]),
110 cpu_exclusive_addr
= tcg_global_mem_new_i32(TCG_AREG0
,
111 offsetof(CPUState
, exclusive_addr
), "exclusive_addr");
112 cpu_exclusive_val
= tcg_global_mem_new_i32(TCG_AREG0
,
113 offsetof(CPUState
, exclusive_val
), "exclusive_val");
114 cpu_exclusive_high
= tcg_global_mem_new_i32(TCG_AREG0
,
115 offsetof(CPUState
, exclusive_high
), "exclusive_high");
116 #ifdef CONFIG_USER_ONLY
117 cpu_exclusive_test
= tcg_global_mem_new_i32(TCG_AREG0
,
118 offsetof(CPUState
, exclusive_test
), "exclusive_test");
119 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
120 offsetof(CPUState
, exclusive_info
), "exclusive_info");
127 static int num_temps
;
129 /* Allocate a temporary variable. */
130 static TCGv_i32
new_tmp(void)
133 return tcg_temp_new_i32();
136 /* Release a temporary variable. */
137 static void dead_tmp(TCGv tmp
)
143 static inline TCGv
load_cpu_offset(int offset
)
145 TCGv tmp
= new_tmp();
146 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
150 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
152 static inline void store_cpu_offset(TCGv var
, int offset
)
154 tcg_gen_st_i32(var
, cpu_env
, offset
);
158 #define store_cpu_field(var, name) \
159 store_cpu_offset(var, offsetof(CPUState, name))
161 /* Set a variable to the value of a CPU register. */
162 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
166 /* normaly, since we updated PC, we need only to add one insn */
168 addr
= (long)s
->pc
+ 2;
170 addr
= (long)s
->pc
+ 4;
171 tcg_gen_movi_i32(var
, addr
);
173 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
177 /* Create a new temporary and set it to the value of a CPU register. */
178 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
180 TCGv tmp
= new_tmp();
181 load_reg_var(s
, tmp
, reg
);
185 /* Set a CPU register. The source must be a temporary and will be
187 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
190 tcg_gen_andi_i32(var
, var
, ~1);
191 s
->is_jmp
= DISAS_JUMP
;
193 tcg_gen_mov_i32(cpu_R
[reg
], var
);
197 /* Value extensions. */
198 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
199 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
200 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
201 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
203 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
204 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
207 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
209 TCGv tmp_mask
= tcg_const_i32(mask
);
210 gen_helper_cpsr_write(var
, tmp_mask
);
211 tcg_temp_free_i32(tmp_mask
);
213 /* Set NZCV flags from the high 4 bits of var. */
214 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
216 static void gen_exception(int excp
)
218 TCGv tmp
= new_tmp();
219 tcg_gen_movi_i32(tmp
, excp
);
220 gen_helper_exception(tmp
);
224 static void gen_smul_dual(TCGv a
, TCGv b
)
226 TCGv tmp1
= new_tmp();
227 TCGv tmp2
= new_tmp();
228 tcg_gen_ext16s_i32(tmp1
, a
);
229 tcg_gen_ext16s_i32(tmp2
, b
);
230 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
232 tcg_gen_sari_i32(a
, a
, 16);
233 tcg_gen_sari_i32(b
, b
, 16);
234 tcg_gen_mul_i32(b
, b
, a
);
235 tcg_gen_mov_i32(a
, tmp1
);
239 /* Byteswap each halfword. */
240 static void gen_rev16(TCGv var
)
242 TCGv tmp
= new_tmp();
243 tcg_gen_shri_i32(tmp
, var
, 8);
244 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
245 tcg_gen_shli_i32(var
, var
, 8);
246 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
247 tcg_gen_or_i32(var
, var
, tmp
);
251 /* Byteswap low halfword and sign extend. */
252 static void gen_revsh(TCGv var
)
254 tcg_gen_ext16u_i32(var
, var
);
255 tcg_gen_bswap16_i32(var
, var
);
256 tcg_gen_ext16s_i32(var
, var
);
259 /* Unsigned bitfield extract. */
260 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
263 tcg_gen_shri_i32(var
, var
, shift
);
264 tcg_gen_andi_i32(var
, var
, mask
);
267 /* Signed bitfield extract. */
268 static void gen_sbfx(TCGv var
, int shift
, int width
)
273 tcg_gen_sari_i32(var
, var
, shift
);
274 if (shift
+ width
< 32) {
275 signbit
= 1u << (width
- 1);
276 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
277 tcg_gen_xori_i32(var
, var
, signbit
);
278 tcg_gen_subi_i32(var
, var
, signbit
);
282 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
283 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
285 tcg_gen_andi_i32(val
, val
, mask
);
286 tcg_gen_shli_i32(val
, val
, shift
);
287 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
288 tcg_gen_or_i32(dest
, base
, val
);
291 /* Return (b << 32) + a. Mark inputs as dead */
292 static TCGv_i64
gen_addq_msw(TCGv_i64 a
, TCGv b
)
294 TCGv_i64 tmp64
= tcg_temp_new_i64();
296 tcg_gen_extu_i32_i64(tmp64
, b
);
298 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
299 tcg_gen_add_i64(a
, tmp64
, a
);
301 tcg_temp_free_i64(tmp64
);
305 /* Return (b << 32) - a. Mark inputs as dead. */
306 static TCGv_i64
gen_subq_msw(TCGv_i64 a
, TCGv b
)
308 TCGv_i64 tmp64
= tcg_temp_new_i64();
310 tcg_gen_extu_i32_i64(tmp64
, b
);
312 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
313 tcg_gen_sub_i64(a
, tmp64
, a
);
315 tcg_temp_free_i64(tmp64
);
319 /* FIXME: Most targets have native widening multiplication.
320 It would be good to use that instead of a full wide multiply. */
321 /* 32x32->64 multiply. Marks inputs as dead. */
322 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
324 TCGv_i64 tmp1
= tcg_temp_new_i64();
325 TCGv_i64 tmp2
= tcg_temp_new_i64();
327 tcg_gen_extu_i32_i64(tmp1
, a
);
329 tcg_gen_extu_i32_i64(tmp2
, b
);
331 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
332 tcg_temp_free_i64(tmp2
);
336 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
338 TCGv_i64 tmp1
= tcg_temp_new_i64();
339 TCGv_i64 tmp2
= tcg_temp_new_i64();
341 tcg_gen_ext_i32_i64(tmp1
, a
);
343 tcg_gen_ext_i32_i64(tmp2
, b
);
345 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
346 tcg_temp_free_i64(tmp2
);
350 /* Swap low and high halfwords. */
351 static void gen_swap_half(TCGv var
)
353 TCGv tmp
= new_tmp();
354 tcg_gen_shri_i32(tmp
, var
, 16);
355 tcg_gen_shli_i32(var
, var
, 16);
356 tcg_gen_or_i32(var
, var
, tmp
);
360 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
361 tmp = (t0 ^ t1) & 0x8000;
364 t0 = (t0 + t1) ^ tmp;
367 static void gen_add16(TCGv t0
, TCGv t1
)
369 TCGv tmp
= new_tmp();
370 tcg_gen_xor_i32(tmp
, t0
, t1
);
371 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
372 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
373 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
374 tcg_gen_add_i32(t0
, t0
, t1
);
375 tcg_gen_xor_i32(t0
, t0
, tmp
);
380 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
382 /* Set CF to the top bit of var. */
383 static void gen_set_CF_bit31(TCGv var
)
385 TCGv tmp
= new_tmp();
386 tcg_gen_shri_i32(tmp
, var
, 31);
391 /* Set N and Z flags from var. */
392 static inline void gen_logic_CC(TCGv var
)
394 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
395 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
399 static void gen_adc(TCGv t0
, TCGv t1
)
402 tcg_gen_add_i32(t0
, t0
, t1
);
403 tmp
= load_cpu_field(CF
);
404 tcg_gen_add_i32(t0
, t0
, tmp
);
408 /* dest = T0 + T1 + CF. */
409 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
412 tcg_gen_add_i32(dest
, t0
, t1
);
413 tmp
= load_cpu_field(CF
);
414 tcg_gen_add_i32(dest
, dest
, tmp
);
418 /* dest = T0 - T1 + CF - 1. */
419 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
422 tcg_gen_sub_i32(dest
, t0
, t1
);
423 tmp
= load_cpu_field(CF
);
424 tcg_gen_add_i32(dest
, dest
, tmp
);
425 tcg_gen_subi_i32(dest
, dest
, 1);
429 /* FIXME: Implement this natively. */
430 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
432 static void shifter_out_im(TCGv var
, int shift
)
434 TCGv tmp
= new_tmp();
436 tcg_gen_andi_i32(tmp
, var
, 1);
438 tcg_gen_shri_i32(tmp
, var
, shift
);
440 tcg_gen_andi_i32(tmp
, tmp
, 1);
446 /* Shift by immediate. Includes special handling for shift == 0. */
447 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
453 shifter_out_im(var
, 32 - shift
);
454 tcg_gen_shli_i32(var
, var
, shift
);
460 tcg_gen_shri_i32(var
, var
, 31);
463 tcg_gen_movi_i32(var
, 0);
466 shifter_out_im(var
, shift
- 1);
467 tcg_gen_shri_i32(var
, var
, shift
);
474 shifter_out_im(var
, shift
- 1);
477 tcg_gen_sari_i32(var
, var
, shift
);
479 case 3: /* ROR/RRX */
482 shifter_out_im(var
, shift
- 1);
483 tcg_gen_rotri_i32(var
, var
, shift
); break;
485 TCGv tmp
= load_cpu_field(CF
);
487 shifter_out_im(var
, 0);
488 tcg_gen_shri_i32(var
, var
, 1);
489 tcg_gen_shli_i32(tmp
, tmp
, 31);
490 tcg_gen_or_i32(var
, var
, tmp
);
496 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
497 TCGv shift
, int flags
)
501 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
502 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
503 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
504 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
508 case 0: gen_helper_shl(var
, var
, shift
); break;
509 case 1: gen_helper_shr(var
, var
, shift
); break;
510 case 2: gen_helper_sar(var
, var
, shift
); break;
511 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
512 tcg_gen_rotr_i32(var
, var
, shift
); break;
518 #define PAS_OP(pfx) \
520 case 0: gen_pas_helper(glue(pfx,add16)); break; \
521 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
522 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
523 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
524 case 4: gen_pas_helper(glue(pfx,add8)); break; \
525 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
527 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
532 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
534 tmp
= tcg_temp_new_ptr();
535 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
537 tcg_temp_free_ptr(tmp
);
540 tmp
= tcg_temp_new_ptr();
541 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
543 tcg_temp_free_ptr(tmp
);
545 #undef gen_pas_helper
546 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
559 #undef gen_pas_helper
564 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
565 #define PAS_OP(pfx) \
567 case 0: gen_pas_helper(glue(pfx,add8)); break; \
568 case 1: gen_pas_helper(glue(pfx,add16)); break; \
569 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
570 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
571 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
572 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
574 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
579 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
581 tmp
= tcg_temp_new_ptr();
582 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
584 tcg_temp_free_ptr(tmp
);
587 tmp
= tcg_temp_new_ptr();
588 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
590 tcg_temp_free_ptr(tmp
);
592 #undef gen_pas_helper
593 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
606 #undef gen_pas_helper
611 static void gen_test_cc(int cc
, int label
)
619 tmp
= load_cpu_field(ZF
);
620 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
623 tmp
= load_cpu_field(ZF
);
624 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
627 tmp
= load_cpu_field(CF
);
628 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
631 tmp
= load_cpu_field(CF
);
632 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
635 tmp
= load_cpu_field(NF
);
636 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
639 tmp
= load_cpu_field(NF
);
640 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
643 tmp
= load_cpu_field(VF
);
644 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
647 tmp
= load_cpu_field(VF
);
648 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
650 case 8: /* hi: C && !Z */
651 inv
= gen_new_label();
652 tmp
= load_cpu_field(CF
);
653 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
655 tmp
= load_cpu_field(ZF
);
656 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
659 case 9: /* ls: !C || Z */
660 tmp
= load_cpu_field(CF
);
661 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
663 tmp
= load_cpu_field(ZF
);
664 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
666 case 10: /* ge: N == V -> N ^ V == 0 */
667 tmp
= load_cpu_field(VF
);
668 tmp2
= load_cpu_field(NF
);
669 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
671 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
673 case 11: /* lt: N != V -> N ^ V != 0 */
674 tmp
= load_cpu_field(VF
);
675 tmp2
= load_cpu_field(NF
);
676 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
678 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
680 case 12: /* gt: !Z && N == V */
681 inv
= gen_new_label();
682 tmp
= load_cpu_field(ZF
);
683 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
685 tmp
= load_cpu_field(VF
);
686 tmp2
= load_cpu_field(NF
);
687 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
689 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
692 case 13: /* le: Z || N != V */
693 tmp
= load_cpu_field(ZF
);
694 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
696 tmp
= load_cpu_field(VF
);
697 tmp2
= load_cpu_field(NF
);
698 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
700 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
703 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
709 static const uint8_t table_logic_cc
[16] = {
728 /* Set PC and Thumb state from an immediate address. */
729 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
733 s
->is_jmp
= DISAS_UPDATE
;
734 if (s
->thumb
!= (addr
& 1)) {
736 tcg_gen_movi_i32(tmp
, addr
& 1);
737 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
740 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
743 /* Set PC and Thumb state from var. var is marked as dead. */
744 static inline void gen_bx(DisasContext
*s
, TCGv var
)
746 s
->is_jmp
= DISAS_UPDATE
;
747 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
748 tcg_gen_andi_i32(var
, var
, 1);
749 store_cpu_field(var
, thumb
);
752 /* Variant of store_reg which uses branch&exchange logic when storing
753 to r15 in ARM architecture v7 and above. The source must be a temporary
754 and will be marked as dead. */
755 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
758 if (reg
== 15 && ENABLE_ARCH_7
) {
761 store_reg(s
, reg
, var
);
765 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
767 TCGv tmp
= new_tmp();
768 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
771 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
773 TCGv tmp
= new_tmp();
774 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
777 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
779 TCGv tmp
= new_tmp();
780 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
783 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
785 TCGv tmp
= new_tmp();
786 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
789 static inline TCGv
gen_ld32(TCGv addr
, int index
)
791 TCGv tmp
= new_tmp();
792 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
795 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
797 TCGv_i64 tmp
= tcg_temp_new_i64();
798 tcg_gen_qemu_ld64(tmp
, addr
, index
);
801 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
803 tcg_gen_qemu_st8(val
, addr
, index
);
806 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
808 tcg_gen_qemu_st16(val
, addr
, index
);
811 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
813 tcg_gen_qemu_st32(val
, addr
, index
);
816 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
818 tcg_gen_qemu_st64(val
, addr
, index
);
819 tcg_temp_free_i64(val
);
822 static inline void gen_set_pc_im(uint32_t val
)
824 tcg_gen_movi_i32(cpu_R
[15], val
);
827 /* Force a TB lookup after an instruction that changes the CPU state. */
828 static inline void gen_lookup_tb(DisasContext
*s
)
830 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
831 s
->is_jmp
= DISAS_UPDATE
;
834 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
837 int val
, rm
, shift
, shiftop
;
840 if (!(insn
& (1 << 25))) {
843 if (!(insn
& (1 << 23)))
846 tcg_gen_addi_i32(var
, var
, val
);
850 shift
= (insn
>> 7) & 0x1f;
851 shiftop
= (insn
>> 5) & 3;
852 offset
= load_reg(s
, rm
);
853 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
854 if (!(insn
& (1 << 23)))
855 tcg_gen_sub_i32(var
, var
, offset
);
857 tcg_gen_add_i32(var
, var
, offset
);
862 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
868 if (insn
& (1 << 22)) {
870 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
871 if (!(insn
& (1 << 23)))
875 tcg_gen_addi_i32(var
, var
, val
);
879 tcg_gen_addi_i32(var
, var
, extra
);
881 offset
= load_reg(s
, rm
);
882 if (!(insn
& (1 << 23)))
883 tcg_gen_sub_i32(var
, var
, offset
);
885 tcg_gen_add_i32(var
, var
, offset
);
890 #define VFP_OP2(name) \
891 static inline void gen_vfp_##name(int dp) \
894 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
896 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
906 static inline void gen_vfp_abs(int dp
)
909 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
911 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
914 static inline void gen_vfp_neg(int dp
)
917 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
919 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
922 static inline void gen_vfp_sqrt(int dp
)
925 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
927 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
930 static inline void gen_vfp_cmp(int dp
)
933 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
935 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
938 static inline void gen_vfp_cmpe(int dp
)
941 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
943 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
946 static inline void gen_vfp_F1_ld0(int dp
)
949 tcg_gen_movi_i64(cpu_F1d
, 0);
951 tcg_gen_movi_i32(cpu_F1s
, 0);
954 static inline void gen_vfp_uito(int dp
)
957 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
959 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
962 static inline void gen_vfp_sito(int dp
)
965 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
967 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
970 static inline void gen_vfp_toui(int dp
)
973 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
975 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
978 static inline void gen_vfp_touiz(int dp
)
981 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
983 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
986 static inline void gen_vfp_tosi(int dp
)
989 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
991 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
994 static inline void gen_vfp_tosiz(int dp
)
997 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
999 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1002 #define VFP_GEN_FIX(name) \
1003 static inline void gen_vfp_##name(int dp, int shift) \
1005 TCGv tmp_shift = tcg_const_i32(shift); \
1007 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1009 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1010 tcg_temp_free_i32(tmp_shift); \
1022 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1025 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1027 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1030 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1033 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1035 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1039 vfp_reg_offset (int dp
, int reg
)
1042 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1044 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1045 + offsetof(CPU_DoubleU
, l
.upper
);
1047 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1048 + offsetof(CPU_DoubleU
, l
.lower
);
1052 /* Return the offset of a 32-bit piece of a NEON register.
1053 zero is the least significant end of the register. */
1055 neon_reg_offset (int reg
, int n
)
1059 return vfp_reg_offset(0, sreg
);
1062 static TCGv
neon_load_reg(int reg
, int pass
)
1064 TCGv tmp
= new_tmp();
1065 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1069 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1071 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1075 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1077 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1080 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1082 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1085 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1086 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1087 #define tcg_gen_st_f32 tcg_gen_st_i32
1088 #define tcg_gen_st_f64 tcg_gen_st_i64
1090 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1093 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1095 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1098 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1101 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1103 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1106 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1109 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1111 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1114 #define ARM_CP_RW_BIT (1 << 20)
1116 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1118 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1121 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1123 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1126 static inline TCGv
iwmmxt_load_creg(int reg
)
1128 TCGv var
= new_tmp();
1129 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1133 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1135 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1139 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1141 iwmmxt_store_reg(cpu_M0
, rn
);
1144 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1146 iwmmxt_load_reg(cpu_M0
, rn
);
1149 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1151 iwmmxt_load_reg(cpu_V1
, rn
);
1152 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1155 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1157 iwmmxt_load_reg(cpu_V1
, rn
);
1158 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1161 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1163 iwmmxt_load_reg(cpu_V1
, rn
);
1164 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1167 #define IWMMXT_OP(name) \
1168 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1170 iwmmxt_load_reg(cpu_V1, rn); \
1171 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1174 #define IWMMXT_OP_ENV(name) \
1175 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1177 iwmmxt_load_reg(cpu_V1, rn); \
1178 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1181 #define IWMMXT_OP_ENV_SIZE(name) \
1182 IWMMXT_OP_ENV(name##b) \
1183 IWMMXT_OP_ENV(name##w) \
1184 IWMMXT_OP_ENV(name##l)
1186 #define IWMMXT_OP_ENV1(name) \
1187 static inline void gen_op_iwmmxt_##name##_M0(void) \
1189 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1203 IWMMXT_OP_ENV_SIZE(unpackl
)
1204 IWMMXT_OP_ENV_SIZE(unpackh
)
1206 IWMMXT_OP_ENV1(unpacklub
)
1207 IWMMXT_OP_ENV1(unpackluw
)
1208 IWMMXT_OP_ENV1(unpacklul
)
1209 IWMMXT_OP_ENV1(unpackhub
)
1210 IWMMXT_OP_ENV1(unpackhuw
)
1211 IWMMXT_OP_ENV1(unpackhul
)
1212 IWMMXT_OP_ENV1(unpacklsb
)
1213 IWMMXT_OP_ENV1(unpacklsw
)
1214 IWMMXT_OP_ENV1(unpacklsl
)
1215 IWMMXT_OP_ENV1(unpackhsb
)
1216 IWMMXT_OP_ENV1(unpackhsw
)
1217 IWMMXT_OP_ENV1(unpackhsl
)
1219 IWMMXT_OP_ENV_SIZE(cmpeq
)
1220 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1221 IWMMXT_OP_ENV_SIZE(cmpgts
)
1223 IWMMXT_OP_ENV_SIZE(mins
)
1224 IWMMXT_OP_ENV_SIZE(minu
)
1225 IWMMXT_OP_ENV_SIZE(maxs
)
1226 IWMMXT_OP_ENV_SIZE(maxu
)
1228 IWMMXT_OP_ENV_SIZE(subn
)
1229 IWMMXT_OP_ENV_SIZE(addn
)
1230 IWMMXT_OP_ENV_SIZE(subu
)
1231 IWMMXT_OP_ENV_SIZE(addu
)
1232 IWMMXT_OP_ENV_SIZE(subs
)
1233 IWMMXT_OP_ENV_SIZE(adds
)
1235 IWMMXT_OP_ENV(avgb0
)
1236 IWMMXT_OP_ENV(avgb1
)
1237 IWMMXT_OP_ENV(avgw0
)
1238 IWMMXT_OP_ENV(avgw1
)
1242 IWMMXT_OP_ENV(packuw
)
1243 IWMMXT_OP_ENV(packul
)
1244 IWMMXT_OP_ENV(packuq
)
1245 IWMMXT_OP_ENV(packsw
)
1246 IWMMXT_OP_ENV(packsl
)
1247 IWMMXT_OP_ENV(packsq
)
1249 static void gen_op_iwmmxt_set_mup(void)
1252 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1253 tcg_gen_ori_i32(tmp
, tmp
, 2);
1254 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1257 static void gen_op_iwmmxt_set_cup(void)
1260 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1261 tcg_gen_ori_i32(tmp
, tmp
, 1);
1262 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1265 static void gen_op_iwmmxt_setpsr_nz(void)
1267 TCGv tmp
= new_tmp();
1268 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1269 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1272 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1274 iwmmxt_load_reg(cpu_V1
, rn
);
1275 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1276 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1279 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1285 rd
= (insn
>> 16) & 0xf;
1286 tmp
= load_reg(s
, rd
);
1288 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1289 if (insn
& (1 << 24)) {
1291 if (insn
& (1 << 23))
1292 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1294 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1295 tcg_gen_mov_i32(dest
, tmp
);
1296 if (insn
& (1 << 21))
1297 store_reg(s
, rd
, tmp
);
1300 } else if (insn
& (1 << 21)) {
1302 tcg_gen_mov_i32(dest
, tmp
);
1303 if (insn
& (1 << 23))
1304 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1306 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1307 store_reg(s
, rd
, tmp
);
1308 } else if (!(insn
& (1 << 23)))
1313 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1315 int rd
= (insn
>> 0) & 0xf;
1318 if (insn
& (1 << 8)) {
1319 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1322 tmp
= iwmmxt_load_creg(rd
);
1326 iwmmxt_load_reg(cpu_V0
, rd
);
1327 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1329 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1330 tcg_gen_mov_i32(dest
, tmp
);
1335 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1336 (ie. an undefined instruction). */
1337 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1340 int rdhi
, rdlo
, rd0
, rd1
, i
;
1342 TCGv tmp
, tmp2
, tmp3
;
1344 if ((insn
& 0x0e000e00) == 0x0c000000) {
1345 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1347 rdlo
= (insn
>> 12) & 0xf;
1348 rdhi
= (insn
>> 16) & 0xf;
1349 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1350 iwmmxt_load_reg(cpu_V0
, wrd
);
1351 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1352 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1353 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1354 } else { /* TMCRR */
1355 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1356 iwmmxt_store_reg(cpu_V0
, wrd
);
1357 gen_op_iwmmxt_set_mup();
1362 wrd
= (insn
>> 12) & 0xf;
1364 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1368 if (insn
& ARM_CP_RW_BIT
) {
1369 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1371 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1372 iwmmxt_store_creg(wrd
, tmp
);
1375 if (insn
& (1 << 8)) {
1376 if (insn
& (1 << 22)) { /* WLDRD */
1377 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1379 } else { /* WLDRW wRd */
1380 tmp
= gen_ld32(addr
, IS_USER(s
));
1383 if (insn
& (1 << 22)) { /* WLDRH */
1384 tmp
= gen_ld16u(addr
, IS_USER(s
));
1385 } else { /* WLDRB */
1386 tmp
= gen_ld8u(addr
, IS_USER(s
));
1390 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1393 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1396 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1397 tmp
= iwmmxt_load_creg(wrd
);
1398 gen_st32(tmp
, addr
, IS_USER(s
));
1400 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1402 if (insn
& (1 << 8)) {
1403 if (insn
& (1 << 22)) { /* WSTRD */
1405 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1406 } else { /* WSTRW wRd */
1407 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1408 gen_st32(tmp
, addr
, IS_USER(s
));
1411 if (insn
& (1 << 22)) { /* WSTRH */
1412 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1413 gen_st16(tmp
, addr
, IS_USER(s
));
1414 } else { /* WSTRB */
1415 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1416 gen_st8(tmp
, addr
, IS_USER(s
));
1425 if ((insn
& 0x0f000000) != 0x0e000000)
1428 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1429 case 0x000: /* WOR */
1430 wrd
= (insn
>> 12) & 0xf;
1431 rd0
= (insn
>> 0) & 0xf;
1432 rd1
= (insn
>> 16) & 0xf;
1433 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1434 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1435 gen_op_iwmmxt_setpsr_nz();
1436 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1437 gen_op_iwmmxt_set_mup();
1438 gen_op_iwmmxt_set_cup();
1440 case 0x011: /* TMCR */
1443 rd
= (insn
>> 12) & 0xf;
1444 wrd
= (insn
>> 16) & 0xf;
1446 case ARM_IWMMXT_wCID
:
1447 case ARM_IWMMXT_wCASF
:
1449 case ARM_IWMMXT_wCon
:
1450 gen_op_iwmmxt_set_cup();
1452 case ARM_IWMMXT_wCSSF
:
1453 tmp
= iwmmxt_load_creg(wrd
);
1454 tmp2
= load_reg(s
, rd
);
1455 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1457 iwmmxt_store_creg(wrd
, tmp
);
1459 case ARM_IWMMXT_wCGR0
:
1460 case ARM_IWMMXT_wCGR1
:
1461 case ARM_IWMMXT_wCGR2
:
1462 case ARM_IWMMXT_wCGR3
:
1463 gen_op_iwmmxt_set_cup();
1464 tmp
= load_reg(s
, rd
);
1465 iwmmxt_store_creg(wrd
, tmp
);
1471 case 0x100: /* WXOR */
1472 wrd
= (insn
>> 12) & 0xf;
1473 rd0
= (insn
>> 0) & 0xf;
1474 rd1
= (insn
>> 16) & 0xf;
1475 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1476 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1477 gen_op_iwmmxt_setpsr_nz();
1478 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1479 gen_op_iwmmxt_set_mup();
1480 gen_op_iwmmxt_set_cup();
1482 case 0x111: /* TMRC */
1485 rd
= (insn
>> 12) & 0xf;
1486 wrd
= (insn
>> 16) & 0xf;
1487 tmp
= iwmmxt_load_creg(wrd
);
1488 store_reg(s
, rd
, tmp
);
1490 case 0x300: /* WANDN */
1491 wrd
= (insn
>> 12) & 0xf;
1492 rd0
= (insn
>> 0) & 0xf;
1493 rd1
= (insn
>> 16) & 0xf;
1494 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1495 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1496 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1497 gen_op_iwmmxt_setpsr_nz();
1498 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1499 gen_op_iwmmxt_set_mup();
1500 gen_op_iwmmxt_set_cup();
1502 case 0x200: /* WAND */
1503 wrd
= (insn
>> 12) & 0xf;
1504 rd0
= (insn
>> 0) & 0xf;
1505 rd1
= (insn
>> 16) & 0xf;
1506 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1507 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1508 gen_op_iwmmxt_setpsr_nz();
1509 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1510 gen_op_iwmmxt_set_mup();
1511 gen_op_iwmmxt_set_cup();
1513 case 0x810: case 0xa10: /* WMADD */
1514 wrd
= (insn
>> 12) & 0xf;
1515 rd0
= (insn
>> 0) & 0xf;
1516 rd1
= (insn
>> 16) & 0xf;
1517 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1518 if (insn
& (1 << 21))
1519 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1521 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1522 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1523 gen_op_iwmmxt_set_mup();
1525 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1526 wrd
= (insn
>> 12) & 0xf;
1527 rd0
= (insn
>> 16) & 0xf;
1528 rd1
= (insn
>> 0) & 0xf;
1529 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1530 switch ((insn
>> 22) & 3) {
1532 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1535 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1538 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1543 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1544 gen_op_iwmmxt_set_mup();
1545 gen_op_iwmmxt_set_cup();
1547 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1548 wrd
= (insn
>> 12) & 0xf;
1549 rd0
= (insn
>> 16) & 0xf;
1550 rd1
= (insn
>> 0) & 0xf;
1551 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1552 switch ((insn
>> 22) & 3) {
1554 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1557 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1560 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1565 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1566 gen_op_iwmmxt_set_mup();
1567 gen_op_iwmmxt_set_cup();
1569 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1570 wrd
= (insn
>> 12) & 0xf;
1571 rd0
= (insn
>> 16) & 0xf;
1572 rd1
= (insn
>> 0) & 0xf;
1573 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1574 if (insn
& (1 << 22))
1575 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1577 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1578 if (!(insn
& (1 << 20)))
1579 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1580 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1581 gen_op_iwmmxt_set_mup();
1583 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1584 wrd
= (insn
>> 12) & 0xf;
1585 rd0
= (insn
>> 16) & 0xf;
1586 rd1
= (insn
>> 0) & 0xf;
1587 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1588 if (insn
& (1 << 21)) {
1589 if (insn
& (1 << 20))
1590 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1592 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1594 if (insn
& (1 << 20))
1595 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1597 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1599 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1600 gen_op_iwmmxt_set_mup();
1602 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1603 wrd
= (insn
>> 12) & 0xf;
1604 rd0
= (insn
>> 16) & 0xf;
1605 rd1
= (insn
>> 0) & 0xf;
1606 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1607 if (insn
& (1 << 21))
1608 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1610 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1611 if (!(insn
& (1 << 20))) {
1612 iwmmxt_load_reg(cpu_V1
, wrd
);
1613 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1615 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1616 gen_op_iwmmxt_set_mup();
1618 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1619 wrd
= (insn
>> 12) & 0xf;
1620 rd0
= (insn
>> 16) & 0xf;
1621 rd1
= (insn
>> 0) & 0xf;
1622 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1623 switch ((insn
>> 22) & 3) {
1625 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1628 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1631 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1636 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1637 gen_op_iwmmxt_set_mup();
1638 gen_op_iwmmxt_set_cup();
1640 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1641 wrd
= (insn
>> 12) & 0xf;
1642 rd0
= (insn
>> 16) & 0xf;
1643 rd1
= (insn
>> 0) & 0xf;
1644 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1645 if (insn
& (1 << 22)) {
1646 if (insn
& (1 << 20))
1647 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1649 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1651 if (insn
& (1 << 20))
1652 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1654 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1656 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1657 gen_op_iwmmxt_set_mup();
1658 gen_op_iwmmxt_set_cup();
1660 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1661 wrd
= (insn
>> 12) & 0xf;
1662 rd0
= (insn
>> 16) & 0xf;
1663 rd1
= (insn
>> 0) & 0xf;
1664 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1665 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1666 tcg_gen_andi_i32(tmp
, tmp
, 7);
1667 iwmmxt_load_reg(cpu_V1
, rd1
);
1668 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1670 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1671 gen_op_iwmmxt_set_mup();
1673 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1674 if (((insn
>> 6) & 3) == 3)
1676 rd
= (insn
>> 12) & 0xf;
1677 wrd
= (insn
>> 16) & 0xf;
1678 tmp
= load_reg(s
, rd
);
1679 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1680 switch ((insn
>> 6) & 3) {
1682 tmp2
= tcg_const_i32(0xff);
1683 tmp3
= tcg_const_i32((insn
& 7) << 3);
1686 tmp2
= tcg_const_i32(0xffff);
1687 tmp3
= tcg_const_i32((insn
& 3) << 4);
1690 tmp2
= tcg_const_i32(0xffffffff);
1691 tmp3
= tcg_const_i32((insn
& 1) << 5);
1697 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1698 tcg_temp_free(tmp3
);
1699 tcg_temp_free(tmp2
);
1701 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1702 gen_op_iwmmxt_set_mup();
1704 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1705 rd
= (insn
>> 12) & 0xf;
1706 wrd
= (insn
>> 16) & 0xf;
1707 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1709 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1711 switch ((insn
>> 22) & 3) {
1713 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1714 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1716 tcg_gen_ext8s_i32(tmp
, tmp
);
1718 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1722 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1723 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1725 tcg_gen_ext16s_i32(tmp
, tmp
);
1727 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1731 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1732 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1735 store_reg(s
, rd
, tmp
);
1737 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1738 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1740 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1741 switch ((insn
>> 22) & 3) {
1743 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1746 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1749 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1752 tcg_gen_shli_i32(tmp
, tmp
, 28);
1756 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1757 if (((insn
>> 6) & 3) == 3)
1759 rd
= (insn
>> 12) & 0xf;
1760 wrd
= (insn
>> 16) & 0xf;
1761 tmp
= load_reg(s
, rd
);
1762 switch ((insn
>> 6) & 3) {
1764 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1767 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1770 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1774 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1775 gen_op_iwmmxt_set_mup();
1777 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1778 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1780 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1782 tcg_gen_mov_i32(tmp2
, tmp
);
1783 switch ((insn
>> 22) & 3) {
1785 for (i
= 0; i
< 7; i
++) {
1786 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1787 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1791 for (i
= 0; i
< 3; i
++) {
1792 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1793 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1797 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1798 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1805 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1806 wrd
= (insn
>> 12) & 0xf;
1807 rd0
= (insn
>> 16) & 0xf;
1808 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1809 switch ((insn
>> 22) & 3) {
1811 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1814 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1817 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1822 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1823 gen_op_iwmmxt_set_mup();
1825 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1826 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1828 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1830 tcg_gen_mov_i32(tmp2
, tmp
);
1831 switch ((insn
>> 22) & 3) {
1833 for (i
= 0; i
< 7; i
++) {
1834 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1835 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1839 for (i
= 0; i
< 3; i
++) {
1840 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1841 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1845 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1846 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1853 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1854 rd
= (insn
>> 12) & 0xf;
1855 rd0
= (insn
>> 16) & 0xf;
1856 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1858 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1860 switch ((insn
>> 22) & 3) {
1862 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1865 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1868 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1871 store_reg(s
, rd
, tmp
);
1873 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1874 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1875 wrd
= (insn
>> 12) & 0xf;
1876 rd0
= (insn
>> 16) & 0xf;
1877 rd1
= (insn
>> 0) & 0xf;
1878 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1879 switch ((insn
>> 22) & 3) {
1881 if (insn
& (1 << 21))
1882 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1884 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1887 if (insn
& (1 << 21))
1888 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1890 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1893 if (insn
& (1 << 21))
1894 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1896 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1901 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1902 gen_op_iwmmxt_set_mup();
1903 gen_op_iwmmxt_set_cup();
1905 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1906 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1907 wrd
= (insn
>> 12) & 0xf;
1908 rd0
= (insn
>> 16) & 0xf;
1909 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1910 switch ((insn
>> 22) & 3) {
1912 if (insn
& (1 << 21))
1913 gen_op_iwmmxt_unpacklsb_M0();
1915 gen_op_iwmmxt_unpacklub_M0();
1918 if (insn
& (1 << 21))
1919 gen_op_iwmmxt_unpacklsw_M0();
1921 gen_op_iwmmxt_unpackluw_M0();
1924 if (insn
& (1 << 21))
1925 gen_op_iwmmxt_unpacklsl_M0();
1927 gen_op_iwmmxt_unpacklul_M0();
1932 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1933 gen_op_iwmmxt_set_mup();
1934 gen_op_iwmmxt_set_cup();
1936 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1937 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1938 wrd
= (insn
>> 12) & 0xf;
1939 rd0
= (insn
>> 16) & 0xf;
1940 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1941 switch ((insn
>> 22) & 3) {
1943 if (insn
& (1 << 21))
1944 gen_op_iwmmxt_unpackhsb_M0();
1946 gen_op_iwmmxt_unpackhub_M0();
1949 if (insn
& (1 << 21))
1950 gen_op_iwmmxt_unpackhsw_M0();
1952 gen_op_iwmmxt_unpackhuw_M0();
1955 if (insn
& (1 << 21))
1956 gen_op_iwmmxt_unpackhsl_M0();
1958 gen_op_iwmmxt_unpackhul_M0();
1963 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1964 gen_op_iwmmxt_set_mup();
1965 gen_op_iwmmxt_set_cup();
1967 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1968 case 0x214: case 0x614: case 0xa14: case 0xe14:
1969 if (((insn
>> 22) & 3) == 0)
1971 wrd
= (insn
>> 12) & 0xf;
1972 rd0
= (insn
>> 16) & 0xf;
1973 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1975 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1979 switch ((insn
>> 22) & 3) {
1981 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1984 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1987 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1991 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1992 gen_op_iwmmxt_set_mup();
1993 gen_op_iwmmxt_set_cup();
1995 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1996 case 0x014: case 0x414: case 0x814: case 0xc14:
1997 if (((insn
>> 22) & 3) == 0)
1999 wrd
= (insn
>> 12) & 0xf;
2000 rd0
= (insn
>> 16) & 0xf;
2001 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2003 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2007 switch ((insn
>> 22) & 3) {
2009 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2012 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2015 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2019 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2020 gen_op_iwmmxt_set_mup();
2021 gen_op_iwmmxt_set_cup();
2023 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2024 case 0x114: case 0x514: case 0x914: case 0xd14:
2025 if (((insn
>> 22) & 3) == 0)
2027 wrd
= (insn
>> 12) & 0xf;
2028 rd0
= (insn
>> 16) & 0xf;
2029 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2031 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2035 switch ((insn
>> 22) & 3) {
2037 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2040 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2043 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2047 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2048 gen_op_iwmmxt_set_mup();
2049 gen_op_iwmmxt_set_cup();
2051 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2052 case 0x314: case 0x714: case 0xb14: case 0xf14:
2053 if (((insn
>> 22) & 3) == 0)
2055 wrd
= (insn
>> 12) & 0xf;
2056 rd0
= (insn
>> 16) & 0xf;
2057 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2059 switch ((insn
>> 22) & 3) {
2061 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2065 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2068 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2072 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2075 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2079 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2083 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2084 gen_op_iwmmxt_set_mup();
2085 gen_op_iwmmxt_set_cup();
2087 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2088 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2089 wrd
= (insn
>> 12) & 0xf;
2090 rd0
= (insn
>> 16) & 0xf;
2091 rd1
= (insn
>> 0) & 0xf;
2092 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2093 switch ((insn
>> 22) & 3) {
2095 if (insn
& (1 << 21))
2096 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2098 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2101 if (insn
& (1 << 21))
2102 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2104 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2107 if (insn
& (1 << 21))
2108 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2110 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2115 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2116 gen_op_iwmmxt_set_mup();
2118 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2119 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2120 wrd
= (insn
>> 12) & 0xf;
2121 rd0
= (insn
>> 16) & 0xf;
2122 rd1
= (insn
>> 0) & 0xf;
2123 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2124 switch ((insn
>> 22) & 3) {
2126 if (insn
& (1 << 21))
2127 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2129 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2132 if (insn
& (1 << 21))
2133 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2135 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2138 if (insn
& (1 << 21))
2139 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2141 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2146 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2147 gen_op_iwmmxt_set_mup();
2149 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2150 case 0x402: case 0x502: case 0x602: case 0x702:
2151 wrd
= (insn
>> 12) & 0xf;
2152 rd0
= (insn
>> 16) & 0xf;
2153 rd1
= (insn
>> 0) & 0xf;
2154 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2155 tmp
= tcg_const_i32((insn
>> 20) & 3);
2156 iwmmxt_load_reg(cpu_V1
, rd1
);
2157 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2159 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2160 gen_op_iwmmxt_set_mup();
2162 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2163 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2164 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2165 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2166 wrd
= (insn
>> 12) & 0xf;
2167 rd0
= (insn
>> 16) & 0xf;
2168 rd1
= (insn
>> 0) & 0xf;
2169 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2170 switch ((insn
>> 20) & 0xf) {
2172 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2175 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2178 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2181 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2184 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2187 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2190 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2193 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2196 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2201 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2202 gen_op_iwmmxt_set_mup();
2203 gen_op_iwmmxt_set_cup();
2205 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2206 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2207 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2208 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2209 wrd
= (insn
>> 12) & 0xf;
2210 rd0
= (insn
>> 16) & 0xf;
2211 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2212 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2213 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2215 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2216 gen_op_iwmmxt_set_mup();
2217 gen_op_iwmmxt_set_cup();
2219 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2220 case 0x418: case 0x518: case 0x618: case 0x718:
2221 case 0x818: case 0x918: case 0xa18: case 0xb18:
2222 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2223 wrd
= (insn
>> 12) & 0xf;
2224 rd0
= (insn
>> 16) & 0xf;
2225 rd1
= (insn
>> 0) & 0xf;
2226 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2227 switch ((insn
>> 20) & 0xf) {
2229 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2232 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2235 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2238 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2241 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2244 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2247 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2250 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2253 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2258 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2259 gen_op_iwmmxt_set_mup();
2260 gen_op_iwmmxt_set_cup();
2262 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2263 case 0x408: case 0x508: case 0x608: case 0x708:
2264 case 0x808: case 0x908: case 0xa08: case 0xb08:
2265 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2266 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2268 wrd
= (insn
>> 12) & 0xf;
2269 rd0
= (insn
>> 16) & 0xf;
2270 rd1
= (insn
>> 0) & 0xf;
2271 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2272 switch ((insn
>> 22) & 3) {
2274 if (insn
& (1 << 21))
2275 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2277 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2280 if (insn
& (1 << 21))
2281 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2283 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2286 if (insn
& (1 << 21))
2287 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2289 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2292 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2293 gen_op_iwmmxt_set_mup();
2294 gen_op_iwmmxt_set_cup();
2296 case 0x201: case 0x203: case 0x205: case 0x207:
2297 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2298 case 0x211: case 0x213: case 0x215: case 0x217:
2299 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2300 wrd
= (insn
>> 5) & 0xf;
2301 rd0
= (insn
>> 12) & 0xf;
2302 rd1
= (insn
>> 0) & 0xf;
2303 if (rd0
== 0xf || rd1
== 0xf)
2305 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2306 tmp
= load_reg(s
, rd0
);
2307 tmp2
= load_reg(s
, rd1
);
2308 switch ((insn
>> 16) & 0xf) {
2309 case 0x0: /* TMIA */
2310 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2312 case 0x8: /* TMIAPH */
2313 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2315 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2316 if (insn
& (1 << 16))
2317 tcg_gen_shri_i32(tmp
, tmp
, 16);
2318 if (insn
& (1 << 17))
2319 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2320 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2329 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2330 gen_op_iwmmxt_set_mup();
2339 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2340 (ie. an undefined instruction). */
2341 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2343 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2346 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2347 /* Multiply with Internal Accumulate Format */
2348 rd0
= (insn
>> 12) & 0xf;
2350 acc
= (insn
>> 5) & 7;
2355 tmp
= load_reg(s
, rd0
);
2356 tmp2
= load_reg(s
, rd1
);
2357 switch ((insn
>> 16) & 0xf) {
2359 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2361 case 0x8: /* MIAPH */
2362 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2364 case 0xc: /* MIABB */
2365 case 0xd: /* MIABT */
2366 case 0xe: /* MIATB */
2367 case 0xf: /* MIATT */
2368 if (insn
& (1 << 16))
2369 tcg_gen_shri_i32(tmp
, tmp
, 16);
2370 if (insn
& (1 << 17))
2371 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2372 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2380 gen_op_iwmmxt_movq_wRn_M0(acc
);
2384 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2385 /* Internal Accumulator Access Format */
2386 rdhi
= (insn
>> 16) & 0xf;
2387 rdlo
= (insn
>> 12) & 0xf;
2393 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2394 iwmmxt_load_reg(cpu_V0
, acc
);
2395 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2396 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2397 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2398 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2400 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2401 iwmmxt_store_reg(cpu_V0
, acc
);
2409 /* Disassemble system coprocessor instruction. Return nonzero if
2410 instruction is not defined. */
2411 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2414 uint32_t rd
= (insn
>> 12) & 0xf;
2415 uint32_t cp
= (insn
>> 8) & 0xf;
2420 if (insn
& ARM_CP_RW_BIT
) {
2421 if (!env
->cp
[cp
].cp_read
)
2423 gen_set_pc_im(s
->pc
);
2425 tmp2
= tcg_const_i32(insn
);
2426 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2427 tcg_temp_free(tmp2
);
2428 store_reg(s
, rd
, tmp
);
2430 if (!env
->cp
[cp
].cp_write
)
2432 gen_set_pc_im(s
->pc
);
2433 tmp
= load_reg(s
, rd
);
2434 tmp2
= tcg_const_i32(insn
);
2435 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2436 tcg_temp_free(tmp2
);
2442 static int cp15_user_ok(uint32_t insn
)
2444 int cpn
= (insn
>> 16) & 0xf;
2445 int cpm
= insn
& 0xf;
2446 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2448 if (cpn
== 13 && cpm
== 0) {
2450 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2454 /* ISB, DSB, DMB. */
2455 if ((cpm
== 5 && op
== 4)
2456 || (cpm
== 10 && (op
== 4 || op
== 5)))
2462 static int cp15_tls_load_store(CPUState
*env
, DisasContext
*s
, uint32_t insn
, uint32_t rd
)
2465 int cpn
= (insn
>> 16) & 0xf;
2466 int cpm
= insn
& 0xf;
2467 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2469 if (!arm_feature(env
, ARM_FEATURE_V6K
))
2472 if (!(cpn
== 13 && cpm
== 0))
2475 if (insn
& ARM_CP_RW_BIT
) {
2478 tmp
= load_cpu_field(cp15
.c13_tls1
);
2481 tmp
= load_cpu_field(cp15
.c13_tls2
);
2484 tmp
= load_cpu_field(cp15
.c13_tls3
);
2489 store_reg(s
, rd
, tmp
);
2492 tmp
= load_reg(s
, rd
);
2495 store_cpu_field(tmp
, cp15
.c13_tls1
);
2498 store_cpu_field(tmp
, cp15
.c13_tls2
);
2501 store_cpu_field(tmp
, cp15
.c13_tls3
);
2511 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2512 instruction is not defined. */
2513 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2518 /* M profile cores use memory mapped registers instead of cp15. */
2519 if (arm_feature(env
, ARM_FEATURE_M
))
2522 if ((insn
& (1 << 25)) == 0) {
2523 if (insn
& (1 << 20)) {
2527 /* mcrr. Used for block cache operations, so implement as no-op. */
2530 if ((insn
& (1 << 4)) == 0) {
2534 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2537 if ((insn
& 0x0fff0fff) == 0x0e070f90
2538 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2539 /* Wait for interrupt. */
2540 gen_set_pc_im(s
->pc
);
2541 s
->is_jmp
= DISAS_WFI
;
2544 rd
= (insn
>> 12) & 0xf;
2546 if (cp15_tls_load_store(env
, s
, insn
, rd
))
2549 tmp2
= tcg_const_i32(insn
);
2550 if (insn
& ARM_CP_RW_BIT
) {
2552 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2553 /* If the destination register is r15 then sets condition codes. */
2555 store_reg(s
, rd
, tmp
);
2559 tmp
= load_reg(s
, rd
);
2560 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2562 /* Normally we would always end the TB here, but Linux
2563 * arch/arm/mach-pxa/sleep.S expects two instructions following
2564 * an MMU enable to execute from cache. Imitate this behaviour. */
2565 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2566 (insn
& 0x0fff0fff) != 0x0e010f10)
2569 tcg_temp_free_i32(tmp2
);
2573 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2574 #define VFP_SREG(insn, bigbit, smallbit) \
2575 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2576 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2577 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2578 reg = (((insn) >> (bigbit)) & 0x0f) \
2579 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2581 if (insn & (1 << (smallbit))) \
2583 reg = ((insn) >> (bigbit)) & 0x0f; \
2586 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2587 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2588 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2589 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2590 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2591 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2593 /* Move between integer and VFP cores. */
2594 static TCGv
gen_vfp_mrs(void)
2596 TCGv tmp
= new_tmp();
2597 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2601 static void gen_vfp_msr(TCGv tmp
)
2603 tcg_gen_mov_i32(cpu_F0s
, tmp
);
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 (!s
->vfp_enabled
) {
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 (!s
->vfp_enabled
)
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 (!s
->vfp_enabled
)
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
);
4650 case 6: /* VQSHLU */
4652 gen_helper_neon_qshlu_s64(cpu_V0
, cpu_env
,
4660 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4663 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4668 if (op
== 1 || op
== 3) {
4670 neon_load_reg64(cpu_V0
, rd
+ pass
);
4671 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4672 } else if (op
== 4 || (op
== 5 && u
)) {
4674 cpu_abort(env
, "VS[LR]I.64 not implemented");
4676 neon_store_reg64(cpu_V0
, rd
+ pass
);
4677 } else { /* size < 3 */
4678 /* Operands in T0 and T1. */
4679 tmp
= neon_load_reg(rm
, pass
);
4681 tcg_gen_movi_i32(tmp2
, imm
);
4685 GEN_NEON_INTEGER_OP(shl
);
4689 GEN_NEON_INTEGER_OP(rshl
);
4694 GEN_NEON_INTEGER_OP(shl
);
4696 case 5: /* VSHL, VSLI */
4698 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4699 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4700 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4704 case 6: /* VQSHLU */
4710 gen_helper_neon_qshlu_s8(tmp
, cpu_env
,
4714 gen_helper_neon_qshlu_s16(tmp
, cpu_env
,
4718 gen_helper_neon_qshlu_s32(tmp
, cpu_env
,
4726 GEN_NEON_INTEGER_OP_ENV(qshl
);
4731 if (op
== 1 || op
== 3) {
4733 tmp2
= neon_load_reg(rd
, pass
);
4734 gen_neon_add(size
, tmp2
, tmp
);
4736 } else if (op
== 4 || (op
== 5 && u
)) {
4741 mask
= 0xff >> -shift
;
4743 mask
= (uint8_t)(0xff << shift
);
4749 mask
= 0xffff >> -shift
;
4751 mask
= (uint16_t)(0xffff << shift
);
4755 if (shift
< -31 || shift
> 31) {
4759 mask
= 0xffffffffu
>> -shift
;
4761 mask
= 0xffffffffu
<< shift
;
4767 tmp2
= neon_load_reg(rd
, pass
);
4768 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4769 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4770 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4773 neon_store_reg(rd
, pass
, tmp
);
4776 } else if (op
< 10) {
4777 /* Shift by immediate and narrow:
4778 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4779 shift
= shift
- (1 << (size
+ 3));
4783 imm
= (uint16_t)shift
;
4785 tmp2
= tcg_const_i32(imm
);
4786 TCGV_UNUSED_I64(tmp64
);
4789 imm
= (uint32_t)shift
;
4790 tmp2
= tcg_const_i32(imm
);
4791 TCGV_UNUSED_I64(tmp64
);
4794 tmp64
= tcg_const_i64(shift
);
4801 for (pass
= 0; pass
< 2; pass
++) {
4803 neon_load_reg64(cpu_V0
, rm
+ pass
);
4806 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4808 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4811 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4813 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4816 tmp
= neon_load_reg(rm
+ pass
, 0);
4817 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4818 tmp3
= neon_load_reg(rm
+ pass
, 1);
4819 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4820 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4825 if (op
== 8 && !u
) {
4826 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4829 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4831 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4833 neon_store_reg(rd
, pass
, tmp
);
4836 tcg_temp_free_i64(tmp64
);
4840 } else if (op
== 10) {
4844 tmp
= neon_load_reg(rm
, 0);
4845 tmp2
= neon_load_reg(rm
, 1);
4846 for (pass
= 0; pass
< 2; pass
++) {
4850 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4853 /* The shift is less than the width of the source
4854 type, so we can just shift the whole register. */
4855 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4856 if (size
< 2 || !u
) {
4859 imm
= (0xffu
>> (8 - shift
));
4862 imm
= 0xffff >> (16 - shift
);
4864 imm64
= imm
| (((uint64_t)imm
) << 32);
4865 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4868 neon_store_reg64(cpu_V0
, rd
+ pass
);
4870 } else if (op
>= 14) {
4871 /* VCVT fixed-point. */
4872 /* We have already masked out the must-be-1 top bit of imm6,
4873 * hence this 32-shift where the ARM ARM has 64-imm6.
4876 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4877 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4880 gen_vfp_ulto(0, shift
);
4882 gen_vfp_slto(0, shift
);
4885 gen_vfp_toul(0, shift
);
4887 gen_vfp_tosl(0, shift
);
4889 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4894 } else { /* (insn & 0x00380080) == 0 */
4897 op
= (insn
>> 8) & 0xf;
4898 /* One register and immediate. */
4899 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4900 invert
= (insn
& (1 << 5)) != 0;
4918 imm
= (imm
<< 8) | (imm
<< 24);
4921 imm
= (imm
<< 8) | 0xff;
4924 imm
= (imm
<< 16) | 0xffff;
4927 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4932 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4933 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4939 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4940 if (op
& 1 && op
< 12) {
4941 tmp
= neon_load_reg(rd
, pass
);
4943 /* The immediate value has already been inverted, so
4945 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4947 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4952 if (op
== 14 && invert
) {
4955 for (n
= 0; n
< 4; n
++) {
4956 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4957 val
|= 0xff << (n
* 8);
4959 tcg_gen_movi_i32(tmp
, val
);
4961 tcg_gen_movi_i32(tmp
, imm
);
4964 neon_store_reg(rd
, pass
, tmp
);
4967 } else { /* (insn & 0x00800010 == 0x00800000) */
4969 op
= (insn
>> 8) & 0xf;
4970 if ((insn
& (1 << 6)) == 0) {
4971 /* Three registers of different lengths. */
4975 /* prewiden, src1_wide, src2_wide */
4976 static const int neon_3reg_wide
[16][3] = {
4977 {1, 0, 0}, /* VADDL */
4978 {1, 1, 0}, /* VADDW */
4979 {1, 0, 0}, /* VSUBL */
4980 {1, 1, 0}, /* VSUBW */
4981 {0, 1, 1}, /* VADDHN */
4982 {0, 0, 0}, /* VABAL */
4983 {0, 1, 1}, /* VSUBHN */
4984 {0, 0, 0}, /* VABDL */
4985 {0, 0, 0}, /* VMLAL */
4986 {0, 0, 0}, /* VQDMLAL */
4987 {0, 0, 0}, /* VMLSL */
4988 {0, 0, 0}, /* VQDMLSL */
4989 {0, 0, 0}, /* Integer VMULL */
4990 {0, 0, 0}, /* VQDMULL */
4991 {0, 0, 0} /* Polynomial VMULL */
4994 prewiden
= neon_3reg_wide
[op
][0];
4995 src1_wide
= neon_3reg_wide
[op
][1];
4996 src2_wide
= neon_3reg_wide
[op
][2];
4998 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
5001 /* Avoid overlapping operands. Wide source operands are
5002 always aligned so will never overlap with wide
5003 destinations in problematic ways. */
5004 if (rd
== rm
&& !src2_wide
) {
5005 tmp
= neon_load_reg(rm
, 1);
5006 neon_store_scratch(2, tmp
);
5007 } else if (rd
== rn
&& !src1_wide
) {
5008 tmp
= neon_load_reg(rn
, 1);
5009 neon_store_scratch(2, tmp
);
5012 for (pass
= 0; pass
< 2; pass
++) {
5014 neon_load_reg64(cpu_V0
, rn
+ pass
);
5017 if (pass
== 1 && rd
== rn
) {
5018 tmp
= neon_load_scratch(2);
5020 tmp
= neon_load_reg(rn
, pass
);
5023 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5027 neon_load_reg64(cpu_V1
, rm
+ pass
);
5030 if (pass
== 1 && rd
== rm
) {
5031 tmp2
= neon_load_scratch(2);
5033 tmp2
= neon_load_reg(rm
, pass
);
5036 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5040 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5041 gen_neon_addl(size
);
5043 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5044 gen_neon_subl(size
);
5046 case 5: case 7: /* VABAL, VABDL */
5047 switch ((size
<< 1) | u
) {
5049 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5052 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5055 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5058 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5061 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5064 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5071 case 8: case 9: case 10: case 11: case 12: case 13:
5072 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5073 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5077 case 14: /* Polynomial VMULL */
5078 cpu_abort(env
, "Polynomial VMULL not implemented");
5080 default: /* 15 is RESERVED. */
5083 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5085 if (op
== 10 || op
== 11) {
5086 gen_neon_negl(cpu_V0
, size
);
5090 neon_load_reg64(cpu_V1
, rd
+ pass
);
5094 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5095 gen_neon_addl(size
);
5097 case 9: case 11: /* VQDMLAL, VQDMLSL */
5098 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5099 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5102 case 13: /* VQDMULL */
5103 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5108 neon_store_reg64(cpu_V0
, rd
+ pass
);
5109 } else if (op
== 4 || op
== 6) {
5110 /* Narrowing operation. */
5115 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5118 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5121 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5122 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5129 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5132 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5135 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5136 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5137 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5145 neon_store_reg(rd
, 0, tmp3
);
5146 neon_store_reg(rd
, 1, tmp
);
5149 /* Write back the result. */
5150 neon_store_reg64(cpu_V0
, rd
+ pass
);
5154 /* Two registers and a scalar. */
5156 case 0: /* Integer VMLA scalar */
5157 case 1: /* Float VMLA scalar */
5158 case 4: /* Integer VMLS scalar */
5159 case 5: /* Floating point VMLS scalar */
5160 case 8: /* Integer VMUL scalar */
5161 case 9: /* Floating point VMUL scalar */
5162 case 12: /* VQDMULH scalar */
5163 case 13: /* VQRDMULH scalar */
5164 tmp
= neon_get_scalar(size
, rm
);
5165 neon_store_scratch(0, tmp
);
5166 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5167 tmp
= neon_load_scratch(0);
5168 tmp2
= neon_load_reg(rn
, pass
);
5171 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5173 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5175 } else if (op
== 13) {
5177 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5179 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5181 } else if (op
& 1) {
5182 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5185 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5186 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5187 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5194 tmp2
= neon_load_reg(rd
, pass
);
5197 gen_neon_add(size
, tmp
, tmp2
);
5200 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5203 gen_neon_rsb(size
, tmp
, tmp2
);
5206 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5213 neon_store_reg(rd
, pass
, tmp
);
5216 case 2: /* VMLAL sclar */
5217 case 3: /* VQDMLAL scalar */
5218 case 6: /* VMLSL scalar */
5219 case 7: /* VQDMLSL scalar */
5220 case 10: /* VMULL scalar */
5221 case 11: /* VQDMULL scalar */
5222 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5225 tmp2
= neon_get_scalar(size
, rm
);
5226 tmp3
= neon_load_reg(rn
, 1);
5228 for (pass
= 0; pass
< 2; pass
++) {
5230 tmp
= neon_load_reg(rn
, 0);
5234 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5236 if (op
== 6 || op
== 7) {
5237 gen_neon_negl(cpu_V0
, size
);
5240 neon_load_reg64(cpu_V1
, rd
+ pass
);
5244 gen_neon_addl(size
);
5247 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5248 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5254 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5259 neon_store_reg64(cpu_V0
, rd
+ pass
);
5265 default: /* 14 and 15 are RESERVED */
5269 } else { /* size == 3 */
5272 imm
= (insn
>> 8) & 0xf;
5278 neon_load_reg64(cpu_V0
, rn
);
5280 neon_load_reg64(cpu_V1
, rn
+ 1);
5282 } else if (imm
== 8) {
5283 neon_load_reg64(cpu_V0
, rn
+ 1);
5285 neon_load_reg64(cpu_V1
, rm
);
5288 tmp64
= tcg_temp_new_i64();
5290 neon_load_reg64(cpu_V0
, rn
);
5291 neon_load_reg64(tmp64
, rn
+ 1);
5293 neon_load_reg64(cpu_V0
, rn
+ 1);
5294 neon_load_reg64(tmp64
, rm
);
5296 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5297 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5298 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5300 neon_load_reg64(cpu_V1
, rm
);
5302 neon_load_reg64(cpu_V1
, rm
+ 1);
5305 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5306 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5307 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5308 tcg_temp_free_i64(tmp64
);
5311 neon_load_reg64(cpu_V0
, rn
);
5312 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5313 neon_load_reg64(cpu_V1
, rm
);
5314 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5315 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5317 neon_store_reg64(cpu_V0
, rd
);
5319 neon_store_reg64(cpu_V1
, rd
+ 1);
5321 } else if ((insn
& (1 << 11)) == 0) {
5322 /* Two register misc. */
5323 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5324 size
= (insn
>> 18) & 3;
5326 case 0: /* VREV64 */
5329 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5330 tmp
= neon_load_reg(rm
, pass
* 2);
5331 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5333 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5334 case 1: gen_swap_half(tmp
); break;
5335 case 2: /* no-op */ break;
5338 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5340 neon_store_reg(rd
, pass
* 2, tmp2
);
5343 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5344 case 1: gen_swap_half(tmp2
); break;
5347 neon_store_reg(rd
, pass
* 2, tmp2
);
5351 case 4: case 5: /* VPADDL */
5352 case 12: case 13: /* VPADAL */
5355 for (pass
= 0; pass
< q
+ 1; pass
++) {
5356 tmp
= neon_load_reg(rm
, pass
* 2);
5357 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5358 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5359 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5361 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5362 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5363 case 2: tcg_gen_add_i64(CPU_V001
); break;
5368 neon_load_reg64(cpu_V1
, rd
+ pass
);
5369 gen_neon_addl(size
);
5371 neon_store_reg64(cpu_V0
, rd
+ pass
);
5376 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5377 tmp
= neon_load_reg(rm
, n
);
5378 tmp2
= neon_load_reg(rd
, n
+ 1);
5379 neon_store_reg(rm
, n
, tmp2
);
5380 neon_store_reg(rd
, n
+ 1, tmp
);
5388 Rd A3 A2 A1 A0 B2 B0 A2 A0
5389 Rm B3 B2 B1 B0 B3 B1 A3 A1
5393 gen_neon_unzip(rd
, q
, 0, size
);
5394 gen_neon_unzip(rm
, q
, 4, size
);
5396 static int unzip_order_q
[8] =
5397 {0, 2, 4, 6, 1, 3, 5, 7};
5398 for (n
= 0; n
< 8; n
++) {
5399 int reg
= (n
< 4) ? rd
: rm
;
5400 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5401 neon_store_reg(reg
, n
% 4, tmp
);
5404 static int unzip_order
[4] =
5406 for (n
= 0; n
< 4; n
++) {
5407 int reg
= (n
< 2) ? rd
: rm
;
5408 tmp
= neon_load_scratch(unzip_order
[n
]);
5409 neon_store_reg(reg
, n
% 2, tmp
);
5415 Rd A3 A2 A1 A0 B1 A1 B0 A0
5416 Rm B3 B2 B1 B0 B3 A3 B2 A2
5420 count
= (q
? 4 : 2);
5421 for (n
= 0; n
< count
; n
++) {
5422 tmp
= neon_load_reg(rd
, n
);
5423 tmp2
= neon_load_reg(rd
, n
);
5425 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5426 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5427 case 2: /* no-op */; break;
5430 neon_store_scratch(n
* 2, tmp
);
5431 neon_store_scratch(n
* 2 + 1, tmp2
);
5433 for (n
= 0; n
< count
* 2; n
++) {
5434 int reg
= (n
< count
) ? rd
: rm
;
5435 tmp
= neon_load_scratch(n
);
5436 neon_store_reg(reg
, n
% count
, tmp
);
5439 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5443 for (pass
= 0; pass
< 2; pass
++) {
5444 neon_load_reg64(cpu_V0
, rm
+ pass
);
5446 if (op
== 36 && q
== 0) {
5447 gen_neon_narrow(size
, tmp
, cpu_V0
);
5449 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5451 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5456 neon_store_reg(rd
, 0, tmp2
);
5457 neon_store_reg(rd
, 1, tmp
);
5461 case 38: /* VSHLL */
5464 tmp
= neon_load_reg(rm
, 0);
5465 tmp2
= neon_load_reg(rm
, 1);
5466 for (pass
= 0; pass
< 2; pass
++) {
5469 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5470 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5471 neon_store_reg64(cpu_V0
, rd
+ pass
);
5474 case 44: /* VCVT.F16.F32 */
5475 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5479 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5480 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5481 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5482 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5483 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5484 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5485 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5486 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5487 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5488 neon_store_reg(rd
, 0, tmp2
);
5490 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5491 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5492 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5493 neon_store_reg(rd
, 1, tmp2
);
5496 case 46: /* VCVT.F32.F16 */
5497 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5500 tmp
= neon_load_reg(rm
, 0);
5501 tmp2
= neon_load_reg(rm
, 1);
5502 tcg_gen_ext16u_i32(tmp3
, tmp
);
5503 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5504 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5505 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5506 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5507 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5509 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5510 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5511 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5512 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5513 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5514 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5520 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5521 if (op
== 30 || op
== 31 || op
>= 58) {
5522 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5523 neon_reg_offset(rm
, pass
));
5526 tmp
= neon_load_reg(rm
, pass
);
5529 case 1: /* VREV32 */
5531 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5532 case 1: gen_swap_half(tmp
); break;
5536 case 2: /* VREV16 */
5543 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5544 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5545 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5551 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5552 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5553 case 2: gen_helper_clz(tmp
, tmp
); break;
5560 gen_helper_neon_cnt_u8(tmp
, tmp
);
5565 tcg_gen_not_i32(tmp
, tmp
);
5567 case 14: /* VQABS */
5569 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5570 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5571 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5575 case 15: /* VQNEG */
5577 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5578 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5579 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5583 case 16: case 19: /* VCGT #0, VCLE #0 */
5584 tmp2
= tcg_const_i32(0);
5586 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5587 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5588 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5591 tcg_temp_free(tmp2
);
5593 tcg_gen_not_i32(tmp
, tmp
);
5595 case 17: case 20: /* VCGE #0, VCLT #0 */
5596 tmp2
= tcg_const_i32(0);
5598 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5599 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5600 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5603 tcg_temp_free(tmp2
);
5605 tcg_gen_not_i32(tmp
, tmp
);
5607 case 18: /* VCEQ #0 */
5608 tmp2
= tcg_const_i32(0);
5610 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5611 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5612 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5615 tcg_temp_free(tmp2
);
5619 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5620 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5621 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5628 tmp2
= tcg_const_i32(0);
5629 gen_neon_rsb(size
, tmp
, tmp2
);
5630 tcg_temp_free(tmp2
);
5632 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5633 tmp2
= tcg_const_i32(0);
5634 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5635 tcg_temp_free(tmp2
);
5637 tcg_gen_not_i32(tmp
, tmp
);
5639 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5640 tmp2
= tcg_const_i32(0);
5641 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5642 tcg_temp_free(tmp2
);
5644 tcg_gen_not_i32(tmp
, tmp
);
5646 case 26: /* Float VCEQ #0 */
5647 tmp2
= tcg_const_i32(0);
5648 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5649 tcg_temp_free(tmp2
);
5651 case 30: /* Float VABS */
5654 case 31: /* Float VNEG */
5658 tmp2
= neon_load_reg(rd
, pass
);
5659 neon_store_reg(rm
, pass
, tmp2
);
5662 tmp2
= neon_load_reg(rd
, pass
);
5664 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5665 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5669 neon_store_reg(rm
, pass
, tmp2
);
5671 case 56: /* Integer VRECPE */
5672 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5674 case 57: /* Integer VRSQRTE */
5675 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5677 case 58: /* Float VRECPE */
5678 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5680 case 59: /* Float VRSQRTE */
5681 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5683 case 60: /* VCVT.F32.S32 */
5686 case 61: /* VCVT.F32.U32 */
5689 case 62: /* VCVT.S32.F32 */
5692 case 63: /* VCVT.U32.F32 */
5696 /* Reserved: 21, 29, 39-56 */
5699 if (op
== 30 || op
== 31 || op
>= 58) {
5700 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5701 neon_reg_offset(rd
, pass
));
5703 neon_store_reg(rd
, pass
, tmp
);
5708 } else if ((insn
& (1 << 10)) == 0) {
5710 n
= ((insn
>> 5) & 0x18) + 8;
5711 if (insn
& (1 << 6)) {
5712 tmp
= neon_load_reg(rd
, 0);
5715 tcg_gen_movi_i32(tmp
, 0);
5717 tmp2
= neon_load_reg(rm
, 0);
5718 tmp4
= tcg_const_i32(rn
);
5719 tmp5
= tcg_const_i32(n
);
5720 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5722 if (insn
& (1 << 6)) {
5723 tmp
= neon_load_reg(rd
, 1);
5726 tcg_gen_movi_i32(tmp
, 0);
5728 tmp3
= neon_load_reg(rm
, 1);
5729 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5730 tcg_temp_free_i32(tmp5
);
5731 tcg_temp_free_i32(tmp4
);
5732 neon_store_reg(rd
, 0, tmp2
);
5733 neon_store_reg(rd
, 1, tmp3
);
5735 } else if ((insn
& 0x380) == 0) {
5737 if (insn
& (1 << 19)) {
5738 tmp
= neon_load_reg(rm
, 1);
5740 tmp
= neon_load_reg(rm
, 0);
5742 if (insn
& (1 << 16)) {
5743 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5744 } else if (insn
& (1 << 17)) {
5745 if ((insn
>> 18) & 1)
5746 gen_neon_dup_high16(tmp
);
5748 gen_neon_dup_low16(tmp
);
5750 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5752 tcg_gen_mov_i32(tmp2
, tmp
);
5753 neon_store_reg(rd
, pass
, tmp2
);
5764 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5766 int crn
= (insn
>> 16) & 0xf;
5767 int crm
= insn
& 0xf;
5768 int op1
= (insn
>> 21) & 7;
5769 int op2
= (insn
>> 5) & 7;
5770 int rt
= (insn
>> 12) & 0xf;
5773 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5774 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5778 tmp
= load_cpu_field(teecr
);
5779 store_reg(s
, rt
, tmp
);
5782 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5784 if (IS_USER(s
) && (env
->teecr
& 1))
5786 tmp
= load_cpu_field(teehbr
);
5787 store_reg(s
, rt
, tmp
);
5791 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5792 op1
, crn
, crm
, op2
);
5796 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5798 int crn
= (insn
>> 16) & 0xf;
5799 int crm
= insn
& 0xf;
5800 int op1
= (insn
>> 21) & 7;
5801 int op2
= (insn
>> 5) & 7;
5802 int rt
= (insn
>> 12) & 0xf;
5805 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5806 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5810 tmp
= load_reg(s
, rt
);
5811 gen_helper_set_teecr(cpu_env
, tmp
);
5815 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5817 if (IS_USER(s
) && (env
->teecr
& 1))
5819 tmp
= load_reg(s
, rt
);
5820 store_cpu_field(tmp
, teehbr
);
5824 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5825 op1
, crn
, crm
, op2
);
5829 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5833 cpnum
= (insn
>> 8) & 0xf;
5834 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5835 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5841 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5842 return disas_iwmmxt_insn(env
, s
, insn
);
5843 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5844 return disas_dsp_insn(env
, s
, insn
);
5849 return disas_vfp_insn (env
, s
, insn
);
5851 /* Coprocessors 7-15 are architecturally reserved by ARM.
5852 Unfortunately Intel decided to ignore this. */
5853 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5855 if (insn
& (1 << 20))
5856 return disas_cp14_read(env
, s
, insn
);
5858 return disas_cp14_write(env
, s
, insn
);
5860 return disas_cp15_insn (env
, s
, insn
);
5863 /* Unknown coprocessor. See if the board has hooked it. */
5864 return disas_cp_insn (env
, s
, insn
);
5869 /* Store a 64-bit value to a register pair. Clobbers val. */
5870 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5874 tcg_gen_trunc_i64_i32(tmp
, val
);
5875 store_reg(s
, rlow
, tmp
);
5877 tcg_gen_shri_i64(val
, val
, 32);
5878 tcg_gen_trunc_i64_i32(tmp
, val
);
5879 store_reg(s
, rhigh
, tmp
);
5882 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5883 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5888 /* Load value and extend to 64 bits. */
5889 tmp
= tcg_temp_new_i64();
5890 tmp2
= load_reg(s
, rlow
);
5891 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5893 tcg_gen_add_i64(val
, val
, tmp
);
5894 tcg_temp_free_i64(tmp
);
5897 /* load and add a 64-bit value from a register pair. */
5898 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5904 /* Load 64-bit value rd:rn. */
5905 tmpl
= load_reg(s
, rlow
);
5906 tmph
= load_reg(s
, rhigh
);
5907 tmp
= tcg_temp_new_i64();
5908 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5911 tcg_gen_add_i64(val
, val
, tmp
);
5912 tcg_temp_free_i64(tmp
);
5915 /* Set N and Z flags from a 64-bit value. */
5916 static void gen_logicq_cc(TCGv_i64 val
)
5918 TCGv tmp
= new_tmp();
5919 gen_helper_logicq_cc(tmp
, val
);
5924 /* Load/Store exclusive instructions are implemented by remembering
5925 the value/address loaded, and seeing if these are the same
5926 when the store is performed. This should be is sufficient to implement
5927 the architecturally mandated semantics, and avoids having to monitor
5930 In system emulation mode only one CPU will be running at once, so
5931 this sequence is effectively atomic. In user emulation mode we
5932 throw an exception and handle the atomic operation elsewhere. */
5933 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
5934 TCGv addr
, int size
)
5940 tmp
= gen_ld8u(addr
, IS_USER(s
));
5943 tmp
= gen_ld16u(addr
, IS_USER(s
));
5947 tmp
= gen_ld32(addr
, IS_USER(s
));
5952 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
5953 store_reg(s
, rt
, tmp
);
5955 TCGv tmp2
= new_tmp();
5956 tcg_gen_addi_i32(tmp2
, addr
, 4);
5957 tmp
= gen_ld32(tmp2
, IS_USER(s
));
5959 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
5960 store_reg(s
, rt2
, tmp
);
5962 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
5965 static void gen_clrex(DisasContext
*s
)
5967 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
5970 #ifdef CONFIG_USER_ONLY
5971 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5972 TCGv addr
, int size
)
5974 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
5975 tcg_gen_movi_i32(cpu_exclusive_info
,
5976 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
5977 gen_set_condexec(s
);
5978 gen_set_pc_im(s
->pc
- 4);
5979 gen_exception(EXCP_STREX
);
5980 s
->is_jmp
= DISAS_JUMP
;
5983 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5984 TCGv addr
, int size
)
5990 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5996 fail_label
= gen_new_label();
5997 done_label
= gen_new_label();
5998 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
6001 tmp
= gen_ld8u(addr
, IS_USER(s
));
6004 tmp
= gen_ld16u(addr
, IS_USER(s
));
6008 tmp
= gen_ld32(addr
, IS_USER(s
));
6013 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
6016 TCGv tmp2
= new_tmp();
6017 tcg_gen_addi_i32(tmp2
, addr
, 4);
6018 tmp
= gen_ld32(tmp2
, IS_USER(s
));
6020 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6023 tmp
= load_reg(s
, rt
);
6026 gen_st8(tmp
, addr
, IS_USER(s
));
6029 gen_st16(tmp
, addr
, IS_USER(s
));
6033 gen_st32(tmp
, addr
, IS_USER(s
));
6039 tcg_gen_addi_i32(addr
, addr
, 4);
6040 tmp
= load_reg(s
, rt2
);
6041 gen_st32(tmp
, addr
, IS_USER(s
));
6043 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6044 tcg_gen_br(done_label
);
6045 gen_set_label(fail_label
);
6046 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6047 gen_set_label(done_label
);
6048 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6052 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
6054 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6061 insn
= ldl_code(s
->pc
);
6064 /* M variants do not implement ARM mode. */
6069 /* Unconditional instructions. */
6070 if (((insn
>> 25) & 7) == 1) {
6071 /* NEON Data processing. */
6072 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6075 if (disas_neon_data_insn(env
, s
, insn
))
6079 if ((insn
& 0x0f100000) == 0x04000000) {
6080 /* NEON load/store. */
6081 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6084 if (disas_neon_ls_insn(env
, s
, insn
))
6088 if ((insn
& 0x0d70f000) == 0x0550f000)
6090 else if ((insn
& 0x0ffffdff) == 0x01010000) {
6093 if (insn
& (1 << 9)) {
6094 /* BE8 mode not implemented. */
6098 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6099 switch ((insn
>> 4) & 0xf) {
6108 /* We don't emulate caches so these are a no-op. */
6113 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6119 op1
= (insn
& 0x1f);
6121 tmp
= tcg_const_i32(op1
);
6122 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6123 tcg_temp_free_i32(tmp
);
6124 i
= (insn
>> 23) & 3;
6126 case 0: offset
= -4; break; /* DA */
6127 case 1: offset
= 0; break; /* IA */
6128 case 2: offset
= -8; break; /* DB */
6129 case 3: offset
= 4; break; /* IB */
6133 tcg_gen_addi_i32(addr
, addr
, offset
);
6134 tmp
= load_reg(s
, 14);
6135 gen_st32(tmp
, addr
, 0);
6136 tmp
= load_cpu_field(spsr
);
6137 tcg_gen_addi_i32(addr
, addr
, 4);
6138 gen_st32(tmp
, addr
, 0);
6139 if (insn
& (1 << 21)) {
6140 /* Base writeback. */
6142 case 0: offset
= -8; break;
6143 case 1: offset
= 4; break;
6144 case 2: offset
= -4; break;
6145 case 3: offset
= 0; break;
6149 tcg_gen_addi_i32(addr
, addr
, offset
);
6150 tmp
= tcg_const_i32(op1
);
6151 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6152 tcg_temp_free_i32(tmp
);
6158 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6164 rn
= (insn
>> 16) & 0xf;
6165 addr
= load_reg(s
, rn
);
6166 i
= (insn
>> 23) & 3;
6168 case 0: offset
= -4; break; /* DA */
6169 case 1: offset
= 0; break; /* IA */
6170 case 2: offset
= -8; break; /* DB */
6171 case 3: offset
= 4; break; /* IB */
6175 tcg_gen_addi_i32(addr
, addr
, offset
);
6176 /* Load PC into tmp and CPSR into tmp2. */
6177 tmp
= gen_ld32(addr
, 0);
6178 tcg_gen_addi_i32(addr
, addr
, 4);
6179 tmp2
= gen_ld32(addr
, 0);
6180 if (insn
& (1 << 21)) {
6181 /* Base writeback. */
6183 case 0: offset
= -8; break;
6184 case 1: offset
= 4; break;
6185 case 2: offset
= -4; break;
6186 case 3: offset
= 0; break;
6190 tcg_gen_addi_i32(addr
, addr
, offset
);
6191 store_reg(s
, rn
, addr
);
6195 gen_rfe(s
, tmp
, tmp2
);
6197 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6198 /* branch link and change to thumb (blx <offset>) */
6201 val
= (uint32_t)s
->pc
;
6203 tcg_gen_movi_i32(tmp
, val
);
6204 store_reg(s
, 14, tmp
);
6205 /* Sign-extend the 24-bit offset */
6206 offset
= (((int32_t)insn
) << 8) >> 8;
6207 /* offset * 4 + bit24 * 2 + (thumb bit) */
6208 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6209 /* pipeline offset */
6213 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6214 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6215 /* iWMMXt register transfer. */
6216 if (env
->cp15
.c15_cpar
& (1 << 1))
6217 if (!disas_iwmmxt_insn(env
, s
, insn
))
6220 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6221 /* Coprocessor double register transfer. */
6222 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6223 /* Additional coprocessor register transfer. */
6224 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6227 /* cps (privileged) */
6231 if (insn
& (1 << 19)) {
6232 if (insn
& (1 << 8))
6234 if (insn
& (1 << 7))
6236 if (insn
& (1 << 6))
6238 if (insn
& (1 << 18))
6241 if (insn
& (1 << 17)) {
6243 val
|= (insn
& 0x1f);
6246 gen_set_psr_im(s
, mask
, 0, val
);
6253 /* if not always execute, we generate a conditional jump to
6255 s
->condlabel
= gen_new_label();
6256 gen_test_cc(cond
^ 1, s
->condlabel
);
6259 if ((insn
& 0x0f900000) == 0x03000000) {
6260 if ((insn
& (1 << 21)) == 0) {
6262 rd
= (insn
>> 12) & 0xf;
6263 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6264 if ((insn
& (1 << 22)) == 0) {
6267 tcg_gen_movi_i32(tmp
, val
);
6270 tmp
= load_reg(s
, rd
);
6271 tcg_gen_ext16u_i32(tmp
, tmp
);
6272 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6274 store_reg(s
, rd
, tmp
);
6276 if (((insn
>> 12) & 0xf) != 0xf)
6278 if (((insn
>> 16) & 0xf) == 0) {
6279 gen_nop_hint(s
, insn
& 0xff);
6281 /* CPSR = immediate */
6283 shift
= ((insn
>> 8) & 0xf) * 2;
6285 val
= (val
>> shift
) | (val
<< (32 - shift
));
6286 i
= ((insn
& (1 << 22)) != 0);
6287 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6291 } else if ((insn
& 0x0f900000) == 0x01000000
6292 && (insn
& 0x00000090) != 0x00000090) {
6293 /* miscellaneous instructions */
6294 op1
= (insn
>> 21) & 3;
6295 sh
= (insn
>> 4) & 0xf;
6298 case 0x0: /* move program status register */
6301 tmp
= load_reg(s
, rm
);
6302 i
= ((op1
& 2) != 0);
6303 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6307 rd
= (insn
>> 12) & 0xf;
6311 tmp
= load_cpu_field(spsr
);
6314 gen_helper_cpsr_read(tmp
);
6316 store_reg(s
, rd
, tmp
);
6321 /* branch/exchange thumb (bx). */
6322 tmp
= load_reg(s
, rm
);
6324 } else if (op1
== 3) {
6326 rd
= (insn
>> 12) & 0xf;
6327 tmp
= load_reg(s
, rm
);
6328 gen_helper_clz(tmp
, tmp
);
6329 store_reg(s
, rd
, tmp
);
6337 /* Trivial implementation equivalent to bx. */
6338 tmp
= load_reg(s
, rm
);
6348 /* branch link/exchange thumb (blx) */
6349 tmp
= load_reg(s
, rm
);
6351 tcg_gen_movi_i32(tmp2
, s
->pc
);
6352 store_reg(s
, 14, tmp2
);
6355 case 0x5: /* saturating add/subtract */
6356 rd
= (insn
>> 12) & 0xf;
6357 rn
= (insn
>> 16) & 0xf;
6358 tmp
= load_reg(s
, rm
);
6359 tmp2
= load_reg(s
, rn
);
6361 gen_helper_double_saturate(tmp2
, tmp2
);
6363 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6365 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6367 store_reg(s
, rd
, tmp
);
6370 /* SMC instruction (op1 == 3)
6371 and undefined instructions (op1 == 0 || op1 == 2)
6377 gen_set_condexec(s
);
6378 gen_set_pc_im(s
->pc
- 4);
6379 gen_exception(EXCP_BKPT
);
6380 s
->is_jmp
= DISAS_JUMP
;
6382 case 0x8: /* signed multiply */
6386 rs
= (insn
>> 8) & 0xf;
6387 rn
= (insn
>> 12) & 0xf;
6388 rd
= (insn
>> 16) & 0xf;
6390 /* (32 * 16) >> 16 */
6391 tmp
= load_reg(s
, rm
);
6392 tmp2
= load_reg(s
, rs
);
6394 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6397 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6398 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6400 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6401 tcg_temp_free_i64(tmp64
);
6402 if ((sh
& 2) == 0) {
6403 tmp2
= load_reg(s
, rn
);
6404 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6407 store_reg(s
, rd
, tmp
);
6410 tmp
= load_reg(s
, rm
);
6411 tmp2
= load_reg(s
, rs
);
6412 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6415 tmp64
= tcg_temp_new_i64();
6416 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6418 gen_addq(s
, tmp64
, rn
, rd
);
6419 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6420 tcg_temp_free_i64(tmp64
);
6423 tmp2
= load_reg(s
, rn
);
6424 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6427 store_reg(s
, rd
, tmp
);
6434 } else if (((insn
& 0x0e000000) == 0 &&
6435 (insn
& 0x00000090) != 0x90) ||
6436 ((insn
& 0x0e000000) == (1 << 25))) {
6437 int set_cc
, logic_cc
, shiftop
;
6439 op1
= (insn
>> 21) & 0xf;
6440 set_cc
= (insn
>> 20) & 1;
6441 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6443 /* data processing instruction */
6444 if (insn
& (1 << 25)) {
6445 /* immediate operand */
6447 shift
= ((insn
>> 8) & 0xf) * 2;
6449 val
= (val
>> shift
) | (val
<< (32 - shift
));
6452 tcg_gen_movi_i32(tmp2
, val
);
6453 if (logic_cc
&& shift
) {
6454 gen_set_CF_bit31(tmp2
);
6459 tmp2
= load_reg(s
, rm
);
6460 shiftop
= (insn
>> 5) & 3;
6461 if (!(insn
& (1 << 4))) {
6462 shift
= (insn
>> 7) & 0x1f;
6463 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6465 rs
= (insn
>> 8) & 0xf;
6466 tmp
= load_reg(s
, rs
);
6467 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6470 if (op1
!= 0x0f && op1
!= 0x0d) {
6471 rn
= (insn
>> 16) & 0xf;
6472 tmp
= load_reg(s
, rn
);
6476 rd
= (insn
>> 12) & 0xf;
6479 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6483 store_reg_bx(env
, s
, rd
, tmp
);
6486 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6490 store_reg_bx(env
, s
, rd
, tmp
);
6493 if (set_cc
&& rd
== 15) {
6494 /* SUBS r15, ... is used for exception return. */
6498 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6499 gen_exception_return(s
, tmp
);
6502 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6504 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6506 store_reg_bx(env
, s
, rd
, tmp
);
6511 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6513 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6515 store_reg_bx(env
, s
, rd
, tmp
);
6519 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6521 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6523 store_reg_bx(env
, s
, rd
, tmp
);
6527 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6529 gen_add_carry(tmp
, tmp
, tmp2
);
6531 store_reg_bx(env
, s
, rd
, tmp
);
6535 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6537 gen_sub_carry(tmp
, tmp
, tmp2
);
6539 store_reg_bx(env
, s
, rd
, tmp
);
6543 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6545 gen_sub_carry(tmp
, tmp2
, tmp
);
6547 store_reg_bx(env
, s
, rd
, tmp
);
6551 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6558 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6565 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6571 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6576 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6580 store_reg_bx(env
, s
, rd
, tmp
);
6583 if (logic_cc
&& rd
== 15) {
6584 /* MOVS r15, ... is used for exception return. */
6588 gen_exception_return(s
, tmp2
);
6593 store_reg_bx(env
, s
, rd
, tmp2
);
6597 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6601 store_reg_bx(env
, s
, rd
, tmp
);
6605 tcg_gen_not_i32(tmp2
, tmp2
);
6609 store_reg_bx(env
, s
, rd
, tmp2
);
6612 if (op1
!= 0x0f && op1
!= 0x0d) {
6616 /* other instructions */
6617 op1
= (insn
>> 24) & 0xf;
6621 /* multiplies, extra load/stores */
6622 sh
= (insn
>> 5) & 3;
6625 rd
= (insn
>> 16) & 0xf;
6626 rn
= (insn
>> 12) & 0xf;
6627 rs
= (insn
>> 8) & 0xf;
6629 op1
= (insn
>> 20) & 0xf;
6631 case 0: case 1: case 2: case 3: case 6:
6633 tmp
= load_reg(s
, rs
);
6634 tmp2
= load_reg(s
, rm
);
6635 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6637 if (insn
& (1 << 22)) {
6638 /* Subtract (mls) */
6640 tmp2
= load_reg(s
, rn
);
6641 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6643 } else if (insn
& (1 << 21)) {
6645 tmp2
= load_reg(s
, rn
);
6646 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6649 if (insn
& (1 << 20))
6651 store_reg(s
, rd
, tmp
);
6654 /* 64 bit mul double accumulate (UMAAL) */
6656 tmp
= load_reg(s
, rs
);
6657 tmp2
= load_reg(s
, rm
);
6658 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6659 gen_addq_lo(s
, tmp64
, rn
);
6660 gen_addq_lo(s
, tmp64
, rd
);
6661 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6662 tcg_temp_free_i64(tmp64
);
6664 case 8: case 9: case 10: case 11:
6665 case 12: case 13: case 14: case 15:
6666 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6667 tmp
= load_reg(s
, rs
);
6668 tmp2
= load_reg(s
, rm
);
6669 if (insn
& (1 << 22)) {
6670 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6672 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6674 if (insn
& (1 << 21)) { /* mult accumulate */
6675 gen_addq(s
, tmp64
, rn
, rd
);
6677 if (insn
& (1 << 20)) {
6678 gen_logicq_cc(tmp64
);
6680 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6681 tcg_temp_free_i64(tmp64
);
6687 rn
= (insn
>> 16) & 0xf;
6688 rd
= (insn
>> 12) & 0xf;
6689 if (insn
& (1 << 23)) {
6690 /* load/store exclusive */
6691 op1
= (insn
>> 21) & 0x3;
6696 addr
= tcg_temp_local_new_i32();
6697 load_reg_var(s
, addr
, rn
);
6698 if (insn
& (1 << 20)) {
6701 gen_load_exclusive(s
, rd
, 15, addr
, 2);
6703 case 1: /* ldrexd */
6704 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
6706 case 2: /* ldrexb */
6707 gen_load_exclusive(s
, rd
, 15, addr
, 0);
6709 case 3: /* ldrexh */
6710 gen_load_exclusive(s
, rd
, 15, addr
, 1);
6719 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
6721 case 1: /* strexd */
6722 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
6724 case 2: /* strexb */
6725 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
6727 case 3: /* strexh */
6728 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
6734 tcg_temp_free(addr
);
6736 /* SWP instruction */
6739 /* ??? This is not really atomic. However we know
6740 we never have multiple CPUs running in parallel,
6741 so it is good enough. */
6742 addr
= load_reg(s
, rn
);
6743 tmp
= load_reg(s
, rm
);
6744 if (insn
& (1 << 22)) {
6745 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6746 gen_st8(tmp
, addr
, IS_USER(s
));
6748 tmp2
= gen_ld32(addr
, IS_USER(s
));
6749 gen_st32(tmp
, addr
, IS_USER(s
));
6752 store_reg(s
, rd
, tmp2
);
6758 /* Misc load/store */
6759 rn
= (insn
>> 16) & 0xf;
6760 rd
= (insn
>> 12) & 0xf;
6761 addr
= load_reg(s
, rn
);
6762 if (insn
& (1 << 24))
6763 gen_add_datah_offset(s
, insn
, 0, addr
);
6765 if (insn
& (1 << 20)) {
6769 tmp
= gen_ld16u(addr
, IS_USER(s
));
6772 tmp
= gen_ld8s(addr
, IS_USER(s
));
6776 tmp
= gen_ld16s(addr
, IS_USER(s
));
6780 } else if (sh
& 2) {
6784 tmp
= load_reg(s
, rd
);
6785 gen_st32(tmp
, addr
, IS_USER(s
));
6786 tcg_gen_addi_i32(addr
, addr
, 4);
6787 tmp
= load_reg(s
, rd
+ 1);
6788 gen_st32(tmp
, addr
, IS_USER(s
));
6792 tmp
= gen_ld32(addr
, IS_USER(s
));
6793 store_reg(s
, rd
, tmp
);
6794 tcg_gen_addi_i32(addr
, addr
, 4);
6795 tmp
= gen_ld32(addr
, IS_USER(s
));
6799 address_offset
= -4;
6802 tmp
= load_reg(s
, rd
);
6803 gen_st16(tmp
, addr
, IS_USER(s
));
6806 /* Perform base writeback before the loaded value to
6807 ensure correct behavior with overlapping index registers.
6808 ldrd with base writeback is is undefined if the
6809 destination and index registers overlap. */
6810 if (!(insn
& (1 << 24))) {
6811 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6812 store_reg(s
, rn
, addr
);
6813 } else if (insn
& (1 << 21)) {
6815 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6816 store_reg(s
, rn
, addr
);
6821 /* Complete the load. */
6822 store_reg(s
, rd
, tmp
);
6831 if (insn
& (1 << 4)) {
6833 /* Armv6 Media instructions. */
6835 rn
= (insn
>> 16) & 0xf;
6836 rd
= (insn
>> 12) & 0xf;
6837 rs
= (insn
>> 8) & 0xf;
6838 switch ((insn
>> 23) & 3) {
6839 case 0: /* Parallel add/subtract. */
6840 op1
= (insn
>> 20) & 7;
6841 tmp
= load_reg(s
, rn
);
6842 tmp2
= load_reg(s
, rm
);
6843 sh
= (insn
>> 5) & 7;
6844 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6846 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6848 store_reg(s
, rd
, tmp
);
6851 if ((insn
& 0x00700020) == 0) {
6852 /* Halfword pack. */
6853 tmp
= load_reg(s
, rn
);
6854 tmp2
= load_reg(s
, rm
);
6855 shift
= (insn
>> 7) & 0x1f;
6856 if (insn
& (1 << 6)) {
6860 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6861 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6862 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6866 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6867 tcg_gen_ext16u_i32(tmp
, tmp
);
6868 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6870 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6872 store_reg(s
, rd
, tmp
);
6873 } else if ((insn
& 0x00200020) == 0x00200000) {
6875 tmp
= load_reg(s
, rm
);
6876 shift
= (insn
>> 7) & 0x1f;
6877 if (insn
& (1 << 6)) {
6880 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6882 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6884 sh
= (insn
>> 16) & 0x1f;
6886 tmp2
= tcg_const_i32(sh
);
6887 if (insn
& (1 << 22))
6888 gen_helper_usat(tmp
, tmp
, tmp2
);
6890 gen_helper_ssat(tmp
, tmp
, tmp2
);
6891 tcg_temp_free_i32(tmp2
);
6893 store_reg(s
, rd
, tmp
);
6894 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6896 tmp
= load_reg(s
, rm
);
6897 sh
= (insn
>> 16) & 0x1f;
6899 tmp2
= tcg_const_i32(sh
);
6900 if (insn
& (1 << 22))
6901 gen_helper_usat16(tmp
, tmp
, tmp2
);
6903 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6904 tcg_temp_free_i32(tmp2
);
6906 store_reg(s
, rd
, tmp
);
6907 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6909 tmp
= load_reg(s
, rn
);
6910 tmp2
= load_reg(s
, rm
);
6912 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6913 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6916 store_reg(s
, rd
, tmp
);
6917 } else if ((insn
& 0x000003e0) == 0x00000060) {
6918 tmp
= load_reg(s
, rm
);
6919 shift
= (insn
>> 10) & 3;
6920 /* ??? In many cases it's not neccessary to do a
6921 rotate, a shift is sufficient. */
6923 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6924 op1
= (insn
>> 20) & 7;
6926 case 0: gen_sxtb16(tmp
); break;
6927 case 2: gen_sxtb(tmp
); break;
6928 case 3: gen_sxth(tmp
); break;
6929 case 4: gen_uxtb16(tmp
); break;
6930 case 6: gen_uxtb(tmp
); break;
6931 case 7: gen_uxth(tmp
); break;
6932 default: goto illegal_op
;
6935 tmp2
= load_reg(s
, rn
);
6936 if ((op1
& 3) == 0) {
6937 gen_add16(tmp
, tmp2
);
6939 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6943 store_reg(s
, rd
, tmp
);
6944 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6946 tmp
= load_reg(s
, rm
);
6947 if (insn
& (1 << 22)) {
6948 if (insn
& (1 << 7)) {
6952 gen_helper_rbit(tmp
, tmp
);
6955 if (insn
& (1 << 7))
6958 tcg_gen_bswap32_i32(tmp
, tmp
);
6960 store_reg(s
, rd
, tmp
);
6965 case 2: /* Multiplies (Type 3). */
6966 tmp
= load_reg(s
, rm
);
6967 tmp2
= load_reg(s
, rs
);
6968 if (insn
& (1 << 20)) {
6969 /* Signed multiply most significant [accumulate].
6970 (SMMUL, SMMLA, SMMLS) */
6971 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6974 tmp
= load_reg(s
, rd
);
6975 if (insn
& (1 << 6)) {
6976 tmp64
= gen_subq_msw(tmp64
, tmp
);
6978 tmp64
= gen_addq_msw(tmp64
, tmp
);
6981 if (insn
& (1 << 5)) {
6982 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6984 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6986 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6987 tcg_temp_free_i64(tmp64
);
6988 store_reg(s
, rn
, tmp
);
6990 if (insn
& (1 << 5))
6991 gen_swap_half(tmp2
);
6992 gen_smul_dual(tmp
, tmp2
);
6993 /* This addition cannot overflow. */
6994 if (insn
& (1 << 6)) {
6995 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6997 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7000 if (insn
& (1 << 22)) {
7001 /* smlald, smlsld */
7002 tmp64
= tcg_temp_new_i64();
7003 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7005 gen_addq(s
, tmp64
, rd
, rn
);
7006 gen_storeq_reg(s
, rd
, rn
, tmp64
);
7007 tcg_temp_free_i64(tmp64
);
7009 /* smuad, smusd, smlad, smlsd */
7012 tmp2
= load_reg(s
, rd
);
7013 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7016 store_reg(s
, rn
, tmp
);
7021 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
7023 case 0: /* Unsigned sum of absolute differences. */
7025 tmp
= load_reg(s
, rm
);
7026 tmp2
= load_reg(s
, rs
);
7027 gen_helper_usad8(tmp
, tmp
, tmp2
);
7030 tmp2
= load_reg(s
, rd
);
7031 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7034 store_reg(s
, rn
, tmp
);
7036 case 0x20: case 0x24: case 0x28: case 0x2c:
7037 /* Bitfield insert/clear. */
7039 shift
= (insn
>> 7) & 0x1f;
7040 i
= (insn
>> 16) & 0x1f;
7044 tcg_gen_movi_i32(tmp
, 0);
7046 tmp
= load_reg(s
, rm
);
7049 tmp2
= load_reg(s
, rd
);
7050 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
7053 store_reg(s
, rd
, tmp
);
7055 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7056 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7058 tmp
= load_reg(s
, rm
);
7059 shift
= (insn
>> 7) & 0x1f;
7060 i
= ((insn
>> 16) & 0x1f) + 1;
7065 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7067 gen_sbfx(tmp
, shift
, i
);
7070 store_reg(s
, rd
, tmp
);
7080 /* Check for undefined extension instructions
7081 * per the ARM Bible IE:
7082 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7084 sh
= (0xf << 20) | (0xf << 4);
7085 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7089 /* load/store byte/word */
7090 rn
= (insn
>> 16) & 0xf;
7091 rd
= (insn
>> 12) & 0xf;
7092 tmp2
= load_reg(s
, rn
);
7093 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7094 if (insn
& (1 << 24))
7095 gen_add_data_offset(s
, insn
, tmp2
);
7096 if (insn
& (1 << 20)) {
7098 if (insn
& (1 << 22)) {
7099 tmp
= gen_ld8u(tmp2
, i
);
7101 tmp
= gen_ld32(tmp2
, i
);
7105 tmp
= load_reg(s
, rd
);
7106 if (insn
& (1 << 22))
7107 gen_st8(tmp
, tmp2
, i
);
7109 gen_st32(tmp
, tmp2
, i
);
7111 if (!(insn
& (1 << 24))) {
7112 gen_add_data_offset(s
, insn
, tmp2
);
7113 store_reg(s
, rn
, tmp2
);
7114 } else if (insn
& (1 << 21)) {
7115 store_reg(s
, rn
, tmp2
);
7119 if (insn
& (1 << 20)) {
7120 /* Complete the load. */
7124 store_reg(s
, rd
, tmp
);
7130 int j
, n
, user
, loaded_base
;
7132 /* load/store multiple words */
7133 /* XXX: store correct base if write back */
7135 if (insn
& (1 << 22)) {
7137 goto illegal_op
; /* only usable in supervisor mode */
7139 if ((insn
& (1 << 15)) == 0)
7142 rn
= (insn
>> 16) & 0xf;
7143 addr
= load_reg(s
, rn
);
7145 /* compute total size */
7147 TCGV_UNUSED(loaded_var
);
7150 if (insn
& (1 << i
))
7153 /* XXX: test invalid n == 0 case ? */
7154 if (insn
& (1 << 23)) {
7155 if (insn
& (1 << 24)) {
7157 tcg_gen_addi_i32(addr
, addr
, 4);
7159 /* post increment */
7162 if (insn
& (1 << 24)) {
7164 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7166 /* post decrement */
7168 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7173 if (insn
& (1 << i
)) {
7174 if (insn
& (1 << 20)) {
7176 tmp
= gen_ld32(addr
, IS_USER(s
));
7180 tmp2
= tcg_const_i32(i
);
7181 gen_helper_set_user_reg(tmp2
, tmp
);
7182 tcg_temp_free_i32(tmp2
);
7184 } else if (i
== rn
) {
7188 store_reg(s
, i
, tmp
);
7193 /* special case: r15 = PC + 8 */
7194 val
= (long)s
->pc
+ 4;
7196 tcg_gen_movi_i32(tmp
, val
);
7199 tmp2
= tcg_const_i32(i
);
7200 gen_helper_get_user_reg(tmp
, tmp2
);
7201 tcg_temp_free_i32(tmp2
);
7203 tmp
= load_reg(s
, i
);
7205 gen_st32(tmp
, addr
, IS_USER(s
));
7208 /* no need to add after the last transfer */
7210 tcg_gen_addi_i32(addr
, addr
, 4);
7213 if (insn
& (1 << 21)) {
7215 if (insn
& (1 << 23)) {
7216 if (insn
& (1 << 24)) {
7219 /* post increment */
7220 tcg_gen_addi_i32(addr
, addr
, 4);
7223 if (insn
& (1 << 24)) {
7226 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7228 /* post decrement */
7229 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7232 store_reg(s
, rn
, addr
);
7237 store_reg(s
, rn
, loaded_var
);
7239 if ((insn
& (1 << 22)) && !user
) {
7240 /* Restore CPSR from SPSR. */
7241 tmp
= load_cpu_field(spsr
);
7242 gen_set_cpsr(tmp
, 0xffffffff);
7244 s
->is_jmp
= DISAS_UPDATE
;
7253 /* branch (and link) */
7254 val
= (int32_t)s
->pc
;
7255 if (insn
& (1 << 24)) {
7257 tcg_gen_movi_i32(tmp
, val
);
7258 store_reg(s
, 14, tmp
);
7260 offset
= (((int32_t)insn
<< 8) >> 8);
7261 val
+= (offset
<< 2) + 4;
7269 if (disas_coproc_insn(env
, s
, insn
))
7274 gen_set_pc_im(s
->pc
);
7275 s
->is_jmp
= DISAS_SWI
;
7279 gen_set_condexec(s
);
7280 gen_set_pc_im(s
->pc
- 4);
7281 gen_exception(EXCP_UDEF
);
7282 s
->is_jmp
= DISAS_JUMP
;
7288 /* Return true if this is a Thumb-2 logical op. */
7290 thumb2_logic_op(int op
)
7295 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7296 then set condition code flags based on the result of the operation.
7297 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7298 to the high bit of T1.
7299 Returns zero if the opcode is valid. */
7302 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7309 tcg_gen_and_i32(t0
, t0
, t1
);
7313 tcg_gen_andc_i32(t0
, t0
, t1
);
7317 tcg_gen_or_i32(t0
, t0
, t1
);
7321 tcg_gen_not_i32(t1
, t1
);
7322 tcg_gen_or_i32(t0
, t0
, t1
);
7326 tcg_gen_xor_i32(t0
, t0
, t1
);
7331 gen_helper_add_cc(t0
, t0
, t1
);
7333 tcg_gen_add_i32(t0
, t0
, t1
);
7337 gen_helper_adc_cc(t0
, t0
, t1
);
7343 gen_helper_sbc_cc(t0
, t0
, t1
);
7345 gen_sub_carry(t0
, t0
, t1
);
7349 gen_helper_sub_cc(t0
, t0
, t1
);
7351 tcg_gen_sub_i32(t0
, t0
, t1
);
7355 gen_helper_sub_cc(t0
, t1
, t0
);
7357 tcg_gen_sub_i32(t0
, t1
, t0
);
7359 default: /* 5, 6, 7, 9, 12, 15. */
7365 gen_set_CF_bit31(t1
);
7370 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7372 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7374 uint32_t insn
, imm
, shift
, offset
;
7375 uint32_t rd
, rn
, rm
, rs
;
7386 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7387 || arm_feature (env
, ARM_FEATURE_M
))) {
7388 /* Thumb-1 cores may need to treat bl and blx as a pair of
7389 16-bit instructions to get correct prefetch abort behavior. */
7391 if ((insn
& (1 << 12)) == 0) {
7392 /* Second half of blx. */
7393 offset
= ((insn
& 0x7ff) << 1);
7394 tmp
= load_reg(s
, 14);
7395 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7396 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7399 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7400 store_reg(s
, 14, tmp2
);
7404 if (insn
& (1 << 11)) {
7405 /* Second half of bl. */
7406 offset
= ((insn
& 0x7ff) << 1) | 1;
7407 tmp
= load_reg(s
, 14);
7408 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7411 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7412 store_reg(s
, 14, tmp2
);
7416 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7417 /* Instruction spans a page boundary. Implement it as two
7418 16-bit instructions in case the second half causes an
7420 offset
= ((int32_t)insn
<< 21) >> 9;
7421 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7424 /* Fall through to 32-bit decode. */
7427 insn
= lduw_code(s
->pc
);
7429 insn
|= (uint32_t)insn_hw1
<< 16;
7431 if ((insn
& 0xf800e800) != 0xf000e800) {
7435 rn
= (insn
>> 16) & 0xf;
7436 rs
= (insn
>> 12) & 0xf;
7437 rd
= (insn
>> 8) & 0xf;
7439 switch ((insn
>> 25) & 0xf) {
7440 case 0: case 1: case 2: case 3:
7441 /* 16-bit instructions. Should never happen. */
7444 if (insn
& (1 << 22)) {
7445 /* Other load/store, table branch. */
7446 if (insn
& 0x01200000) {
7447 /* Load/store doubleword. */
7450 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7452 addr
= load_reg(s
, rn
);
7454 offset
= (insn
& 0xff) * 4;
7455 if ((insn
& (1 << 23)) == 0)
7457 if (insn
& (1 << 24)) {
7458 tcg_gen_addi_i32(addr
, addr
, offset
);
7461 if (insn
& (1 << 20)) {
7463 tmp
= gen_ld32(addr
, IS_USER(s
));
7464 store_reg(s
, rs
, tmp
);
7465 tcg_gen_addi_i32(addr
, addr
, 4);
7466 tmp
= gen_ld32(addr
, IS_USER(s
));
7467 store_reg(s
, rd
, tmp
);
7470 tmp
= load_reg(s
, rs
);
7471 gen_st32(tmp
, addr
, IS_USER(s
));
7472 tcg_gen_addi_i32(addr
, addr
, 4);
7473 tmp
= load_reg(s
, rd
);
7474 gen_st32(tmp
, addr
, IS_USER(s
));
7476 if (insn
& (1 << 21)) {
7477 /* Base writeback. */
7480 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7481 store_reg(s
, rn
, addr
);
7485 } else if ((insn
& (1 << 23)) == 0) {
7486 /* Load/store exclusive word. */
7487 addr
= tcg_temp_local_new();
7488 load_reg_var(s
, addr
, rn
);
7489 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
7490 if (insn
& (1 << 20)) {
7491 gen_load_exclusive(s
, rs
, 15, addr
, 2);
7493 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
7495 tcg_temp_free(addr
);
7496 } else if ((insn
& (1 << 6)) == 0) {
7500 tcg_gen_movi_i32(addr
, s
->pc
);
7502 addr
= load_reg(s
, rn
);
7504 tmp
= load_reg(s
, rm
);
7505 tcg_gen_add_i32(addr
, addr
, tmp
);
7506 if (insn
& (1 << 4)) {
7508 tcg_gen_add_i32(addr
, addr
, tmp
);
7510 tmp
= gen_ld16u(addr
, IS_USER(s
));
7513 tmp
= gen_ld8u(addr
, IS_USER(s
));
7516 tcg_gen_shli_i32(tmp
, tmp
, 1);
7517 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7518 store_reg(s
, 15, tmp
);
7520 /* Load/store exclusive byte/halfword/doubleword. */
7522 op
= (insn
>> 4) & 0x3;
7526 addr
= tcg_temp_local_new();
7527 load_reg_var(s
, addr
, rn
);
7528 if (insn
& (1 << 20)) {
7529 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
7531 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
7533 tcg_temp_free(addr
);
7536 /* Load/store multiple, RFE, SRS. */
7537 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7538 /* Not available in user mode. */
7541 if (insn
& (1 << 20)) {
7543 addr
= load_reg(s
, rn
);
7544 if ((insn
& (1 << 24)) == 0)
7545 tcg_gen_addi_i32(addr
, addr
, -8);
7546 /* Load PC into tmp and CPSR into tmp2. */
7547 tmp
= gen_ld32(addr
, 0);
7548 tcg_gen_addi_i32(addr
, addr
, 4);
7549 tmp2
= gen_ld32(addr
, 0);
7550 if (insn
& (1 << 21)) {
7551 /* Base writeback. */
7552 if (insn
& (1 << 24)) {
7553 tcg_gen_addi_i32(addr
, addr
, 4);
7555 tcg_gen_addi_i32(addr
, addr
, -4);
7557 store_reg(s
, rn
, addr
);
7561 gen_rfe(s
, tmp
, tmp2
);
7566 tmp
= tcg_const_i32(op
);
7567 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7568 tcg_temp_free_i32(tmp
);
7569 if ((insn
& (1 << 24)) == 0) {
7570 tcg_gen_addi_i32(addr
, addr
, -8);
7572 tmp
= load_reg(s
, 14);
7573 gen_st32(tmp
, addr
, 0);
7574 tcg_gen_addi_i32(addr
, addr
, 4);
7576 gen_helper_cpsr_read(tmp
);
7577 gen_st32(tmp
, addr
, 0);
7578 if (insn
& (1 << 21)) {
7579 if ((insn
& (1 << 24)) == 0) {
7580 tcg_gen_addi_i32(addr
, addr
, -4);
7582 tcg_gen_addi_i32(addr
, addr
, 4);
7584 tmp
= tcg_const_i32(op
);
7585 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7586 tcg_temp_free_i32(tmp
);
7593 /* Load/store multiple. */
7594 addr
= load_reg(s
, rn
);
7596 for (i
= 0; i
< 16; i
++) {
7597 if (insn
& (1 << i
))
7600 if (insn
& (1 << 24)) {
7601 tcg_gen_addi_i32(addr
, addr
, -offset
);
7604 for (i
= 0; i
< 16; i
++) {
7605 if ((insn
& (1 << i
)) == 0)
7607 if (insn
& (1 << 20)) {
7609 tmp
= gen_ld32(addr
, IS_USER(s
));
7613 store_reg(s
, i
, tmp
);
7617 tmp
= load_reg(s
, i
);
7618 gen_st32(tmp
, addr
, IS_USER(s
));
7620 tcg_gen_addi_i32(addr
, addr
, 4);
7622 if (insn
& (1 << 21)) {
7623 /* Base register writeback. */
7624 if (insn
& (1 << 24)) {
7625 tcg_gen_addi_i32(addr
, addr
, -offset
);
7627 /* Fault if writeback register is in register list. */
7628 if (insn
& (1 << rn
))
7630 store_reg(s
, rn
, addr
);
7639 op
= (insn
>> 21) & 0xf;
7641 /* Halfword pack. */
7642 tmp
= load_reg(s
, rn
);
7643 tmp2
= load_reg(s
, rm
);
7644 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
7645 if (insn
& (1 << 5)) {
7649 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7650 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7651 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7655 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7656 tcg_gen_ext16u_i32(tmp
, tmp
);
7657 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7659 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7661 store_reg(s
, rd
, tmp
);
7663 /* Data processing register constant shift. */
7666 tcg_gen_movi_i32(tmp
, 0);
7668 tmp
= load_reg(s
, rn
);
7670 tmp2
= load_reg(s
, rm
);
7672 shiftop
= (insn
>> 4) & 3;
7673 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7674 conds
= (insn
& (1 << 20)) != 0;
7675 logic_cc
= (conds
&& thumb2_logic_op(op
));
7676 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7677 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7681 store_reg(s
, rd
, tmp
);
7687 case 13: /* Misc data processing. */
7688 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7689 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7692 case 0: /* Register controlled shift. */
7693 tmp
= load_reg(s
, rn
);
7694 tmp2
= load_reg(s
, rm
);
7695 if ((insn
& 0x70) != 0)
7697 op
= (insn
>> 21) & 3;
7698 logic_cc
= (insn
& (1 << 20)) != 0;
7699 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7702 store_reg_bx(env
, s
, rd
, tmp
);
7704 case 1: /* Sign/zero extend. */
7705 tmp
= load_reg(s
, rm
);
7706 shift
= (insn
>> 4) & 3;
7707 /* ??? In many cases it's not neccessary to do a
7708 rotate, a shift is sufficient. */
7710 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7711 op
= (insn
>> 20) & 7;
7713 case 0: gen_sxth(tmp
); break;
7714 case 1: gen_uxth(tmp
); break;
7715 case 2: gen_sxtb16(tmp
); break;
7716 case 3: gen_uxtb16(tmp
); break;
7717 case 4: gen_sxtb(tmp
); break;
7718 case 5: gen_uxtb(tmp
); break;
7719 default: goto illegal_op
;
7722 tmp2
= load_reg(s
, rn
);
7723 if ((op
>> 1) == 1) {
7724 gen_add16(tmp
, tmp2
);
7726 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7730 store_reg(s
, rd
, tmp
);
7732 case 2: /* SIMD add/subtract. */
7733 op
= (insn
>> 20) & 7;
7734 shift
= (insn
>> 4) & 7;
7735 if ((op
& 3) == 3 || (shift
& 3) == 3)
7737 tmp
= load_reg(s
, rn
);
7738 tmp2
= load_reg(s
, rm
);
7739 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7741 store_reg(s
, rd
, tmp
);
7743 case 3: /* Other data processing. */
7744 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7746 /* Saturating add/subtract. */
7747 tmp
= load_reg(s
, rn
);
7748 tmp2
= load_reg(s
, rm
);
7750 gen_helper_double_saturate(tmp
, tmp
);
7752 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7754 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7757 tmp
= load_reg(s
, rn
);
7759 case 0x0a: /* rbit */
7760 gen_helper_rbit(tmp
, tmp
);
7762 case 0x08: /* rev */
7763 tcg_gen_bswap32_i32(tmp
, tmp
);
7765 case 0x09: /* rev16 */
7768 case 0x0b: /* revsh */
7771 case 0x10: /* sel */
7772 tmp2
= load_reg(s
, rm
);
7774 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7775 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7779 case 0x18: /* clz */
7780 gen_helper_clz(tmp
, tmp
);
7786 store_reg(s
, rd
, tmp
);
7788 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7789 op
= (insn
>> 4) & 0xf;
7790 tmp
= load_reg(s
, rn
);
7791 tmp2
= load_reg(s
, rm
);
7792 switch ((insn
>> 20) & 7) {
7793 case 0: /* 32 x 32 -> 32 */
7794 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7797 tmp2
= load_reg(s
, rs
);
7799 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7801 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7805 case 1: /* 16 x 16 -> 32 */
7806 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7809 tmp2
= load_reg(s
, rs
);
7810 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7814 case 2: /* Dual multiply add. */
7815 case 4: /* Dual multiply subtract. */
7817 gen_swap_half(tmp2
);
7818 gen_smul_dual(tmp
, tmp2
);
7819 /* This addition cannot overflow. */
7820 if (insn
& (1 << 22)) {
7821 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7823 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7828 tmp2
= load_reg(s
, rs
);
7829 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7833 case 3: /* 32 * 16 -> 32msb */
7835 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7838 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7839 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7841 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7842 tcg_temp_free_i64(tmp64
);
7845 tmp2
= load_reg(s
, rs
);
7846 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7850 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7851 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7853 tmp
= load_reg(s
, rs
);
7854 if (insn
& (1 << 20)) {
7855 tmp64
= gen_addq_msw(tmp64
, tmp
);
7857 tmp64
= gen_subq_msw(tmp64
, tmp
);
7860 if (insn
& (1 << 4)) {
7861 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
7863 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
7865 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7866 tcg_temp_free_i64(tmp64
);
7868 case 7: /* Unsigned sum of absolute differences. */
7869 gen_helper_usad8(tmp
, tmp
, tmp2
);
7872 tmp2
= load_reg(s
, rs
);
7873 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7878 store_reg(s
, rd
, tmp
);
7880 case 6: case 7: /* 64-bit multiply, Divide. */
7881 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7882 tmp
= load_reg(s
, rn
);
7883 tmp2
= load_reg(s
, rm
);
7884 if ((op
& 0x50) == 0x10) {
7886 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7889 gen_helper_udiv(tmp
, tmp
, tmp2
);
7891 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7893 store_reg(s
, rd
, tmp
);
7894 } else if ((op
& 0xe) == 0xc) {
7895 /* Dual multiply accumulate long. */
7897 gen_swap_half(tmp2
);
7898 gen_smul_dual(tmp
, tmp2
);
7900 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7902 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7906 tmp64
= tcg_temp_new_i64();
7907 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7909 gen_addq(s
, tmp64
, rs
, rd
);
7910 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7911 tcg_temp_free_i64(tmp64
);
7914 /* Unsigned 64-bit multiply */
7915 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7919 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7921 tmp64
= tcg_temp_new_i64();
7922 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7925 /* Signed 64-bit multiply */
7926 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7931 gen_addq_lo(s
, tmp64
, rs
);
7932 gen_addq_lo(s
, tmp64
, rd
);
7933 } else if (op
& 0x40) {
7934 /* 64-bit accumulate. */
7935 gen_addq(s
, tmp64
, rs
, rd
);
7937 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7938 tcg_temp_free_i64(tmp64
);
7943 case 6: case 7: case 14: case 15:
7945 if (((insn
>> 24) & 3) == 3) {
7946 /* Translate into the equivalent ARM encoding. */
7947 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7948 if (disas_neon_data_insn(env
, s
, insn
))
7951 if (insn
& (1 << 28))
7953 if (disas_coproc_insn (env
, s
, insn
))
7957 case 8: case 9: case 10: case 11:
7958 if (insn
& (1 << 15)) {
7959 /* Branches, misc control. */
7960 if (insn
& 0x5000) {
7961 /* Unconditional branch. */
7962 /* signextend(hw1[10:0]) -> offset[:12]. */
7963 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7964 /* hw1[10:0] -> offset[11:1]. */
7965 offset
|= (insn
& 0x7ff) << 1;
7966 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7967 offset[24:22] already have the same value because of the
7968 sign extension above. */
7969 offset
^= ((~insn
) & (1 << 13)) << 10;
7970 offset
^= ((~insn
) & (1 << 11)) << 11;
7972 if (insn
& (1 << 14)) {
7973 /* Branch and link. */
7974 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7978 if (insn
& (1 << 12)) {
7983 offset
&= ~(uint32_t)2;
7984 gen_bx_im(s
, offset
);
7986 } else if (((insn
>> 23) & 7) == 7) {
7988 if (insn
& (1 << 13))
7991 if (insn
& (1 << 26)) {
7992 /* Secure monitor call (v6Z) */
7993 goto illegal_op
; /* not implemented. */
7995 op
= (insn
>> 20) & 7;
7997 case 0: /* msr cpsr. */
7999 tmp
= load_reg(s
, rn
);
8000 addr
= tcg_const_i32(insn
& 0xff);
8001 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8002 tcg_temp_free_i32(addr
);
8008 case 1: /* msr spsr. */
8011 tmp
= load_reg(s
, rn
);
8013 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
8017 case 2: /* cps, nop-hint. */
8018 if (((insn
>> 8) & 7) == 0) {
8019 gen_nop_hint(s
, insn
& 0xff);
8021 /* Implemented as NOP in user mode. */
8026 if (insn
& (1 << 10)) {
8027 if (insn
& (1 << 7))
8029 if (insn
& (1 << 6))
8031 if (insn
& (1 << 5))
8033 if (insn
& (1 << 9))
8034 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8036 if (insn
& (1 << 8)) {
8038 imm
|= (insn
& 0x1f);
8041 gen_set_psr_im(s
, offset
, 0, imm
);
8044 case 3: /* Special control operations. */
8046 op
= (insn
>> 4) & 0xf;
8054 /* These execute as NOPs. */
8061 /* Trivial implementation equivalent to bx. */
8062 tmp
= load_reg(s
, rn
);
8065 case 5: /* Exception return. */
8069 if (rn
!= 14 || rd
!= 15) {
8072 tmp
= load_reg(s
, rn
);
8073 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8074 gen_exception_return(s
, tmp
);
8076 case 6: /* mrs cpsr. */
8079 addr
= tcg_const_i32(insn
& 0xff);
8080 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8081 tcg_temp_free_i32(addr
);
8083 gen_helper_cpsr_read(tmp
);
8085 store_reg(s
, rd
, tmp
);
8087 case 7: /* mrs spsr. */
8088 /* Not accessible in user mode. */
8089 if (IS_USER(s
) || IS_M(env
))
8091 tmp
= load_cpu_field(spsr
);
8092 store_reg(s
, rd
, tmp
);
8097 /* Conditional branch. */
8098 op
= (insn
>> 22) & 0xf;
8099 /* Generate a conditional jump to next instruction. */
8100 s
->condlabel
= gen_new_label();
8101 gen_test_cc(op
^ 1, s
->condlabel
);
8104 /* offset[11:1] = insn[10:0] */
8105 offset
= (insn
& 0x7ff) << 1;
8106 /* offset[17:12] = insn[21:16]. */
8107 offset
|= (insn
& 0x003f0000) >> 4;
8108 /* offset[31:20] = insn[26]. */
8109 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8110 /* offset[18] = insn[13]. */
8111 offset
|= (insn
& (1 << 13)) << 5;
8112 /* offset[19] = insn[11]. */
8113 offset
|= (insn
& (1 << 11)) << 8;
8115 /* jump to the offset */
8116 gen_jmp(s
, s
->pc
+ offset
);
8119 /* Data processing immediate. */
8120 if (insn
& (1 << 25)) {
8121 if (insn
& (1 << 24)) {
8122 if (insn
& (1 << 20))
8124 /* Bitfield/Saturate. */
8125 op
= (insn
>> 21) & 7;
8127 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8130 tcg_gen_movi_i32(tmp
, 0);
8132 tmp
= load_reg(s
, rn
);
8135 case 2: /* Signed bitfield extract. */
8137 if (shift
+ imm
> 32)
8140 gen_sbfx(tmp
, shift
, imm
);
8142 case 6: /* Unsigned bitfield extract. */
8144 if (shift
+ imm
> 32)
8147 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8149 case 3: /* Bitfield insert/clear. */
8152 imm
= imm
+ 1 - shift
;
8154 tmp2
= load_reg(s
, rd
);
8155 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
8161 default: /* Saturate. */
8164 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8166 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8168 tmp2
= tcg_const_i32(imm
);
8171 if ((op
& 1) && shift
== 0)
8172 gen_helper_usat16(tmp
, tmp
, tmp2
);
8174 gen_helper_usat(tmp
, tmp
, tmp2
);
8177 if ((op
& 1) && shift
== 0)
8178 gen_helper_ssat16(tmp
, tmp
, tmp2
);
8180 gen_helper_ssat(tmp
, tmp
, tmp2
);
8182 tcg_temp_free_i32(tmp2
);
8185 store_reg(s
, rd
, tmp
);
8187 imm
= ((insn
& 0x04000000) >> 15)
8188 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8189 if (insn
& (1 << 22)) {
8190 /* 16-bit immediate. */
8191 imm
|= (insn
>> 4) & 0xf000;
8192 if (insn
& (1 << 23)) {
8194 tmp
= load_reg(s
, rd
);
8195 tcg_gen_ext16u_i32(tmp
, tmp
);
8196 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8200 tcg_gen_movi_i32(tmp
, imm
);
8203 /* Add/sub 12-bit immediate. */
8205 offset
= s
->pc
& ~(uint32_t)3;
8206 if (insn
& (1 << 23))
8211 tcg_gen_movi_i32(tmp
, offset
);
8213 tmp
= load_reg(s
, rn
);
8214 if (insn
& (1 << 23))
8215 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8217 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8220 store_reg(s
, rd
, tmp
);
8223 int shifter_out
= 0;
8224 /* modified 12-bit immediate. */
8225 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8226 imm
= (insn
& 0xff);
8229 /* Nothing to do. */
8231 case 1: /* 00XY00XY */
8234 case 2: /* XY00XY00 */
8238 case 3: /* XYXYXYXY */
8242 default: /* Rotated constant. */
8243 shift
= (shift
<< 1) | (imm
>> 7);
8245 imm
= imm
<< (32 - shift
);
8250 tcg_gen_movi_i32(tmp2
, imm
);
8251 rn
= (insn
>> 16) & 0xf;
8254 tcg_gen_movi_i32(tmp
, 0);
8256 tmp
= load_reg(s
, rn
);
8258 op
= (insn
>> 21) & 0xf;
8259 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8260 shifter_out
, tmp
, tmp2
))
8263 rd
= (insn
>> 8) & 0xf;
8265 store_reg(s
, rd
, tmp
);
8272 case 12: /* Load/store single data item. */
8277 if ((insn
& 0x01100000) == 0x01000000) {
8278 if (disas_neon_ls_insn(env
, s
, insn
))
8286 /* s->pc has already been incremented by 4. */
8287 imm
= s
->pc
& 0xfffffffc;
8288 if (insn
& (1 << 23))
8289 imm
+= insn
& 0xfff;
8291 imm
-= insn
& 0xfff;
8292 tcg_gen_movi_i32(addr
, imm
);
8294 addr
= load_reg(s
, rn
);
8295 if (insn
& (1 << 23)) {
8296 /* Positive offset. */
8298 tcg_gen_addi_i32(addr
, addr
, imm
);
8300 op
= (insn
>> 8) & 7;
8303 case 0: case 8: /* Shifted Register. */
8304 shift
= (insn
>> 4) & 0xf;
8307 tmp
= load_reg(s
, rm
);
8309 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8310 tcg_gen_add_i32(addr
, addr
, tmp
);
8313 case 4: /* Negative offset. */
8314 tcg_gen_addi_i32(addr
, addr
, -imm
);
8316 case 6: /* User privilege. */
8317 tcg_gen_addi_i32(addr
, addr
, imm
);
8320 case 1: /* Post-decrement. */
8323 case 3: /* Post-increment. */
8327 case 5: /* Pre-decrement. */
8330 case 7: /* Pre-increment. */
8331 tcg_gen_addi_i32(addr
, addr
, imm
);
8339 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8340 if (insn
& (1 << 20)) {
8342 if (rs
== 15 && op
!= 2) {
8345 /* Memory hint. Implemented as NOP. */
8348 case 0: tmp
= gen_ld8u(addr
, user
); break;
8349 case 4: tmp
= gen_ld8s(addr
, user
); break;
8350 case 1: tmp
= gen_ld16u(addr
, user
); break;
8351 case 5: tmp
= gen_ld16s(addr
, user
); break;
8352 case 2: tmp
= gen_ld32(addr
, user
); break;
8353 default: goto illegal_op
;
8358 store_reg(s
, rs
, tmp
);
8365 tmp
= load_reg(s
, rs
);
8367 case 0: gen_st8(tmp
, addr
, user
); break;
8368 case 1: gen_st16(tmp
, addr
, user
); break;
8369 case 2: gen_st32(tmp
, addr
, user
); break;
8370 default: goto illegal_op
;
8374 tcg_gen_addi_i32(addr
, addr
, imm
);
8376 store_reg(s
, rn
, addr
);
8390 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8392 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8399 if (s
->condexec_mask
) {
8400 cond
= s
->condexec_cond
;
8401 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
8402 s
->condlabel
= gen_new_label();
8403 gen_test_cc(cond
^ 1, s
->condlabel
);
8408 insn
= lduw_code(s
->pc
);
8411 switch (insn
>> 12) {
8415 op
= (insn
>> 11) & 3;
8418 rn
= (insn
>> 3) & 7;
8419 tmp
= load_reg(s
, rn
);
8420 if (insn
& (1 << 10)) {
8423 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8426 rm
= (insn
>> 6) & 7;
8427 tmp2
= load_reg(s
, rm
);
8429 if (insn
& (1 << 9)) {
8430 if (s
->condexec_mask
)
8431 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8433 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8435 if (s
->condexec_mask
)
8436 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8438 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8441 store_reg(s
, rd
, tmp
);
8443 /* shift immediate */
8444 rm
= (insn
>> 3) & 7;
8445 shift
= (insn
>> 6) & 0x1f;
8446 tmp
= load_reg(s
, rm
);
8447 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8448 if (!s
->condexec_mask
)
8450 store_reg(s
, rd
, tmp
);
8454 /* arithmetic large immediate */
8455 op
= (insn
>> 11) & 3;
8456 rd
= (insn
>> 8) & 0x7;
8457 if (op
== 0) { /* mov */
8459 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8460 if (!s
->condexec_mask
)
8462 store_reg(s
, rd
, tmp
);
8464 tmp
= load_reg(s
, rd
);
8466 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8469 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8474 if (s
->condexec_mask
)
8475 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8477 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8479 store_reg(s
, rd
, tmp
);
8482 if (s
->condexec_mask
)
8483 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8485 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8487 store_reg(s
, rd
, tmp
);
8493 if (insn
& (1 << 11)) {
8494 rd
= (insn
>> 8) & 7;
8495 /* load pc-relative. Bit 1 of PC is ignored. */
8496 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8497 val
&= ~(uint32_t)2;
8499 tcg_gen_movi_i32(addr
, val
);
8500 tmp
= gen_ld32(addr
, IS_USER(s
));
8502 store_reg(s
, rd
, tmp
);
8505 if (insn
& (1 << 10)) {
8506 /* data processing extended or blx */
8507 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8508 rm
= (insn
>> 3) & 0xf;
8509 op
= (insn
>> 8) & 3;
8512 tmp
= load_reg(s
, rd
);
8513 tmp2
= load_reg(s
, rm
);
8514 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8516 store_reg(s
, rd
, tmp
);
8519 tmp
= load_reg(s
, rd
);
8520 tmp2
= load_reg(s
, rm
);
8521 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8525 case 2: /* mov/cpy */
8526 tmp
= load_reg(s
, rm
);
8527 store_reg(s
, rd
, tmp
);
8529 case 3:/* branch [and link] exchange thumb register */
8530 tmp
= load_reg(s
, rm
);
8531 if (insn
& (1 << 7)) {
8532 val
= (uint32_t)s
->pc
| 1;
8534 tcg_gen_movi_i32(tmp2
, val
);
8535 store_reg(s
, 14, tmp2
);
8543 /* data processing register */
8545 rm
= (insn
>> 3) & 7;
8546 op
= (insn
>> 6) & 0xf;
8547 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8548 /* the shift/rotate ops want the operands backwards */
8557 if (op
== 9) { /* neg */
8559 tcg_gen_movi_i32(tmp
, 0);
8560 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8561 tmp
= load_reg(s
, rd
);
8566 tmp2
= load_reg(s
, rm
);
8569 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8570 if (!s
->condexec_mask
)
8574 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8575 if (!s
->condexec_mask
)
8579 if (s
->condexec_mask
) {
8580 gen_helper_shl(tmp2
, tmp2
, tmp
);
8582 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8587 if (s
->condexec_mask
) {
8588 gen_helper_shr(tmp2
, tmp2
, tmp
);
8590 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8595 if (s
->condexec_mask
) {
8596 gen_helper_sar(tmp2
, tmp2
, tmp
);
8598 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8603 if (s
->condexec_mask
)
8606 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8609 if (s
->condexec_mask
)
8610 gen_sub_carry(tmp
, tmp
, tmp2
);
8612 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8615 if (s
->condexec_mask
) {
8616 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8617 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8619 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8624 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8629 if (s
->condexec_mask
)
8630 tcg_gen_neg_i32(tmp
, tmp2
);
8632 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8635 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8639 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8643 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8644 if (!s
->condexec_mask
)
8648 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8649 if (!s
->condexec_mask
)
8653 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8654 if (!s
->condexec_mask
)
8658 tcg_gen_not_i32(tmp2
, tmp2
);
8659 if (!s
->condexec_mask
)
8667 store_reg(s
, rm
, tmp2
);
8671 store_reg(s
, rd
, tmp
);
8681 /* load/store register offset. */
8683 rn
= (insn
>> 3) & 7;
8684 rm
= (insn
>> 6) & 7;
8685 op
= (insn
>> 9) & 7;
8686 addr
= load_reg(s
, rn
);
8687 tmp
= load_reg(s
, rm
);
8688 tcg_gen_add_i32(addr
, addr
, tmp
);
8691 if (op
< 3) /* store */
8692 tmp
= load_reg(s
, rd
);
8696 gen_st32(tmp
, addr
, IS_USER(s
));
8699 gen_st16(tmp
, addr
, IS_USER(s
));
8702 gen_st8(tmp
, addr
, IS_USER(s
));
8705 tmp
= gen_ld8s(addr
, IS_USER(s
));
8708 tmp
= gen_ld32(addr
, IS_USER(s
));
8711 tmp
= gen_ld16u(addr
, IS_USER(s
));
8714 tmp
= gen_ld8u(addr
, IS_USER(s
));
8717 tmp
= gen_ld16s(addr
, IS_USER(s
));
8720 if (op
>= 3) /* load */
8721 store_reg(s
, rd
, tmp
);
8726 /* load/store word immediate offset */
8728 rn
= (insn
>> 3) & 7;
8729 addr
= load_reg(s
, rn
);
8730 val
= (insn
>> 4) & 0x7c;
8731 tcg_gen_addi_i32(addr
, addr
, val
);
8733 if (insn
& (1 << 11)) {
8735 tmp
= gen_ld32(addr
, IS_USER(s
));
8736 store_reg(s
, rd
, tmp
);
8739 tmp
= load_reg(s
, rd
);
8740 gen_st32(tmp
, addr
, IS_USER(s
));
8746 /* load/store byte immediate offset */
8748 rn
= (insn
>> 3) & 7;
8749 addr
= load_reg(s
, rn
);
8750 val
= (insn
>> 6) & 0x1f;
8751 tcg_gen_addi_i32(addr
, addr
, val
);
8753 if (insn
& (1 << 11)) {
8755 tmp
= gen_ld8u(addr
, IS_USER(s
));
8756 store_reg(s
, rd
, tmp
);
8759 tmp
= load_reg(s
, rd
);
8760 gen_st8(tmp
, addr
, IS_USER(s
));
8766 /* load/store halfword immediate offset */
8768 rn
= (insn
>> 3) & 7;
8769 addr
= load_reg(s
, rn
);
8770 val
= (insn
>> 5) & 0x3e;
8771 tcg_gen_addi_i32(addr
, addr
, val
);
8773 if (insn
& (1 << 11)) {
8775 tmp
= gen_ld16u(addr
, IS_USER(s
));
8776 store_reg(s
, rd
, tmp
);
8779 tmp
= load_reg(s
, rd
);
8780 gen_st16(tmp
, addr
, IS_USER(s
));
8786 /* load/store from stack */
8787 rd
= (insn
>> 8) & 7;
8788 addr
= load_reg(s
, 13);
8789 val
= (insn
& 0xff) * 4;
8790 tcg_gen_addi_i32(addr
, addr
, val
);
8792 if (insn
& (1 << 11)) {
8794 tmp
= gen_ld32(addr
, IS_USER(s
));
8795 store_reg(s
, rd
, tmp
);
8798 tmp
= load_reg(s
, rd
);
8799 gen_st32(tmp
, addr
, IS_USER(s
));
8805 /* add to high reg */
8806 rd
= (insn
>> 8) & 7;
8807 if (insn
& (1 << 11)) {
8809 tmp
= load_reg(s
, 13);
8811 /* PC. bit 1 is ignored. */
8813 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8815 val
= (insn
& 0xff) * 4;
8816 tcg_gen_addi_i32(tmp
, tmp
, val
);
8817 store_reg(s
, rd
, tmp
);
8822 op
= (insn
>> 8) & 0xf;
8825 /* adjust stack pointer */
8826 tmp
= load_reg(s
, 13);
8827 val
= (insn
& 0x7f) * 4;
8828 if (insn
& (1 << 7))
8829 val
= -(int32_t)val
;
8830 tcg_gen_addi_i32(tmp
, tmp
, val
);
8831 store_reg(s
, 13, tmp
);
8834 case 2: /* sign/zero extend. */
8837 rm
= (insn
>> 3) & 7;
8838 tmp
= load_reg(s
, rm
);
8839 switch ((insn
>> 6) & 3) {
8840 case 0: gen_sxth(tmp
); break;
8841 case 1: gen_sxtb(tmp
); break;
8842 case 2: gen_uxth(tmp
); break;
8843 case 3: gen_uxtb(tmp
); break;
8845 store_reg(s
, rd
, tmp
);
8847 case 4: case 5: case 0xc: case 0xd:
8849 addr
= load_reg(s
, 13);
8850 if (insn
& (1 << 8))
8854 for (i
= 0; i
< 8; i
++) {
8855 if (insn
& (1 << i
))
8858 if ((insn
& (1 << 11)) == 0) {
8859 tcg_gen_addi_i32(addr
, addr
, -offset
);
8861 for (i
= 0; i
< 8; i
++) {
8862 if (insn
& (1 << i
)) {
8863 if (insn
& (1 << 11)) {
8865 tmp
= gen_ld32(addr
, IS_USER(s
));
8866 store_reg(s
, i
, tmp
);
8869 tmp
= load_reg(s
, i
);
8870 gen_st32(tmp
, addr
, IS_USER(s
));
8872 /* advance to the next address. */
8873 tcg_gen_addi_i32(addr
, addr
, 4);
8877 if (insn
& (1 << 8)) {
8878 if (insn
& (1 << 11)) {
8880 tmp
= gen_ld32(addr
, IS_USER(s
));
8881 /* don't set the pc until the rest of the instruction
8885 tmp
= load_reg(s
, 14);
8886 gen_st32(tmp
, addr
, IS_USER(s
));
8888 tcg_gen_addi_i32(addr
, addr
, 4);
8890 if ((insn
& (1 << 11)) == 0) {
8891 tcg_gen_addi_i32(addr
, addr
, -offset
);
8893 /* write back the new stack pointer */
8894 store_reg(s
, 13, addr
);
8895 /* set the new PC value */
8896 if ((insn
& 0x0900) == 0x0900)
8900 case 1: case 3: case 9: case 11: /* czb */
8902 tmp
= load_reg(s
, rm
);
8903 s
->condlabel
= gen_new_label();
8905 if (insn
& (1 << 11))
8906 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8908 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8910 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8911 val
= (uint32_t)s
->pc
+ 2;
8916 case 15: /* IT, nop-hint. */
8917 if ((insn
& 0xf) == 0) {
8918 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8922 s
->condexec_cond
= (insn
>> 4) & 0xe;
8923 s
->condexec_mask
= insn
& 0x1f;
8924 /* No actual code generated for this insn, just setup state. */
8927 case 0xe: /* bkpt */
8928 gen_set_condexec(s
);
8929 gen_set_pc_im(s
->pc
- 2);
8930 gen_exception(EXCP_BKPT
);
8931 s
->is_jmp
= DISAS_JUMP
;
8936 rn
= (insn
>> 3) & 0x7;
8938 tmp
= load_reg(s
, rn
);
8939 switch ((insn
>> 6) & 3) {
8940 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8941 case 1: gen_rev16(tmp
); break;
8942 case 3: gen_revsh(tmp
); break;
8943 default: goto illegal_op
;
8945 store_reg(s
, rd
, tmp
);
8953 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8956 addr
= tcg_const_i32(16);
8957 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8958 tcg_temp_free_i32(addr
);
8962 addr
= tcg_const_i32(17);
8963 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8964 tcg_temp_free_i32(addr
);
8966 tcg_temp_free_i32(tmp
);
8969 if (insn
& (1 << 4))
8970 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8973 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
8983 /* load/store multiple */
8984 rn
= (insn
>> 8) & 0x7;
8985 addr
= load_reg(s
, rn
);
8986 for (i
= 0; i
< 8; i
++) {
8987 if (insn
& (1 << i
)) {
8988 if (insn
& (1 << 11)) {
8990 tmp
= gen_ld32(addr
, IS_USER(s
));
8991 store_reg(s
, i
, tmp
);
8994 tmp
= load_reg(s
, i
);
8995 gen_st32(tmp
, addr
, IS_USER(s
));
8997 /* advance to the next address */
8998 tcg_gen_addi_i32(addr
, addr
, 4);
9001 /* Base register writeback. */
9002 if ((insn
& (1 << rn
)) == 0) {
9003 store_reg(s
, rn
, addr
);
9010 /* conditional branch or swi */
9011 cond
= (insn
>> 8) & 0xf;
9017 gen_set_condexec(s
);
9018 gen_set_pc_im(s
->pc
);
9019 s
->is_jmp
= DISAS_SWI
;
9022 /* generate a conditional jump to next instruction */
9023 s
->condlabel
= gen_new_label();
9024 gen_test_cc(cond
^ 1, s
->condlabel
);
9027 /* jump to the offset */
9028 val
= (uint32_t)s
->pc
+ 2;
9029 offset
= ((int32_t)insn
<< 24) >> 24;
9035 if (insn
& (1 << 11)) {
9036 if (disas_thumb2_insn(env
, s
, insn
))
9040 /* unconditional branch */
9041 val
= (uint32_t)s
->pc
;
9042 offset
= ((int32_t)insn
<< 21) >> 21;
9043 val
+= (offset
<< 1) + 2;
9048 if (disas_thumb2_insn(env
, s
, insn
))
9054 gen_set_condexec(s
);
9055 gen_set_pc_im(s
->pc
- 4);
9056 gen_exception(EXCP_UDEF
);
9057 s
->is_jmp
= DISAS_JUMP
;
9061 gen_set_condexec(s
);
9062 gen_set_pc_im(s
->pc
- 2);
9063 gen_exception(EXCP_UDEF
);
9064 s
->is_jmp
= DISAS_JUMP
;
9067 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9068 basic block 'tb'. If search_pc is TRUE, also generate PC
9069 information for each intermediate instruction. */
9070 static inline void gen_intermediate_code_internal(CPUState
*env
,
9071 TranslationBlock
*tb
,
9074 DisasContext dc1
, *dc
= &dc1
;
9076 uint16_t *gen_opc_end
;
9078 target_ulong pc_start
;
9079 uint32_t next_page_start
;
9083 /* generate intermediate code */
9090 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
9092 dc
->is_jmp
= DISAS_NEXT
;
9094 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9096 dc
->thumb
= env
->thumb
;
9097 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
9098 dc
->condexec_cond
= env
->condexec_bits
>> 4;
9099 #if !defined(CONFIG_USER_ONLY)
9101 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
9103 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
9106 dc
->vfp_enabled
= ARM_TBFLAG_VFPEN(tb
->flags
);
9107 cpu_F0s
= tcg_temp_new_i32();
9108 cpu_F1s
= tcg_temp_new_i32();
9109 cpu_F0d
= tcg_temp_new_i64();
9110 cpu_F1d
= tcg_temp_new_i64();
9113 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9114 cpu_M0
= tcg_temp_new_i64();
9115 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9118 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9120 max_insns
= CF_COUNT_MASK
;
9123 /* Reset the conditional execution bits immediately. This avoids
9124 complications trying to do it at the end of the block. */
9125 if (env
->condexec_bits
)
9127 TCGv tmp
= new_tmp();
9128 tcg_gen_movi_i32(tmp
, 0);
9129 store_cpu_field(tmp
, condexec_bits
);
9132 #ifdef CONFIG_USER_ONLY
9133 /* Intercept jump to the magic kernel page. */
9134 if (dc
->pc
>= 0xffff0000) {
9135 /* We always get here via a jump, so know we are not in a
9136 conditional execution block. */
9137 gen_exception(EXCP_KERNEL_TRAP
);
9138 dc
->is_jmp
= DISAS_UPDATE
;
9142 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9143 /* We always get here via a jump, so know we are not in a
9144 conditional execution block. */
9145 gen_exception(EXCP_EXCEPTION_EXIT
);
9146 dc
->is_jmp
= DISAS_UPDATE
;
9151 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9152 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9153 if (bp
->pc
== dc
->pc
) {
9154 gen_set_condexec(dc
);
9155 gen_set_pc_im(dc
->pc
);
9156 gen_exception(EXCP_DEBUG
);
9157 dc
->is_jmp
= DISAS_JUMP
;
9158 /* Advance PC so that clearing the breakpoint will
9159 invalidate this TB. */
9161 goto done_generating
;
9167 j
= gen_opc_ptr
- gen_opc_buf
;
9171 gen_opc_instr_start
[lj
++] = 0;
9173 gen_opc_pc
[lj
] = dc
->pc
;
9174 gen_opc_instr_start
[lj
] = 1;
9175 gen_opc_icount
[lj
] = num_insns
;
9178 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9182 disas_thumb_insn(env
, dc
);
9183 if (dc
->condexec_mask
) {
9184 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9185 | ((dc
->condexec_mask
>> 4) & 1);
9186 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9187 if (dc
->condexec_mask
== 0) {
9188 dc
->condexec_cond
= 0;
9192 disas_arm_insn(env
, dc
);
9195 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
9199 if (dc
->condjmp
&& !dc
->is_jmp
) {
9200 gen_set_label(dc
->condlabel
);
9203 /* Translation stops when a conditional branch is encountered.
9204 * Otherwise the subsequent code could get translated several times.
9205 * Also stop translation when a page boundary is reached. This
9206 * ensures prefetch aborts occur at the right place. */
9208 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9209 !env
->singlestep_enabled
&&
9211 dc
->pc
< next_page_start
&&
9212 num_insns
< max_insns
);
9214 if (tb
->cflags
& CF_LAST_IO
) {
9216 /* FIXME: This can theoretically happen with self-modifying
9218 cpu_abort(env
, "IO on conditional branch instruction");
9223 /* At this stage dc->condjmp will only be set when the skipped
9224 instruction was a conditional branch or trap, and the PC has
9225 already been written. */
9226 if (unlikely(env
->singlestep_enabled
)) {
9227 /* Make sure the pc is updated, and raise a debug exception. */
9229 gen_set_condexec(dc
);
9230 if (dc
->is_jmp
== DISAS_SWI
) {
9231 gen_exception(EXCP_SWI
);
9233 gen_exception(EXCP_DEBUG
);
9235 gen_set_label(dc
->condlabel
);
9237 if (dc
->condjmp
|| !dc
->is_jmp
) {
9238 gen_set_pc_im(dc
->pc
);
9241 gen_set_condexec(dc
);
9242 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9243 gen_exception(EXCP_SWI
);
9245 /* FIXME: Single stepping a WFI insn will not halt
9247 gen_exception(EXCP_DEBUG
);
9250 /* While branches must always occur at the end of an IT block,
9251 there are a few other things that can cause us to terminate
9252 the TB in the middel of an IT block:
9253 - Exception generating instructions (bkpt, swi, undefined).
9255 - Hardware watchpoints.
9256 Hardware breakpoints have already been handled and skip this code.
9258 gen_set_condexec(dc
);
9259 switch(dc
->is_jmp
) {
9261 gen_goto_tb(dc
, 1, dc
->pc
);
9266 /* indicate that the hash table must be used to find the next TB */
9270 /* nothing more to generate */
9276 gen_exception(EXCP_SWI
);
9280 gen_set_label(dc
->condlabel
);
9281 gen_set_condexec(dc
);
9282 gen_goto_tb(dc
, 1, dc
->pc
);
9288 gen_icount_end(tb
, num_insns
);
9289 *gen_opc_ptr
= INDEX_op_end
;
9292 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9293 qemu_log("----------------\n");
9294 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9295 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9300 j
= gen_opc_ptr
- gen_opc_buf
;
9303 gen_opc_instr_start
[lj
++] = 0;
9305 tb
->size
= dc
->pc
- pc_start
;
9306 tb
->icount
= num_insns
;
9310 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9312 gen_intermediate_code_internal(env
, tb
, 0);
9315 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9317 gen_intermediate_code_internal(env
, tb
, 1);
9320 static const char *cpu_mode_names
[16] = {
9321 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9322 "???", "???", "???", "und", "???", "???", "???", "sys"
9325 void cpu_dump_state(CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
9335 /* ??? This assumes float64 and double have the same layout.
9336 Oh well, it's only debug dumps. */
9345 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9347 cpu_fprintf(f
, "\n");
9349 cpu_fprintf(f
, " ");
9351 psr
= cpsr_read(env
);
9352 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9354 psr
& (1 << 31) ? 'N' : '-',
9355 psr
& (1 << 30) ? 'Z' : '-',
9356 psr
& (1 << 29) ? 'C' : '-',
9357 psr
& (1 << 28) ? 'V' : '-',
9358 psr
& CPSR_T
? 'T' : 'A',
9359 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9362 for (i
= 0; i
< 16; i
++) {
9363 d
.d
= env
->vfp
.regs
[i
];
9367 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9368 i
* 2, (int)s0
.i
, s0
.s
,
9369 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9370 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9373 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9377 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9378 unsigned long searched_pc
, int pc_pos
, void *puc
)
9380 env
->regs
[15] = gen_opc_pc
[pc_pos
];