]>
git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s
, cpu_F1s
;
82 static TCGv_i64 cpu_F0d
, cpu_F1d
;
84 #include "gen-icount.h"
86 static const char *regnames
[] =
87 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
88 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
90 /* initialize TCG globals. */
91 void arm_translate_init(void)
95 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
97 for (i
= 0; i
< 16; i
++) {
98 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
99 offsetof(CPUState
, regs
[i
]),
107 static int num_temps
;
109 /* Allocate a temporary variable. */
110 static TCGv_i32
new_tmp(void)
113 return tcg_temp_new_i32();
116 /* Release a temporary variable. */
117 static void dead_tmp(TCGv tmp
)
123 static inline TCGv
load_cpu_offset(int offset
)
125 TCGv tmp
= new_tmp();
126 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
130 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
132 static inline void store_cpu_offset(TCGv var
, int offset
)
134 tcg_gen_st_i32(var
, cpu_env
, offset
);
138 #define store_cpu_field(var, name) \
139 store_cpu_offset(var, offsetof(CPUState, name))
141 /* Set a variable to the value of a CPU register. */
142 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
146 /* normaly, since we updated PC, we need only to add one insn */
148 addr
= (long)s
->pc
+ 2;
150 addr
= (long)s
->pc
+ 4;
151 tcg_gen_movi_i32(var
, addr
);
153 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
157 /* Create a new temporary and set it to the value of a CPU register. */
158 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
160 TCGv tmp
= new_tmp();
161 load_reg_var(s
, tmp
, reg
);
165 /* Set a CPU register. The source must be a temporary and will be
167 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
170 tcg_gen_andi_i32(var
, var
, ~1);
171 s
->is_jmp
= DISAS_JUMP
;
173 tcg_gen_mov_i32(cpu_R
[reg
], var
);
177 /* Value extensions. */
178 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
179 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
180 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
181 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
183 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
184 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
187 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
189 TCGv tmp_mask
= tcg_const_i32(mask
);
190 gen_helper_cpsr_write(var
, tmp_mask
);
191 tcg_temp_free_i32(tmp_mask
);
193 /* Set NZCV flags from the high 4 bits of var. */
194 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
196 static void gen_exception(int excp
)
198 TCGv tmp
= new_tmp();
199 tcg_gen_movi_i32(tmp
, excp
);
200 gen_helper_exception(tmp
);
204 static void gen_smul_dual(TCGv a
, TCGv b
)
206 TCGv tmp1
= new_tmp();
207 TCGv tmp2
= new_tmp();
208 tcg_gen_ext16s_i32(tmp1
, a
);
209 tcg_gen_ext16s_i32(tmp2
, b
);
210 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
212 tcg_gen_sari_i32(a
, a
, 16);
213 tcg_gen_sari_i32(b
, b
, 16);
214 tcg_gen_mul_i32(b
, b
, a
);
215 tcg_gen_mov_i32(a
, tmp1
);
219 /* Byteswap each halfword. */
220 static void gen_rev16(TCGv var
)
222 TCGv tmp
= new_tmp();
223 tcg_gen_shri_i32(tmp
, var
, 8);
224 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
225 tcg_gen_shli_i32(var
, var
, 8);
226 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
227 tcg_gen_or_i32(var
, var
, tmp
);
231 /* Byteswap low halfword and sign extend. */
232 static void gen_revsh(TCGv var
)
234 TCGv tmp
= new_tmp();
235 tcg_gen_shri_i32(tmp
, var
, 8);
236 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
237 tcg_gen_shli_i32(var
, var
, 8);
238 tcg_gen_ext8s_i32(var
, var
);
239 tcg_gen_or_i32(var
, var
, tmp
);
243 /* Unsigned bitfield extract. */
244 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
247 tcg_gen_shri_i32(var
, var
, shift
);
248 tcg_gen_andi_i32(var
, var
, mask
);
251 /* Signed bitfield extract. */
252 static void gen_sbfx(TCGv var
, int shift
, int width
)
257 tcg_gen_sari_i32(var
, var
, shift
);
258 if (shift
+ width
< 32) {
259 signbit
= 1u << (width
- 1);
260 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
261 tcg_gen_xori_i32(var
, var
, signbit
);
262 tcg_gen_subi_i32(var
, var
, signbit
);
266 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
267 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
269 tcg_gen_andi_i32(val
, val
, mask
);
270 tcg_gen_shli_i32(val
, val
, shift
);
271 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
272 tcg_gen_or_i32(dest
, base
, val
);
275 /* Round the top 32 bits of a 64-bit value. */
276 static void gen_roundqd(TCGv a
, TCGv b
)
278 tcg_gen_shri_i32(a
, a
, 31);
279 tcg_gen_add_i32(a
, a
, b
);
282 /* FIXME: Most targets have native widening multiplication.
283 It would be good to use that instead of a full wide multiply. */
284 /* 32x32->64 multiply. Marks inputs as dead. */
285 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
287 TCGv_i64 tmp1
= tcg_temp_new_i64();
288 TCGv_i64 tmp2
= tcg_temp_new_i64();
290 tcg_gen_extu_i32_i64(tmp1
, a
);
292 tcg_gen_extu_i32_i64(tmp2
, b
);
294 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
295 tcg_temp_free_i64(tmp2
);
299 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
301 TCGv_i64 tmp1
= tcg_temp_new_i64();
302 TCGv_i64 tmp2
= tcg_temp_new_i64();
304 tcg_gen_ext_i32_i64(tmp1
, a
);
306 tcg_gen_ext_i32_i64(tmp2
, b
);
308 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
309 tcg_temp_free_i64(tmp2
);
313 /* Signed 32x32->64 multiply. */
314 static void gen_imull(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1
, a
);
320 tcg_gen_ext_i32_i64(tmp2
, b
);
321 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
322 tcg_temp_free_i64(tmp2
);
323 tcg_gen_trunc_i64_i32(a
, tmp1
);
324 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
325 tcg_gen_trunc_i64_i32(b
, tmp1
);
326 tcg_temp_free_i64(tmp1
);
329 /* Swap low and high halfwords. */
330 static void gen_swap_half(TCGv var
)
332 TCGv tmp
= new_tmp();
333 tcg_gen_shri_i32(tmp
, var
, 16);
334 tcg_gen_shli_i32(var
, var
, 16);
335 tcg_gen_or_i32(var
, var
, tmp
);
339 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
340 tmp = (t0 ^ t1) & 0x8000;
343 t0 = (t0 + t1) ^ tmp;
346 static void gen_add16(TCGv t0
, TCGv t1
)
348 TCGv tmp
= new_tmp();
349 tcg_gen_xor_i32(tmp
, t0
, t1
);
350 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
351 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
352 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
353 tcg_gen_add_i32(t0
, t0
, t1
);
354 tcg_gen_xor_i32(t0
, t0
, tmp
);
359 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
361 /* Set CF to the top bit of var. */
362 static void gen_set_CF_bit31(TCGv var
)
364 TCGv tmp
= new_tmp();
365 tcg_gen_shri_i32(tmp
, var
, 31);
370 /* Set N and Z flags from var. */
371 static inline void gen_logic_CC(TCGv var
)
373 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
374 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
378 static void gen_adc(TCGv t0
, TCGv t1
)
381 tcg_gen_add_i32(t0
, t0
, t1
);
382 tmp
= load_cpu_field(CF
);
383 tcg_gen_add_i32(t0
, t0
, tmp
);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
391 tcg_gen_add_i32(dest
, t0
, t1
);
392 tmp
= load_cpu_field(CF
);
393 tcg_gen_add_i32(dest
, dest
, tmp
);
397 /* dest = T0 - T1 + CF - 1. */
398 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
401 tcg_gen_sub_i32(dest
, t0
, t1
);
402 tmp
= load_cpu_field(CF
);
403 tcg_gen_add_i32(dest
, dest
, tmp
);
404 tcg_gen_subi_i32(dest
, dest
, 1);
408 /* FIXME: Implement this natively. */
409 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
411 static void shifter_out_im(TCGv var
, int shift
)
413 TCGv tmp
= new_tmp();
415 tcg_gen_andi_i32(tmp
, var
, 1);
417 tcg_gen_shri_i32(tmp
, var
, shift
);
419 tcg_gen_andi_i32(tmp
, tmp
, 1);
425 /* Shift by immediate. Includes special handling for shift == 0. */
426 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
432 shifter_out_im(var
, 32 - shift
);
433 tcg_gen_shli_i32(var
, var
, shift
);
439 tcg_gen_shri_i32(var
, var
, 31);
442 tcg_gen_movi_i32(var
, 0);
445 shifter_out_im(var
, shift
- 1);
446 tcg_gen_shri_i32(var
, var
, shift
);
453 shifter_out_im(var
, shift
- 1);
456 tcg_gen_sari_i32(var
, var
, shift
);
458 case 3: /* ROR/RRX */
461 shifter_out_im(var
, shift
- 1);
462 tcg_gen_rotri_i32(var
, var
, shift
); break;
464 TCGv tmp
= load_cpu_field(CF
);
466 shifter_out_im(var
, 0);
467 tcg_gen_shri_i32(var
, var
, 1);
468 tcg_gen_shli_i32(tmp
, tmp
, 31);
469 tcg_gen_or_i32(var
, var
, tmp
);
475 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
476 TCGv shift
, int flags
)
480 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
481 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
482 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
483 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
487 case 0: gen_helper_shl(var
, var
, shift
); break;
488 case 1: gen_helper_shr(var
, var
, shift
); break;
489 case 2: gen_helper_sar(var
, var
, shift
); break;
490 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
491 tcg_gen_rotr_i32(var
, var
, shift
); break;
497 #define PAS_OP(pfx) \
499 case 0: gen_pas_helper(glue(pfx,add16)); break; \
500 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
501 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
502 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
503 case 4: gen_pas_helper(glue(pfx,add8)); break; \
504 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
506 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
511 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
513 tmp
= tcg_temp_new_ptr();
514 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
516 tcg_temp_free_ptr(tmp
);
519 tmp
= tcg_temp_new_ptr();
520 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
522 tcg_temp_free_ptr(tmp
);
524 #undef gen_pas_helper
525 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
538 #undef gen_pas_helper
543 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
544 #define PAS_OP(pfx) \
546 case 0: gen_pas_helper(glue(pfx,add8)); break; \
547 case 1: gen_pas_helper(glue(pfx,add16)); break; \
548 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
549 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
550 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
551 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
553 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
558 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
560 tmp
= tcg_temp_new_ptr();
561 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
563 tcg_temp_free_ptr(tmp
);
566 tmp
= tcg_temp_new_ptr();
567 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
569 tcg_temp_free_ptr(tmp
);
571 #undef gen_pas_helper
572 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
585 #undef gen_pas_helper
590 static void gen_test_cc(int cc
, int label
)
598 tmp
= load_cpu_field(ZF
);
599 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
602 tmp
= load_cpu_field(ZF
);
603 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
606 tmp
= load_cpu_field(CF
);
607 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
610 tmp
= load_cpu_field(CF
);
611 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
614 tmp
= load_cpu_field(NF
);
615 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
618 tmp
= load_cpu_field(NF
);
619 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
622 tmp
= load_cpu_field(VF
);
623 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
626 tmp
= load_cpu_field(VF
);
627 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
629 case 8: /* hi: C && !Z */
630 inv
= gen_new_label();
631 tmp
= load_cpu_field(CF
);
632 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
634 tmp
= load_cpu_field(ZF
);
635 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
638 case 9: /* ls: !C || Z */
639 tmp
= load_cpu_field(CF
);
640 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
642 tmp
= load_cpu_field(ZF
);
643 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
645 case 10: /* ge: N == V -> N ^ V == 0 */
646 tmp
= load_cpu_field(VF
);
647 tmp2
= load_cpu_field(NF
);
648 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
650 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
652 case 11: /* lt: N != V -> N ^ V != 0 */
653 tmp
= load_cpu_field(VF
);
654 tmp2
= load_cpu_field(NF
);
655 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
657 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
659 case 12: /* gt: !Z && N == V */
660 inv
= gen_new_label();
661 tmp
= load_cpu_field(ZF
);
662 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
664 tmp
= load_cpu_field(VF
);
665 tmp2
= load_cpu_field(NF
);
666 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
668 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
671 case 13: /* le: Z || N != V */
672 tmp
= load_cpu_field(ZF
);
673 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
675 tmp
= load_cpu_field(VF
);
676 tmp2
= load_cpu_field(NF
);
677 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
679 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
682 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
688 static const uint8_t table_logic_cc
[16] = {
707 /* Set PC and Thumb state from an immediate address. */
708 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
712 s
->is_jmp
= DISAS_UPDATE
;
713 if (s
->thumb
!= (addr
& 1)) {
715 tcg_gen_movi_i32(tmp
, addr
& 1);
716 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
719 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
722 /* Set PC and Thumb state from var. var is marked as dead. */
723 static inline void gen_bx(DisasContext
*s
, TCGv var
)
725 s
->is_jmp
= DISAS_UPDATE
;
726 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
727 tcg_gen_andi_i32(var
, var
, 1);
728 store_cpu_field(var
, thumb
);
731 /* Variant of store_reg which uses branch&exchange logic when storing
732 to r15 in ARM architecture v7 and above. The source must be a temporary
733 and will be marked as dead. */
734 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
737 if (reg
== 15 && ENABLE_ARCH_7
) {
740 store_reg(s
, reg
, var
);
744 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
746 TCGv tmp
= new_tmp();
747 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
750 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
752 TCGv tmp
= new_tmp();
753 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
756 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
758 TCGv tmp
= new_tmp();
759 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
762 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
764 TCGv tmp
= new_tmp();
765 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
768 static inline TCGv
gen_ld32(TCGv addr
, int index
)
770 TCGv tmp
= new_tmp();
771 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
774 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
776 TCGv_i64 tmp
= tcg_temp_new_i64();
777 tcg_gen_qemu_ld64(tmp
, addr
, index
);
780 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
782 tcg_gen_qemu_st8(val
, addr
, index
);
785 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
787 tcg_gen_qemu_st16(val
, addr
, index
);
790 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
792 tcg_gen_qemu_st32(val
, addr
, index
);
795 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
797 tcg_gen_qemu_st64(val
, addr
, index
);
798 tcg_temp_free_i64(val
);
801 static inline void gen_set_pc_im(uint32_t val
)
803 tcg_gen_movi_i32(cpu_R
[15], val
);
806 /* Force a TB lookup after an instruction that changes the CPU state. */
807 static inline void gen_lookup_tb(DisasContext
*s
)
809 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
810 s
->is_jmp
= DISAS_UPDATE
;
813 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
816 int val
, rm
, shift
, shiftop
;
819 if (!(insn
& (1 << 25))) {
822 if (!(insn
& (1 << 23)))
825 tcg_gen_addi_i32(var
, var
, val
);
829 shift
= (insn
>> 7) & 0x1f;
830 shiftop
= (insn
>> 5) & 3;
831 offset
= load_reg(s
, rm
);
832 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
833 if (!(insn
& (1 << 23)))
834 tcg_gen_sub_i32(var
, var
, offset
);
836 tcg_gen_add_i32(var
, var
, offset
);
841 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
847 if (insn
& (1 << 22)) {
849 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
850 if (!(insn
& (1 << 23)))
854 tcg_gen_addi_i32(var
, var
, val
);
858 tcg_gen_addi_i32(var
, var
, extra
);
860 offset
= load_reg(s
, rm
);
861 if (!(insn
& (1 << 23)))
862 tcg_gen_sub_i32(var
, var
, offset
);
864 tcg_gen_add_i32(var
, var
, offset
);
869 #define VFP_OP2(name) \
870 static inline void gen_vfp_##name(int dp) \
873 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
875 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
885 static inline void gen_vfp_abs(int dp
)
888 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
890 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
893 static inline void gen_vfp_neg(int dp
)
896 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
898 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
901 static inline void gen_vfp_sqrt(int dp
)
904 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
906 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
909 static inline void gen_vfp_cmp(int dp
)
912 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
914 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
917 static inline void gen_vfp_cmpe(int dp
)
920 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
922 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
925 static inline void gen_vfp_F1_ld0(int dp
)
928 tcg_gen_movi_i64(cpu_F1d
, 0);
930 tcg_gen_movi_i32(cpu_F1s
, 0);
933 static inline void gen_vfp_uito(int dp
)
936 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
938 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
941 static inline void gen_vfp_sito(int dp
)
944 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
946 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
949 static inline void gen_vfp_toui(int dp
)
952 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
954 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
957 static inline void gen_vfp_touiz(int dp
)
960 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
962 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
965 static inline void gen_vfp_tosi(int dp
)
968 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
970 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
973 static inline void gen_vfp_tosiz(int dp
)
976 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
978 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
981 #define VFP_GEN_FIX(name) \
982 static inline void gen_vfp_##name(int dp, int shift) \
984 TCGv tmp_shift = tcg_const_i32(shift); \
986 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
988 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
989 tcg_temp_free_i32(tmp_shift); \
1001 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1004 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1006 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1009 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1012 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1014 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1018 vfp_reg_offset (int dp
, int reg
)
1021 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1023 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1024 + offsetof(CPU_DoubleU
, l
.upper
);
1026 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1027 + offsetof(CPU_DoubleU
, l
.lower
);
1031 /* Return the offset of a 32-bit piece of a NEON register.
1032 zero is the least significant end of the register. */
1034 neon_reg_offset (int reg
, int n
)
1038 return vfp_reg_offset(0, sreg
);
1041 static TCGv
neon_load_reg(int reg
, int pass
)
1043 TCGv tmp
= new_tmp();
1044 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1048 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1050 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1054 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1056 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1059 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1061 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1064 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1065 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1066 #define tcg_gen_st_f32 tcg_gen_st_i32
1067 #define tcg_gen_st_f64 tcg_gen_st_i64
1069 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1072 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1074 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1077 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1080 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1082 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1085 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1088 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1090 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1093 #define ARM_CP_RW_BIT (1 << 20)
1095 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1097 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1100 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1102 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1105 static inline TCGv
iwmmxt_load_creg(int reg
)
1107 TCGv var
= new_tmp();
1108 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1112 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1114 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1117 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1119 iwmmxt_store_reg(cpu_M0
, rn
);
1122 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1124 iwmmxt_load_reg(cpu_M0
, rn
);
1127 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1129 iwmmxt_load_reg(cpu_V1
, rn
);
1130 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1133 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1135 iwmmxt_load_reg(cpu_V1
, rn
);
1136 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1139 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1141 iwmmxt_load_reg(cpu_V1
, rn
);
1142 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1145 #define IWMMXT_OP(name) \
1146 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1148 iwmmxt_load_reg(cpu_V1, rn); \
1149 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1152 #define IWMMXT_OP_ENV(name) \
1153 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1155 iwmmxt_load_reg(cpu_V1, rn); \
1156 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1159 #define IWMMXT_OP_ENV_SIZE(name) \
1160 IWMMXT_OP_ENV(name##b) \
1161 IWMMXT_OP_ENV(name##w) \
1162 IWMMXT_OP_ENV(name##l)
1164 #define IWMMXT_OP_ENV1(name) \
1165 static inline void gen_op_iwmmxt_##name##_M0(void) \
1167 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1181 IWMMXT_OP_ENV_SIZE(unpackl
)
1182 IWMMXT_OP_ENV_SIZE(unpackh
)
1184 IWMMXT_OP_ENV1(unpacklub
)
1185 IWMMXT_OP_ENV1(unpackluw
)
1186 IWMMXT_OP_ENV1(unpacklul
)
1187 IWMMXT_OP_ENV1(unpackhub
)
1188 IWMMXT_OP_ENV1(unpackhuw
)
1189 IWMMXT_OP_ENV1(unpackhul
)
1190 IWMMXT_OP_ENV1(unpacklsb
)
1191 IWMMXT_OP_ENV1(unpacklsw
)
1192 IWMMXT_OP_ENV1(unpacklsl
)
1193 IWMMXT_OP_ENV1(unpackhsb
)
1194 IWMMXT_OP_ENV1(unpackhsw
)
1195 IWMMXT_OP_ENV1(unpackhsl
)
1197 IWMMXT_OP_ENV_SIZE(cmpeq
)
1198 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1199 IWMMXT_OP_ENV_SIZE(cmpgts
)
1201 IWMMXT_OP_ENV_SIZE(mins
)
1202 IWMMXT_OP_ENV_SIZE(minu
)
1203 IWMMXT_OP_ENV_SIZE(maxs
)
1204 IWMMXT_OP_ENV_SIZE(maxu
)
1206 IWMMXT_OP_ENV_SIZE(subn
)
1207 IWMMXT_OP_ENV_SIZE(addn
)
1208 IWMMXT_OP_ENV_SIZE(subu
)
1209 IWMMXT_OP_ENV_SIZE(addu
)
1210 IWMMXT_OP_ENV_SIZE(subs
)
1211 IWMMXT_OP_ENV_SIZE(adds
)
1213 IWMMXT_OP_ENV(avgb0
)
1214 IWMMXT_OP_ENV(avgb1
)
1215 IWMMXT_OP_ENV(avgw0
)
1216 IWMMXT_OP_ENV(avgw1
)
1220 IWMMXT_OP_ENV(packuw
)
1221 IWMMXT_OP_ENV(packul
)
1222 IWMMXT_OP_ENV(packuq
)
1223 IWMMXT_OP_ENV(packsw
)
1224 IWMMXT_OP_ENV(packsl
)
1225 IWMMXT_OP_ENV(packsq
)
1227 static void gen_op_iwmmxt_set_mup(void)
1230 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1231 tcg_gen_ori_i32(tmp
, tmp
, 2);
1232 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1235 static void gen_op_iwmmxt_set_cup(void)
1238 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1239 tcg_gen_ori_i32(tmp
, tmp
, 1);
1240 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1243 static void gen_op_iwmmxt_setpsr_nz(void)
1245 TCGv tmp
= new_tmp();
1246 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1247 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1250 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1252 iwmmxt_load_reg(cpu_V1
, rn
);
1253 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1254 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1257 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1263 rd
= (insn
>> 16) & 0xf;
1264 tmp
= load_reg(s
, rd
);
1266 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1267 if (insn
& (1 << 24)) {
1269 if (insn
& (1 << 23))
1270 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1272 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1273 tcg_gen_mov_i32(dest
, tmp
);
1274 if (insn
& (1 << 21))
1275 store_reg(s
, rd
, tmp
);
1278 } else if (insn
& (1 << 21)) {
1280 tcg_gen_mov_i32(dest
, tmp
);
1281 if (insn
& (1 << 23))
1282 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1284 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1285 store_reg(s
, rd
, tmp
);
1286 } else if (!(insn
& (1 << 23)))
1291 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1293 int rd
= (insn
>> 0) & 0xf;
1296 if (insn
& (1 << 8)) {
1297 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1300 tmp
= iwmmxt_load_creg(rd
);
1304 iwmmxt_load_reg(cpu_V0
, rd
);
1305 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1307 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1308 tcg_gen_mov_i32(dest
, tmp
);
1313 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1314 (ie. an undefined instruction). */
1315 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1318 int rdhi
, rdlo
, rd0
, rd1
, i
;
1320 TCGv tmp
, tmp2
, tmp3
;
1322 if ((insn
& 0x0e000e00) == 0x0c000000) {
1323 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1325 rdlo
= (insn
>> 12) & 0xf;
1326 rdhi
= (insn
>> 16) & 0xf;
1327 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1328 iwmmxt_load_reg(cpu_V0
, wrd
);
1329 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1330 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1331 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1332 } else { /* TMCRR */
1333 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1334 iwmmxt_store_reg(cpu_V0
, wrd
);
1335 gen_op_iwmmxt_set_mup();
1340 wrd
= (insn
>> 12) & 0xf;
1342 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1346 if (insn
& ARM_CP_RW_BIT
) {
1347 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1349 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1350 iwmmxt_store_creg(wrd
, tmp
);
1353 if (insn
& (1 << 8)) {
1354 if (insn
& (1 << 22)) { /* WLDRD */
1355 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1357 } else { /* WLDRW wRd */
1358 tmp
= gen_ld32(addr
, IS_USER(s
));
1361 if (insn
& (1 << 22)) { /* WLDRH */
1362 tmp
= gen_ld16u(addr
, IS_USER(s
));
1363 } else { /* WLDRB */
1364 tmp
= gen_ld8u(addr
, IS_USER(s
));
1368 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1371 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1374 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1375 tmp
= iwmmxt_load_creg(wrd
);
1376 gen_st32(tmp
, addr
, IS_USER(s
));
1378 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1380 if (insn
& (1 << 8)) {
1381 if (insn
& (1 << 22)) { /* WSTRD */
1383 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1384 } else { /* WSTRW wRd */
1385 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1386 gen_st32(tmp
, addr
, IS_USER(s
));
1389 if (insn
& (1 << 22)) { /* WSTRH */
1390 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1391 gen_st16(tmp
, addr
, IS_USER(s
));
1392 } else { /* WSTRB */
1393 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1394 gen_st8(tmp
, addr
, IS_USER(s
));
1402 if ((insn
& 0x0f000000) != 0x0e000000)
1405 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1406 case 0x000: /* WOR */
1407 wrd
= (insn
>> 12) & 0xf;
1408 rd0
= (insn
>> 0) & 0xf;
1409 rd1
= (insn
>> 16) & 0xf;
1410 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1411 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1412 gen_op_iwmmxt_setpsr_nz();
1413 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1414 gen_op_iwmmxt_set_mup();
1415 gen_op_iwmmxt_set_cup();
1417 case 0x011: /* TMCR */
1420 rd
= (insn
>> 12) & 0xf;
1421 wrd
= (insn
>> 16) & 0xf;
1423 case ARM_IWMMXT_wCID
:
1424 case ARM_IWMMXT_wCASF
:
1426 case ARM_IWMMXT_wCon
:
1427 gen_op_iwmmxt_set_cup();
1429 case ARM_IWMMXT_wCSSF
:
1430 tmp
= iwmmxt_load_creg(wrd
);
1431 tmp2
= load_reg(s
, rd
);
1432 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1434 iwmmxt_store_creg(wrd
, tmp
);
1436 case ARM_IWMMXT_wCGR0
:
1437 case ARM_IWMMXT_wCGR1
:
1438 case ARM_IWMMXT_wCGR2
:
1439 case ARM_IWMMXT_wCGR3
:
1440 gen_op_iwmmxt_set_cup();
1441 tmp
= load_reg(s
, rd
);
1442 iwmmxt_store_creg(wrd
, tmp
);
1448 case 0x100: /* WXOR */
1449 wrd
= (insn
>> 12) & 0xf;
1450 rd0
= (insn
>> 0) & 0xf;
1451 rd1
= (insn
>> 16) & 0xf;
1452 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1453 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1454 gen_op_iwmmxt_setpsr_nz();
1455 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1456 gen_op_iwmmxt_set_mup();
1457 gen_op_iwmmxt_set_cup();
1459 case 0x111: /* TMRC */
1462 rd
= (insn
>> 12) & 0xf;
1463 wrd
= (insn
>> 16) & 0xf;
1464 tmp
= iwmmxt_load_creg(wrd
);
1465 store_reg(s
, rd
, tmp
);
1467 case 0x300: /* WANDN */
1468 wrd
= (insn
>> 12) & 0xf;
1469 rd0
= (insn
>> 0) & 0xf;
1470 rd1
= (insn
>> 16) & 0xf;
1471 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1472 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1473 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1474 gen_op_iwmmxt_setpsr_nz();
1475 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1476 gen_op_iwmmxt_set_mup();
1477 gen_op_iwmmxt_set_cup();
1479 case 0x200: /* WAND */
1480 wrd
= (insn
>> 12) & 0xf;
1481 rd0
= (insn
>> 0) & 0xf;
1482 rd1
= (insn
>> 16) & 0xf;
1483 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1484 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1485 gen_op_iwmmxt_setpsr_nz();
1486 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1487 gen_op_iwmmxt_set_mup();
1488 gen_op_iwmmxt_set_cup();
1490 case 0x810: case 0xa10: /* WMADD */
1491 wrd
= (insn
>> 12) & 0xf;
1492 rd0
= (insn
>> 0) & 0xf;
1493 rd1
= (insn
>> 16) & 0xf;
1494 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1495 if (insn
& (1 << 21))
1496 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1498 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1499 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1500 gen_op_iwmmxt_set_mup();
1502 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1503 wrd
= (insn
>> 12) & 0xf;
1504 rd0
= (insn
>> 16) & 0xf;
1505 rd1
= (insn
>> 0) & 0xf;
1506 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1507 switch ((insn
>> 22) & 3) {
1509 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1512 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1515 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1520 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1521 gen_op_iwmmxt_set_mup();
1522 gen_op_iwmmxt_set_cup();
1524 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1525 wrd
= (insn
>> 12) & 0xf;
1526 rd0
= (insn
>> 16) & 0xf;
1527 rd1
= (insn
>> 0) & 0xf;
1528 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1529 switch ((insn
>> 22) & 3) {
1531 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1534 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1537 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1542 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1543 gen_op_iwmmxt_set_mup();
1544 gen_op_iwmmxt_set_cup();
1546 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1547 wrd
= (insn
>> 12) & 0xf;
1548 rd0
= (insn
>> 16) & 0xf;
1549 rd1
= (insn
>> 0) & 0xf;
1550 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1551 if (insn
& (1 << 22))
1552 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1554 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1555 if (!(insn
& (1 << 20)))
1556 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1557 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1558 gen_op_iwmmxt_set_mup();
1560 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1561 wrd
= (insn
>> 12) & 0xf;
1562 rd0
= (insn
>> 16) & 0xf;
1563 rd1
= (insn
>> 0) & 0xf;
1564 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1565 if (insn
& (1 << 21)) {
1566 if (insn
& (1 << 20))
1567 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1569 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1571 if (insn
& (1 << 20))
1572 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1574 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1576 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1577 gen_op_iwmmxt_set_mup();
1579 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1580 wrd
= (insn
>> 12) & 0xf;
1581 rd0
= (insn
>> 16) & 0xf;
1582 rd1
= (insn
>> 0) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1584 if (insn
& (1 << 21))
1585 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1587 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1588 if (!(insn
& (1 << 20))) {
1589 iwmmxt_load_reg(cpu_V1
, wrd
);
1590 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1592 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1593 gen_op_iwmmxt_set_mup();
1595 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1596 wrd
= (insn
>> 12) & 0xf;
1597 rd0
= (insn
>> 16) & 0xf;
1598 rd1
= (insn
>> 0) & 0xf;
1599 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1600 switch ((insn
>> 22) & 3) {
1602 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1605 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1608 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1613 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1614 gen_op_iwmmxt_set_mup();
1615 gen_op_iwmmxt_set_cup();
1617 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1618 wrd
= (insn
>> 12) & 0xf;
1619 rd0
= (insn
>> 16) & 0xf;
1620 rd1
= (insn
>> 0) & 0xf;
1621 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1622 if (insn
& (1 << 22)) {
1623 if (insn
& (1 << 20))
1624 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1626 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1628 if (insn
& (1 << 20))
1629 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1631 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1633 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1634 gen_op_iwmmxt_set_mup();
1635 gen_op_iwmmxt_set_cup();
1637 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1638 wrd
= (insn
>> 12) & 0xf;
1639 rd0
= (insn
>> 16) & 0xf;
1640 rd1
= (insn
>> 0) & 0xf;
1641 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1642 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1643 tcg_gen_andi_i32(tmp
, tmp
, 7);
1644 iwmmxt_load_reg(cpu_V1
, rd1
);
1645 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1647 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1648 gen_op_iwmmxt_set_mup();
1650 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1651 if (((insn
>> 6) & 3) == 3)
1653 rd
= (insn
>> 12) & 0xf;
1654 wrd
= (insn
>> 16) & 0xf;
1655 tmp
= load_reg(s
, rd
);
1656 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1657 switch ((insn
>> 6) & 3) {
1659 tmp2
= tcg_const_i32(0xff);
1660 tmp3
= tcg_const_i32((insn
& 7) << 3);
1663 tmp2
= tcg_const_i32(0xffff);
1664 tmp3
= tcg_const_i32((insn
& 3) << 4);
1667 tmp2
= tcg_const_i32(0xffffffff);
1668 tmp3
= tcg_const_i32((insn
& 1) << 5);
1674 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1675 tcg_temp_free(tmp3
);
1676 tcg_temp_free(tmp2
);
1678 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1679 gen_op_iwmmxt_set_mup();
1681 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1682 rd
= (insn
>> 12) & 0xf;
1683 wrd
= (insn
>> 16) & 0xf;
1684 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1686 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1688 switch ((insn
>> 22) & 3) {
1690 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1691 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1693 tcg_gen_ext8s_i32(tmp
, tmp
);
1695 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1699 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1700 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1702 tcg_gen_ext16s_i32(tmp
, tmp
);
1704 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1708 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1709 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1712 store_reg(s
, rd
, tmp
);
1714 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1715 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1717 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1718 switch ((insn
>> 22) & 3) {
1720 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1723 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1726 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1729 tcg_gen_shli_i32(tmp
, tmp
, 28);
1733 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1734 if (((insn
>> 6) & 3) == 3)
1736 rd
= (insn
>> 12) & 0xf;
1737 wrd
= (insn
>> 16) & 0xf;
1738 tmp
= load_reg(s
, rd
);
1739 switch ((insn
>> 6) & 3) {
1741 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1744 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1747 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1751 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1752 gen_op_iwmmxt_set_mup();
1754 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1755 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1757 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1759 tcg_gen_mov_i32(tmp2
, tmp
);
1760 switch ((insn
>> 22) & 3) {
1762 for (i
= 0; i
< 7; i
++) {
1763 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1764 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1768 for (i
= 0; i
< 3; i
++) {
1769 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1770 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1774 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1775 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1782 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1783 wrd
= (insn
>> 12) & 0xf;
1784 rd0
= (insn
>> 16) & 0xf;
1785 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1786 switch ((insn
>> 22) & 3) {
1788 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1791 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1794 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1799 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1800 gen_op_iwmmxt_set_mup();
1802 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1803 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1805 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1807 tcg_gen_mov_i32(tmp2
, tmp
);
1808 switch ((insn
>> 22) & 3) {
1810 for (i
= 0; i
< 7; i
++) {
1811 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1812 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1816 for (i
= 0; i
< 3; i
++) {
1817 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1818 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1822 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1823 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1830 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1831 rd
= (insn
>> 12) & 0xf;
1832 rd0
= (insn
>> 16) & 0xf;
1833 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1835 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1837 switch ((insn
>> 22) & 3) {
1839 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1842 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1845 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1848 store_reg(s
, rd
, tmp
);
1850 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1851 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1852 wrd
= (insn
>> 12) & 0xf;
1853 rd0
= (insn
>> 16) & 0xf;
1854 rd1
= (insn
>> 0) & 0xf;
1855 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1856 switch ((insn
>> 22) & 3) {
1858 if (insn
& (1 << 21))
1859 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1861 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1864 if (insn
& (1 << 21))
1865 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1867 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1870 if (insn
& (1 << 21))
1871 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1873 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1878 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1879 gen_op_iwmmxt_set_mup();
1880 gen_op_iwmmxt_set_cup();
1882 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1883 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1884 wrd
= (insn
>> 12) & 0xf;
1885 rd0
= (insn
>> 16) & 0xf;
1886 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1887 switch ((insn
>> 22) & 3) {
1889 if (insn
& (1 << 21))
1890 gen_op_iwmmxt_unpacklsb_M0();
1892 gen_op_iwmmxt_unpacklub_M0();
1895 if (insn
& (1 << 21))
1896 gen_op_iwmmxt_unpacklsw_M0();
1898 gen_op_iwmmxt_unpackluw_M0();
1901 if (insn
& (1 << 21))
1902 gen_op_iwmmxt_unpacklsl_M0();
1904 gen_op_iwmmxt_unpacklul_M0();
1909 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1910 gen_op_iwmmxt_set_mup();
1911 gen_op_iwmmxt_set_cup();
1913 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1914 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1915 wrd
= (insn
>> 12) & 0xf;
1916 rd0
= (insn
>> 16) & 0xf;
1917 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1918 switch ((insn
>> 22) & 3) {
1920 if (insn
& (1 << 21))
1921 gen_op_iwmmxt_unpackhsb_M0();
1923 gen_op_iwmmxt_unpackhub_M0();
1926 if (insn
& (1 << 21))
1927 gen_op_iwmmxt_unpackhsw_M0();
1929 gen_op_iwmmxt_unpackhuw_M0();
1932 if (insn
& (1 << 21))
1933 gen_op_iwmmxt_unpackhsl_M0();
1935 gen_op_iwmmxt_unpackhul_M0();
1940 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1941 gen_op_iwmmxt_set_mup();
1942 gen_op_iwmmxt_set_cup();
1944 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1945 case 0x214: case 0x614: case 0xa14: case 0xe14:
1946 if (((insn
>> 22) & 3) == 0)
1948 wrd
= (insn
>> 12) & 0xf;
1949 rd0
= (insn
>> 16) & 0xf;
1950 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1952 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1956 switch ((insn
>> 22) & 3) {
1958 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1961 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1964 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1968 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1969 gen_op_iwmmxt_set_mup();
1970 gen_op_iwmmxt_set_cup();
1972 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1973 case 0x014: case 0x414: case 0x814: case 0xc14:
1974 if (((insn
>> 22) & 3) == 0)
1976 wrd
= (insn
>> 12) & 0xf;
1977 rd0
= (insn
>> 16) & 0xf;
1978 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1980 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1984 switch ((insn
>> 22) & 3) {
1986 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1989 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1992 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1996 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1997 gen_op_iwmmxt_set_mup();
1998 gen_op_iwmmxt_set_cup();
2000 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2001 case 0x114: case 0x514: case 0x914: case 0xd14:
2002 if (((insn
>> 22) & 3) == 0)
2004 wrd
= (insn
>> 12) & 0xf;
2005 rd0
= (insn
>> 16) & 0xf;
2006 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2008 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2012 switch ((insn
>> 22) & 3) {
2014 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2017 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2020 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2024 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2025 gen_op_iwmmxt_set_mup();
2026 gen_op_iwmmxt_set_cup();
2028 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2029 case 0x314: case 0x714: case 0xb14: case 0xf14:
2030 if (((insn
>> 22) & 3) == 0)
2032 wrd
= (insn
>> 12) & 0xf;
2033 rd0
= (insn
>> 16) & 0xf;
2034 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2036 switch ((insn
>> 22) & 3) {
2038 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2042 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2045 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2049 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2052 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2056 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2060 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2061 gen_op_iwmmxt_set_mup();
2062 gen_op_iwmmxt_set_cup();
2064 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2065 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2066 wrd
= (insn
>> 12) & 0xf;
2067 rd0
= (insn
>> 16) & 0xf;
2068 rd1
= (insn
>> 0) & 0xf;
2069 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2070 switch ((insn
>> 22) & 3) {
2072 if (insn
& (1 << 21))
2073 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2075 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2078 if (insn
& (1 << 21))
2079 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2081 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2084 if (insn
& (1 << 21))
2085 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2087 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2092 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2093 gen_op_iwmmxt_set_mup();
2095 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2096 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2097 wrd
= (insn
>> 12) & 0xf;
2098 rd0
= (insn
>> 16) & 0xf;
2099 rd1
= (insn
>> 0) & 0xf;
2100 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2101 switch ((insn
>> 22) & 3) {
2103 if (insn
& (1 << 21))
2104 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2106 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2109 if (insn
& (1 << 21))
2110 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2112 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2115 if (insn
& (1 << 21))
2116 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2118 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2123 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2124 gen_op_iwmmxt_set_mup();
2126 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2127 case 0x402: case 0x502: case 0x602: case 0x702:
2128 wrd
= (insn
>> 12) & 0xf;
2129 rd0
= (insn
>> 16) & 0xf;
2130 rd1
= (insn
>> 0) & 0xf;
2131 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2132 tmp
= tcg_const_i32((insn
>> 20) & 3);
2133 iwmmxt_load_reg(cpu_V1
, rd1
);
2134 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2136 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2137 gen_op_iwmmxt_set_mup();
2139 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2140 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2141 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2142 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2143 wrd
= (insn
>> 12) & 0xf;
2144 rd0
= (insn
>> 16) & 0xf;
2145 rd1
= (insn
>> 0) & 0xf;
2146 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2147 switch ((insn
>> 20) & 0xf) {
2149 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2152 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2155 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2158 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2161 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2164 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2167 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2170 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2173 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2178 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2179 gen_op_iwmmxt_set_mup();
2180 gen_op_iwmmxt_set_cup();
2182 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2183 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2184 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2185 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2186 wrd
= (insn
>> 12) & 0xf;
2187 rd0
= (insn
>> 16) & 0xf;
2188 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2189 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2190 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2192 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2193 gen_op_iwmmxt_set_mup();
2194 gen_op_iwmmxt_set_cup();
2196 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2197 case 0x418: case 0x518: case 0x618: case 0x718:
2198 case 0x818: case 0x918: case 0xa18: case 0xb18:
2199 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2200 wrd
= (insn
>> 12) & 0xf;
2201 rd0
= (insn
>> 16) & 0xf;
2202 rd1
= (insn
>> 0) & 0xf;
2203 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2204 switch ((insn
>> 20) & 0xf) {
2206 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2209 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2212 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2215 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2218 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2221 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2224 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2227 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2230 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2235 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2236 gen_op_iwmmxt_set_mup();
2237 gen_op_iwmmxt_set_cup();
2239 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2240 case 0x408: case 0x508: case 0x608: case 0x708:
2241 case 0x808: case 0x908: case 0xa08: case 0xb08:
2242 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2243 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2245 wrd
= (insn
>> 12) & 0xf;
2246 rd0
= (insn
>> 16) & 0xf;
2247 rd1
= (insn
>> 0) & 0xf;
2248 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2249 switch ((insn
>> 22) & 3) {
2251 if (insn
& (1 << 21))
2252 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2254 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2257 if (insn
& (1 << 21))
2258 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2260 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2263 if (insn
& (1 << 21))
2264 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2266 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2269 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2270 gen_op_iwmmxt_set_mup();
2271 gen_op_iwmmxt_set_cup();
2273 case 0x201: case 0x203: case 0x205: case 0x207:
2274 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2275 case 0x211: case 0x213: case 0x215: case 0x217:
2276 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2277 wrd
= (insn
>> 5) & 0xf;
2278 rd0
= (insn
>> 12) & 0xf;
2279 rd1
= (insn
>> 0) & 0xf;
2280 if (rd0
== 0xf || rd1
== 0xf)
2282 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2283 tmp
= load_reg(s
, rd0
);
2284 tmp2
= load_reg(s
, rd1
);
2285 switch ((insn
>> 16) & 0xf) {
2286 case 0x0: /* TMIA */
2287 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2289 case 0x8: /* TMIAPH */
2290 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2292 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2293 if (insn
& (1 << 16))
2294 tcg_gen_shri_i32(tmp
, tmp
, 16);
2295 if (insn
& (1 << 17))
2296 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2297 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2306 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2307 gen_op_iwmmxt_set_mup();
2316 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2317 (ie. an undefined instruction). */
2318 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2320 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2323 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2324 /* Multiply with Internal Accumulate Format */
2325 rd0
= (insn
>> 12) & 0xf;
2327 acc
= (insn
>> 5) & 7;
2332 tmp
= load_reg(s
, rd0
);
2333 tmp2
= load_reg(s
, rd1
);
2334 switch ((insn
>> 16) & 0xf) {
2336 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2338 case 0x8: /* MIAPH */
2339 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2341 case 0xc: /* MIABB */
2342 case 0xd: /* MIABT */
2343 case 0xe: /* MIATB */
2344 case 0xf: /* MIATT */
2345 if (insn
& (1 << 16))
2346 tcg_gen_shri_i32(tmp
, tmp
, 16);
2347 if (insn
& (1 << 17))
2348 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2349 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2357 gen_op_iwmmxt_movq_wRn_M0(acc
);
2361 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2362 /* Internal Accumulator Access Format */
2363 rdhi
= (insn
>> 16) & 0xf;
2364 rdlo
= (insn
>> 12) & 0xf;
2370 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2371 iwmmxt_load_reg(cpu_V0
, acc
);
2372 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2373 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2374 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2375 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2377 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2378 iwmmxt_store_reg(cpu_V0
, acc
);
2386 /* Disassemble system coprocessor instruction. Return nonzero if
2387 instruction is not defined. */
2388 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2391 uint32_t rd
= (insn
>> 12) & 0xf;
2392 uint32_t cp
= (insn
>> 8) & 0xf;
2397 if (insn
& ARM_CP_RW_BIT
) {
2398 if (!env
->cp
[cp
].cp_read
)
2400 gen_set_pc_im(s
->pc
);
2402 tmp2
= tcg_const_i32(insn
);
2403 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2404 tcg_temp_free(tmp2
);
2405 store_reg(s
, rd
, tmp
);
2407 if (!env
->cp
[cp
].cp_write
)
2409 gen_set_pc_im(s
->pc
);
2410 tmp
= load_reg(s
, rd
);
2411 tmp2
= tcg_const_i32(insn
);
2412 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2413 tcg_temp_free(tmp2
);
2419 static int cp15_user_ok(uint32_t insn
)
2421 int cpn
= (insn
>> 16) & 0xf;
2422 int cpm
= insn
& 0xf;
2423 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2425 if (cpn
== 13 && cpm
== 0) {
2427 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2431 /* ISB, DSB, DMB. */
2432 if ((cpm
== 5 && op
== 4)
2433 || (cpm
== 10 && (op
== 4 || op
== 5)))
2439 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2440 instruction is not defined. */
2441 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2446 /* M profile cores use memory mapped registers instead of cp15. */
2447 if (arm_feature(env
, ARM_FEATURE_M
))
2450 if ((insn
& (1 << 25)) == 0) {
2451 if (insn
& (1 << 20)) {
2455 /* mcrr. Used for block cache operations, so implement as no-op. */
2458 if ((insn
& (1 << 4)) == 0) {
2462 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2465 if ((insn
& 0x0fff0fff) == 0x0e070f90
2466 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2467 /* Wait for interrupt. */
2468 gen_set_pc_im(s
->pc
);
2469 s
->is_jmp
= DISAS_WFI
;
2472 rd
= (insn
>> 12) & 0xf;
2473 tmp2
= tcg_const_i32(insn
);
2474 if (insn
& ARM_CP_RW_BIT
) {
2476 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2477 /* If the destination register is r15 then sets condition codes. */
2479 store_reg(s
, rd
, tmp
);
2483 tmp
= load_reg(s
, rd
);
2484 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2486 /* Normally we would always end the TB here, but Linux
2487 * arch/arm/mach-pxa/sleep.S expects two instructions following
2488 * an MMU enable to execute from cache. Imitate this behaviour. */
2489 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2490 (insn
& 0x0fff0fff) != 0x0e010f10)
2493 tcg_temp_free_i32(tmp2
);
2497 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2498 #define VFP_SREG(insn, bigbit, smallbit) \
2499 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2500 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2501 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2502 reg = (((insn) >> (bigbit)) & 0x0f) \
2503 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2505 if (insn & (1 << (smallbit))) \
2507 reg = ((insn) >> (bigbit)) & 0x0f; \
2510 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2511 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2512 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2513 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2514 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2515 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2517 /* Move between integer and VFP cores. */
2518 static TCGv
gen_vfp_mrs(void)
2520 TCGv tmp
= new_tmp();
2521 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2525 static void gen_vfp_msr(TCGv tmp
)
2527 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2532 vfp_enabled(CPUState
* env
)
2534 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2537 static void gen_neon_dup_u8(TCGv var
, int shift
)
2539 TCGv tmp
= new_tmp();
2541 tcg_gen_shri_i32(var
, var
, shift
);
2542 tcg_gen_ext8u_i32(var
, var
);
2543 tcg_gen_shli_i32(tmp
, var
, 8);
2544 tcg_gen_or_i32(var
, var
, tmp
);
2545 tcg_gen_shli_i32(tmp
, var
, 16);
2546 tcg_gen_or_i32(var
, var
, tmp
);
2550 static void gen_neon_dup_low16(TCGv var
)
2552 TCGv tmp
= new_tmp();
2553 tcg_gen_ext16u_i32(var
, var
);
2554 tcg_gen_shli_i32(tmp
, var
, 16);
2555 tcg_gen_or_i32(var
, var
, tmp
);
2559 static void gen_neon_dup_high16(TCGv var
)
2561 TCGv tmp
= new_tmp();
2562 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2563 tcg_gen_shri_i32(tmp
, var
, 16);
2564 tcg_gen_or_i32(var
, var
, tmp
);
2568 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2569 (ie. an undefined instruction). */
2570 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2572 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2578 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2581 if (!vfp_enabled(env
)) {
2582 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2583 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2585 rn
= (insn
>> 16) & 0xf;
2586 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2587 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2590 dp
= ((insn
& 0xf00) == 0xb00);
2591 switch ((insn
>> 24) & 0xf) {
2593 if (insn
& (1 << 4)) {
2594 /* single register transfer */
2595 rd
= (insn
>> 12) & 0xf;
2600 VFP_DREG_N(rn
, insn
);
2603 if (insn
& 0x00c00060
2604 && !arm_feature(env
, ARM_FEATURE_NEON
))
2607 pass
= (insn
>> 21) & 1;
2608 if (insn
& (1 << 22)) {
2610 offset
= ((insn
>> 5) & 3) * 8;
2611 } else if (insn
& (1 << 5)) {
2613 offset
= (insn
& (1 << 6)) ? 16 : 0;
2618 if (insn
& ARM_CP_RW_BIT
) {
2620 tmp
= neon_load_reg(rn
, pass
);
2624 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2625 if (insn
& (1 << 23))
2631 if (insn
& (1 << 23)) {
2633 tcg_gen_shri_i32(tmp
, tmp
, 16);
2639 tcg_gen_sari_i32(tmp
, tmp
, 16);
2648 store_reg(s
, rd
, tmp
);
2651 tmp
= load_reg(s
, rd
);
2652 if (insn
& (1 << 23)) {
2655 gen_neon_dup_u8(tmp
, 0);
2656 } else if (size
== 1) {
2657 gen_neon_dup_low16(tmp
);
2659 for (n
= 0; n
<= pass
* 2; n
++) {
2661 tcg_gen_mov_i32(tmp2
, tmp
);
2662 neon_store_reg(rn
, n
, tmp2
);
2664 neon_store_reg(rn
, n
, tmp
);
2669 tmp2
= neon_load_reg(rn
, pass
);
2670 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2674 tmp2
= neon_load_reg(rn
, pass
);
2675 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2681 neon_store_reg(rn
, pass
, tmp
);
2685 if ((insn
& 0x6f) != 0x00)
2687 rn
= VFP_SREG_N(insn
);
2688 if (insn
& ARM_CP_RW_BIT
) {
2690 if (insn
& (1 << 21)) {
2691 /* system register */
2696 /* VFP2 allows access to FSID from userspace.
2697 VFP3 restricts all id registers to privileged
2700 && arm_feature(env
, ARM_FEATURE_VFP3
))
2702 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2707 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2709 case ARM_VFP_FPINST
:
2710 case ARM_VFP_FPINST2
:
2711 /* Not present in VFP3. */
2713 || arm_feature(env
, ARM_FEATURE_VFP3
))
2715 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2719 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2720 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2723 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2729 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2731 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2737 gen_mov_F0_vreg(0, rn
);
2738 tmp
= gen_vfp_mrs();
2741 /* Set the 4 flag bits in the CPSR. */
2745 store_reg(s
, rd
, tmp
);
2749 tmp
= load_reg(s
, rd
);
2750 if (insn
& (1 << 21)) {
2752 /* system register */
2757 /* Writes are ignored. */
2760 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2767 /* TODO: VFP subarchitecture support.
2768 * For now, keep the EN bit only */
2769 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2770 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2773 case ARM_VFP_FPINST
:
2774 case ARM_VFP_FPINST2
:
2775 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2782 gen_mov_vreg_F0(0, rn
);
2787 /* data processing */
2788 /* The opcode is in bits 23, 21, 20 and 6. */
2789 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2793 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2795 /* rn is register number */
2796 VFP_DREG_N(rn
, insn
);
2799 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2800 /* Integer or single precision destination. */
2801 rd
= VFP_SREG_D(insn
);
2803 VFP_DREG_D(rd
, insn
);
2806 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2807 /* Integer source. */
2808 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2810 VFP_DREG_M(rm
, insn
);
2813 rn
= VFP_SREG_N(insn
);
2814 if (op
== 15 && rn
== 15) {
2815 /* Double precision destination. */
2816 VFP_DREG_D(rd
, insn
);
2818 rd
= VFP_SREG_D(insn
);
2820 rm
= VFP_SREG_M(insn
);
2823 veclen
= env
->vfp
.vec_len
;
2824 if (op
== 15 && rn
> 3)
2827 /* Shut up compiler warnings. */
2838 /* Figure out what type of vector operation this is. */
2839 if ((rd
& bank_mask
) == 0) {
2844 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2846 delta_d
= env
->vfp
.vec_stride
+ 1;
2848 if ((rm
& bank_mask
) == 0) {
2849 /* mixed scalar/vector */
2858 /* Load the initial operands. */
2863 /* Integer source */
2864 gen_mov_F0_vreg(0, rm
);
2869 gen_mov_F0_vreg(dp
, rd
);
2870 gen_mov_F1_vreg(dp
, rm
);
2874 /* Compare with zero */
2875 gen_mov_F0_vreg(dp
, rd
);
2886 /* Source and destination the same. */
2887 gen_mov_F0_vreg(dp
, rd
);
2890 /* One source operand. */
2891 gen_mov_F0_vreg(dp
, rm
);
2895 /* Two source operands. */
2896 gen_mov_F0_vreg(dp
, rn
);
2897 gen_mov_F1_vreg(dp
, rm
);
2901 /* Perform the calculation. */
2903 case 0: /* mac: fd + (fn * fm) */
2905 gen_mov_F1_vreg(dp
, rd
);
2908 case 1: /* nmac: fd - (fn * fm) */
2911 gen_mov_F1_vreg(dp
, rd
);
2914 case 2: /* msc: -fd + (fn * fm) */
2916 gen_mov_F1_vreg(dp
, rd
);
2919 case 3: /* nmsc: -fd - (fn * fm) */
2922 gen_mov_F1_vreg(dp
, rd
);
2925 case 4: /* mul: fn * fm */
2928 case 5: /* nmul: -(fn * fm) */
2932 case 6: /* add: fn + fm */
2935 case 7: /* sub: fn - fm */
2938 case 8: /* div: fn / fm */
2941 case 14: /* fconst */
2942 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2945 n
= (insn
<< 12) & 0x80000000;
2946 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2953 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
2960 tcg_gen_movi_i32(cpu_F0s
, n
);
2963 case 15: /* extension space */
2977 case 4: /* vcvtb.f32.f16 */
2978 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
2980 tmp
= gen_vfp_mrs();
2981 tcg_gen_ext16u_i32(tmp
, tmp
);
2982 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
2985 case 5: /* vcvtt.f32.f16 */
2986 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
2988 tmp
= gen_vfp_mrs();
2989 tcg_gen_shri_i32(tmp
, tmp
, 16);
2990 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
2993 case 6: /* vcvtb.f16.f32 */
2994 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
2997 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
2998 gen_mov_F0_vreg(0, rd
);
2999 tmp2
= gen_vfp_mrs();
3000 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3001 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3005 case 7: /* vcvtt.f16.f32 */
3006 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3009 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3010 tcg_gen_shli_i32(tmp
, tmp
, 16);
3011 gen_mov_F0_vreg(0, rd
);
3012 tmp2
= gen_vfp_mrs();
3013 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3014 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3027 case 11: /* cmpez */
3031 case 15: /* single<->double conversion */
3033 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3035 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3037 case 16: /* fuito */
3040 case 17: /* fsito */
3043 case 20: /* fshto */
3044 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3046 gen_vfp_shto(dp
, 16 - rm
);
3048 case 21: /* fslto */
3049 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3051 gen_vfp_slto(dp
, 32 - rm
);
3053 case 22: /* fuhto */
3054 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3056 gen_vfp_uhto(dp
, 16 - rm
);
3058 case 23: /* fulto */
3059 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3061 gen_vfp_ulto(dp
, 32 - rm
);
3063 case 24: /* ftoui */
3066 case 25: /* ftouiz */
3069 case 26: /* ftosi */
3072 case 27: /* ftosiz */
3075 case 28: /* ftosh */
3076 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3078 gen_vfp_tosh(dp
, 16 - rm
);
3080 case 29: /* ftosl */
3081 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3083 gen_vfp_tosl(dp
, 32 - rm
);
3085 case 30: /* ftouh */
3086 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3088 gen_vfp_touh(dp
, 16 - rm
);
3090 case 31: /* ftoul */
3091 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3093 gen_vfp_toul(dp
, 32 - rm
);
3095 default: /* undefined */
3096 printf ("rn:%d\n", rn
);
3100 default: /* undefined */
3101 printf ("op:%d\n", op
);
3105 /* Write back the result. */
3106 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3107 ; /* Comparison, do nothing. */
3108 else if (op
== 15 && rn
> 17)
3109 /* Integer result. */
3110 gen_mov_vreg_F0(0, rd
);
3111 else if (op
== 15 && rn
== 15)
3113 gen_mov_vreg_F0(!dp
, rd
);
3115 gen_mov_vreg_F0(dp
, rd
);
3117 /* break out of the loop if we have finished */
3121 if (op
== 15 && delta_m
== 0) {
3122 /* single source one-many */
3124 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3126 gen_mov_vreg_F0(dp
, rd
);
3130 /* Setup the next operands. */
3132 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3136 /* One source operand. */
3137 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3139 gen_mov_F0_vreg(dp
, rm
);
3141 /* Two source operands. */
3142 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3144 gen_mov_F0_vreg(dp
, rn
);
3146 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3148 gen_mov_F1_vreg(dp
, rm
);
3156 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3157 /* two-register transfer */
3158 rn
= (insn
>> 16) & 0xf;
3159 rd
= (insn
>> 12) & 0xf;
3161 VFP_DREG_M(rm
, insn
);
3163 rm
= VFP_SREG_M(insn
);
3166 if (insn
& ARM_CP_RW_BIT
) {
3169 gen_mov_F0_vreg(0, rm
* 2);
3170 tmp
= gen_vfp_mrs();
3171 store_reg(s
, rd
, tmp
);
3172 gen_mov_F0_vreg(0, rm
* 2 + 1);
3173 tmp
= gen_vfp_mrs();
3174 store_reg(s
, rn
, tmp
);
3176 gen_mov_F0_vreg(0, rm
);
3177 tmp
= gen_vfp_mrs();
3178 store_reg(s
, rn
, tmp
);
3179 gen_mov_F0_vreg(0, rm
+ 1);
3180 tmp
= gen_vfp_mrs();
3181 store_reg(s
, rd
, tmp
);
3186 tmp
= load_reg(s
, rd
);
3188 gen_mov_vreg_F0(0, rm
* 2);
3189 tmp
= load_reg(s
, rn
);
3191 gen_mov_vreg_F0(0, rm
* 2 + 1);
3193 tmp
= load_reg(s
, rn
);
3195 gen_mov_vreg_F0(0, rm
);
3196 tmp
= load_reg(s
, rd
);
3198 gen_mov_vreg_F0(0, rm
+ 1);
3203 rn
= (insn
>> 16) & 0xf;
3205 VFP_DREG_D(rd
, insn
);
3207 rd
= VFP_SREG_D(insn
);
3208 if (s
->thumb
&& rn
== 15) {
3210 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3212 addr
= load_reg(s
, rn
);
3214 if ((insn
& 0x01200000) == 0x01000000) {
3215 /* Single load/store */
3216 offset
= (insn
& 0xff) << 2;
3217 if ((insn
& (1 << 23)) == 0)
3219 tcg_gen_addi_i32(addr
, addr
, offset
);
3220 if (insn
& (1 << 20)) {
3221 gen_vfp_ld(s
, dp
, addr
);
3222 gen_mov_vreg_F0(dp
, rd
);
3224 gen_mov_F0_vreg(dp
, rd
);
3225 gen_vfp_st(s
, dp
, addr
);
3229 /* load/store multiple */
3231 n
= (insn
>> 1) & 0x7f;
3235 if (insn
& (1 << 24)) /* pre-decrement */
3236 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3242 for (i
= 0; i
< n
; i
++) {
3243 if (insn
& ARM_CP_RW_BIT
) {
3245 gen_vfp_ld(s
, dp
, addr
);
3246 gen_mov_vreg_F0(dp
, rd
+ i
);
3249 gen_mov_F0_vreg(dp
, rd
+ i
);
3250 gen_vfp_st(s
, dp
, addr
);
3252 tcg_gen_addi_i32(addr
, addr
, offset
);
3254 if (insn
& (1 << 21)) {
3256 if (insn
& (1 << 24))
3257 offset
= -offset
* n
;
3258 else if (dp
&& (insn
& 1))
3264 tcg_gen_addi_i32(addr
, addr
, offset
);
3265 store_reg(s
, rn
, addr
);
3273 /* Should never happen. */
3279 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3281 TranslationBlock
*tb
;
3284 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3286 gen_set_pc_im(dest
);
3287 tcg_gen_exit_tb((long)tb
+ n
);
3289 gen_set_pc_im(dest
);
3294 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3296 if (unlikely(s
->singlestep_enabled
)) {
3297 /* An indirect jump so that we still trigger the debug exception. */
3302 gen_goto_tb(s
, 0, dest
);
3303 s
->is_jmp
= DISAS_TB_JUMP
;
3307 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3310 tcg_gen_sari_i32(t0
, t0
, 16);
3314 tcg_gen_sari_i32(t1
, t1
, 16);
3317 tcg_gen_mul_i32(t0
, t0
, t1
);
3320 /* Return the mask of PSR bits set by a MSR instruction. */
3321 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3325 if (flags
& (1 << 0))
3327 if (flags
& (1 << 1))
3329 if (flags
& (1 << 2))
3331 if (flags
& (1 << 3))
3334 /* Mask out undefined bits. */
3335 mask
&= ~CPSR_RESERVED
;
3336 if (!arm_feature(env
, ARM_FEATURE_V6
))
3337 mask
&= ~(CPSR_E
| CPSR_GE
);
3338 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3340 /* Mask out execution state bits. */
3343 /* Mask out privileged bits. */
3349 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3350 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3354 /* ??? This is also undefined in system mode. */
3358 tmp
= load_cpu_field(spsr
);
3359 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3360 tcg_gen_andi_i32(t0
, t0
, mask
);
3361 tcg_gen_or_i32(tmp
, tmp
, t0
);
3362 store_cpu_field(tmp
, spsr
);
3364 gen_set_cpsr(t0
, mask
);
3371 /* Returns nonzero if access to the PSR is not permitted. */
3372 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3376 tcg_gen_movi_i32(tmp
, val
);
3377 return gen_set_psr(s
, mask
, spsr
, tmp
);
3380 /* Generate an old-style exception return. Marks pc as dead. */
3381 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3384 store_reg(s
, 15, pc
);
3385 tmp
= load_cpu_field(spsr
);
3386 gen_set_cpsr(tmp
, 0xffffffff);
3388 s
->is_jmp
= DISAS_UPDATE
;
3391 /* Generate a v6 exception return. Marks both values as dead. */
3392 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3394 gen_set_cpsr(cpsr
, 0xffffffff);
3396 store_reg(s
, 15, pc
);
3397 s
->is_jmp
= DISAS_UPDATE
;
3401 gen_set_condexec (DisasContext
*s
)
3403 if (s
->condexec_mask
) {
3404 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3405 TCGv tmp
= new_tmp();
3406 tcg_gen_movi_i32(tmp
, val
);
3407 store_cpu_field(tmp
, condexec_bits
);
3411 static void gen_nop_hint(DisasContext
*s
, int val
)
3415 gen_set_pc_im(s
->pc
);
3416 s
->is_jmp
= DISAS_WFI
;
3420 /* TODO: Implement SEV and WFE. May help SMP performance. */
3426 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3428 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3431 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3432 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3433 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3439 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3442 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3443 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3444 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3449 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3450 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3451 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3452 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3453 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3455 /* FIXME: This is wrong. They set the wrong overflow bit. */
3456 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3457 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3458 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3459 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3461 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3462 switch ((size << 1) | u) { \
3464 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3467 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3470 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3473 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3476 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3479 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3481 default: return 1; \
3484 #define GEN_NEON_INTEGER_OP(name) do { \
3485 switch ((size << 1) | u) { \
3487 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3490 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3493 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3496 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3499 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3502 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3504 default: return 1; \
3507 static TCGv
neon_load_scratch(int scratch
)
3509 TCGv tmp
= new_tmp();
3510 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3514 static void neon_store_scratch(int scratch
, TCGv var
)
3516 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3520 static inline TCGv
neon_get_scalar(int size
, int reg
)
3524 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3526 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3528 gen_neon_dup_low16(tmp
);
3530 gen_neon_dup_high16(tmp
);
3536 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3544 tcg_gen_andi_i32(rd
, t0
, 0xff);
3545 tcg_gen_shri_i32(tmp
, t0
, 8);
3546 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3547 tcg_gen_or_i32(rd
, rd
, tmp
);
3548 tcg_gen_shli_i32(tmp
, t1
, 16);
3549 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3550 tcg_gen_or_i32(rd
, rd
, tmp
);
3551 tcg_gen_shli_i32(tmp
, t1
, 8);
3552 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3553 tcg_gen_or_i32(rd
, rd
, tmp
);
3555 tcg_gen_shri_i32(rm
, t0
, 8);
3556 tcg_gen_andi_i32(rm
, rm
, 0xff);
3557 tcg_gen_shri_i32(tmp
, t0
, 16);
3558 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3559 tcg_gen_or_i32(rm
, rm
, tmp
);
3560 tcg_gen_shli_i32(tmp
, t1
, 8);
3561 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3562 tcg_gen_or_i32(rm
, rm
, tmp
);
3563 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3564 tcg_gen_or_i32(t1
, rm
, tmp
);
3565 tcg_gen_mov_i32(t0
, rd
);
3572 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3580 tcg_gen_andi_i32(rd
, t0
, 0xff);
3581 tcg_gen_shli_i32(tmp
, t1
, 8);
3582 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3583 tcg_gen_or_i32(rd
, rd
, tmp
);
3584 tcg_gen_shli_i32(tmp
, t0
, 16);
3585 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3586 tcg_gen_or_i32(rd
, rd
, tmp
);
3587 tcg_gen_shli_i32(tmp
, t1
, 24);
3588 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3589 tcg_gen_or_i32(rd
, rd
, tmp
);
3591 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3592 tcg_gen_shri_i32(tmp
, t0
, 8);
3593 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3594 tcg_gen_or_i32(rm
, rm
, tmp
);
3595 tcg_gen_shri_i32(tmp
, t1
, 8);
3596 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3597 tcg_gen_or_i32(rm
, rm
, tmp
);
3598 tcg_gen_shri_i32(tmp
, t0
, 16);
3599 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3600 tcg_gen_or_i32(t1
, rm
, tmp
);
3601 tcg_gen_mov_i32(t0
, rd
);
3608 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3615 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3616 tcg_gen_shli_i32(tmp2
, t1
, 16);
3617 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3618 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3619 tcg_gen_shri_i32(tmp2
, t0
, 16);
3620 tcg_gen_or_i32(t1
, t1
, tmp2
);
3621 tcg_gen_mov_i32(t0
, tmp
);
3627 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3632 for (n
= 0; n
< q
+ 1; n
+= 2) {
3633 t0
= neon_load_reg(reg
, n
);
3634 t1
= neon_load_reg(reg
, n
+ 1);
3636 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3637 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3638 case 2: /* no-op */; break;
3641 neon_store_scratch(tmp
+ n
, t0
);
3642 neon_store_scratch(tmp
+ n
+ 1, t1
);
3646 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3653 tcg_gen_shli_i32(rd
, t0
, 8);
3654 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3655 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3656 tcg_gen_or_i32(rd
, rd
, tmp
);
3658 tcg_gen_shri_i32(t1
, t1
, 8);
3659 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3660 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3661 tcg_gen_or_i32(t1
, t1
, tmp
);
3662 tcg_gen_mov_i32(t0
, rd
);
3668 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3675 tcg_gen_shli_i32(rd
, t0
, 16);
3676 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3677 tcg_gen_or_i32(rd
, rd
, tmp
);
3678 tcg_gen_shri_i32(t1
, t1
, 16);
3679 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3680 tcg_gen_or_i32(t1
, t1
, tmp
);
3681 tcg_gen_mov_i32(t0
, rd
);
3692 } neon_ls_element_type
[11] = {
3706 /* Translate a NEON load/store element instruction. Return nonzero if the
3707 instruction is invalid. */
3708 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3727 if (!vfp_enabled(env
))
3729 VFP_DREG_D(rd
, insn
);
3730 rn
= (insn
>> 16) & 0xf;
3732 load
= (insn
& (1 << 21)) != 0;
3734 if ((insn
& (1 << 23)) == 0) {
3735 /* Load store all elements. */
3736 op
= (insn
>> 8) & 0xf;
3737 size
= (insn
>> 6) & 3;
3740 nregs
= neon_ls_element_type
[op
].nregs
;
3741 interleave
= neon_ls_element_type
[op
].interleave
;
3742 spacing
= neon_ls_element_type
[op
].spacing
;
3743 if (size
== 3 && (interleave
| spacing
) != 1)
3745 load_reg_var(s
, addr
, rn
);
3746 stride
= (1 << size
) * interleave
;
3747 for (reg
= 0; reg
< nregs
; reg
++) {
3748 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3749 load_reg_var(s
, addr
, rn
);
3750 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3751 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3752 load_reg_var(s
, addr
, rn
);
3753 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3757 tmp64
= gen_ld64(addr
, IS_USER(s
));
3758 neon_store_reg64(tmp64
, rd
);
3759 tcg_temp_free_i64(tmp64
);
3761 tmp64
= tcg_temp_new_i64();
3762 neon_load_reg64(tmp64
, rd
);
3763 gen_st64(tmp64
, addr
, IS_USER(s
));
3765 tcg_gen_addi_i32(addr
, addr
, stride
);
3767 for (pass
= 0; pass
< 2; pass
++) {
3770 tmp
= gen_ld32(addr
, IS_USER(s
));
3771 neon_store_reg(rd
, pass
, tmp
);
3773 tmp
= neon_load_reg(rd
, pass
);
3774 gen_st32(tmp
, addr
, IS_USER(s
));
3776 tcg_gen_addi_i32(addr
, addr
, stride
);
3777 } else if (size
== 1) {
3779 tmp
= gen_ld16u(addr
, IS_USER(s
));
3780 tcg_gen_addi_i32(addr
, addr
, stride
);
3781 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3782 tcg_gen_addi_i32(addr
, addr
, stride
);
3783 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3785 neon_store_reg(rd
, pass
, tmp
);
3787 tmp
= neon_load_reg(rd
, pass
);
3789 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3790 gen_st16(tmp
, addr
, IS_USER(s
));
3791 tcg_gen_addi_i32(addr
, addr
, stride
);
3792 gen_st16(tmp2
, addr
, IS_USER(s
));
3793 tcg_gen_addi_i32(addr
, addr
, stride
);
3795 } else /* size == 0 */ {
3798 for (n
= 0; n
< 4; n
++) {
3799 tmp
= gen_ld8u(addr
, IS_USER(s
));
3800 tcg_gen_addi_i32(addr
, addr
, stride
);
3804 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3808 neon_store_reg(rd
, pass
, tmp2
);
3810 tmp2
= neon_load_reg(rd
, pass
);
3811 for (n
= 0; n
< 4; n
++) {
3814 tcg_gen_mov_i32(tmp
, tmp2
);
3816 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3818 gen_st8(tmp
, addr
, IS_USER(s
));
3819 tcg_gen_addi_i32(addr
, addr
, stride
);
3830 size
= (insn
>> 10) & 3;
3832 /* Load single element to all lanes. */
3835 size
= (insn
>> 6) & 3;
3836 nregs
= ((insn
>> 8) & 3) + 1;
3837 stride
= (insn
& (1 << 5)) ? 2 : 1;
3838 load_reg_var(s
, addr
, rn
);
3839 for (reg
= 0; reg
< nregs
; reg
++) {
3842 tmp
= gen_ld8u(addr
, IS_USER(s
));
3843 gen_neon_dup_u8(tmp
, 0);
3846 tmp
= gen_ld16u(addr
, IS_USER(s
));
3847 gen_neon_dup_low16(tmp
);
3850 tmp
= gen_ld32(addr
, IS_USER(s
));
3854 default: /* Avoid compiler warnings. */
3857 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3859 tcg_gen_mov_i32(tmp2
, tmp
);
3860 neon_store_reg(rd
, 0, tmp2
);
3861 neon_store_reg(rd
, 1, tmp
);
3864 stride
= (1 << size
) * nregs
;
3866 /* Single element. */
3867 pass
= (insn
>> 7) & 1;
3870 shift
= ((insn
>> 5) & 3) * 8;
3874 shift
= ((insn
>> 6) & 1) * 16;
3875 stride
= (insn
& (1 << 5)) ? 2 : 1;
3879 stride
= (insn
& (1 << 6)) ? 2 : 1;
3884 nregs
= ((insn
>> 8) & 3) + 1;
3885 load_reg_var(s
, addr
, rn
);
3886 for (reg
= 0; reg
< nregs
; reg
++) {
3890 tmp
= gen_ld8u(addr
, IS_USER(s
));
3893 tmp
= gen_ld16u(addr
, IS_USER(s
));
3896 tmp
= gen_ld32(addr
, IS_USER(s
));
3898 default: /* Avoid compiler warnings. */
3902 tmp2
= neon_load_reg(rd
, pass
);
3903 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3906 neon_store_reg(rd
, pass
, tmp
);
3907 } else { /* Store */
3908 tmp
= neon_load_reg(rd
, pass
);
3910 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3913 gen_st8(tmp
, addr
, IS_USER(s
));
3916 gen_st16(tmp
, addr
, IS_USER(s
));
3919 gen_st32(tmp
, addr
, IS_USER(s
));
3924 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3926 stride
= nregs
* (1 << size
);
3933 base
= load_reg(s
, rn
);
3935 tcg_gen_addi_i32(base
, base
, stride
);
3938 index
= load_reg(s
, rm
);
3939 tcg_gen_add_i32(base
, base
, index
);
3942 store_reg(s
, rn
, base
);
3947 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3948 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3950 tcg_gen_and_i32(t
, t
, c
);
3951 tcg_gen_andc_i32(f
, f
, c
);
3952 tcg_gen_or_i32(dest
, t
, f
);
3955 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3958 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3959 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3960 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3965 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3968 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3969 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3970 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3975 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3978 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3979 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3980 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3985 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3991 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3992 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3997 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3998 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4005 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4006 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4011 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4012 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4019 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4023 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4024 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4025 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4030 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4031 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4032 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4039 static inline void gen_neon_addl(int size
)
4042 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4043 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4044 case 2: tcg_gen_add_i64(CPU_V001
); break;
4049 static inline void gen_neon_subl(int size
)
4052 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4053 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4054 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4059 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4062 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4063 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4064 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4069 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4072 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4073 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4078 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4082 switch ((size
<< 1) | u
) {
4083 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4084 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4085 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4086 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4088 tmp
= gen_muls_i64_i32(a
, b
);
4089 tcg_gen_mov_i64(dest
, tmp
);
4092 tmp
= gen_mulu_i64_i32(a
, b
);
4093 tcg_gen_mov_i64(dest
, tmp
);
4099 /* Translate a NEON data processing instruction. Return nonzero if the
4100 instruction is invalid.
4101 We process data in a mixture of 32-bit and 64-bit chunks.
4102 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4104 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4117 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4120 if (!vfp_enabled(env
))
4122 q
= (insn
& (1 << 6)) != 0;
4123 u
= (insn
>> 24) & 1;
4124 VFP_DREG_D(rd
, insn
);
4125 VFP_DREG_N(rn
, insn
);
4126 VFP_DREG_M(rm
, insn
);
4127 size
= (insn
>> 20) & 3;
4128 if ((insn
& (1 << 23)) == 0) {
4129 /* Three register same length. */
4130 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4131 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4132 || op
== 10 || op
== 11 || op
== 16)) {
4133 /* 64-bit element instructions. */
4134 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4135 neon_load_reg64(cpu_V0
, rn
+ pass
);
4136 neon_load_reg64(cpu_V1
, rm
+ pass
);
4140 gen_helper_neon_add_saturate_u64(CPU_V001
);
4142 gen_helper_neon_add_saturate_s64(CPU_V001
);
4147 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4149 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4154 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4156 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4161 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4164 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4168 case 10: /* VRSHL */
4170 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4172 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4175 case 11: /* VQRSHL */
4177 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4180 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4186 tcg_gen_sub_i64(CPU_V001
);
4188 tcg_gen_add_i64(CPU_V001
);
4194 neon_store_reg64(cpu_V0
, rd
+ pass
);
4201 case 10: /* VRSHL */
4202 case 11: /* VQRSHL */
4205 /* Shift instruction operands are reversed. */
4212 case 20: /* VPMAX */
4213 case 21: /* VPMIN */
4214 case 23: /* VPADD */
4217 case 26: /* VPADD (float) */
4218 pairwise
= (u
&& size
< 2);
4220 case 30: /* VPMIN/VPMAX (float) */
4228 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4237 tmp
= neon_load_reg(rn
, n
);
4238 tmp2
= neon_load_reg(rn
, n
+ 1);
4240 tmp
= neon_load_reg(rm
, n
);
4241 tmp2
= neon_load_reg(rm
, n
+ 1);
4245 tmp
= neon_load_reg(rn
, pass
);
4246 tmp2
= neon_load_reg(rm
, pass
);
4250 GEN_NEON_INTEGER_OP(hadd
);
4253 GEN_NEON_INTEGER_OP_ENV(qadd
);
4255 case 2: /* VRHADD */
4256 GEN_NEON_INTEGER_OP(rhadd
);
4258 case 3: /* Logic ops. */
4259 switch ((u
<< 2) | size
) {
4261 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4264 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4267 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4270 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4273 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4276 tmp3
= neon_load_reg(rd
, pass
);
4277 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4281 tmp3
= neon_load_reg(rd
, pass
);
4282 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4286 tmp3
= neon_load_reg(rd
, pass
);
4287 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4293 GEN_NEON_INTEGER_OP(hsub
);
4296 GEN_NEON_INTEGER_OP_ENV(qsub
);
4299 GEN_NEON_INTEGER_OP(cgt
);
4302 GEN_NEON_INTEGER_OP(cge
);
4305 GEN_NEON_INTEGER_OP(shl
);
4308 GEN_NEON_INTEGER_OP_ENV(qshl
);
4310 case 10: /* VRSHL */
4311 GEN_NEON_INTEGER_OP(rshl
);
4313 case 11: /* VQRSHL */
4314 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4317 GEN_NEON_INTEGER_OP(max
);
4320 GEN_NEON_INTEGER_OP(min
);
4323 GEN_NEON_INTEGER_OP(abd
);
4326 GEN_NEON_INTEGER_OP(abd
);
4328 tmp2
= neon_load_reg(rd
, pass
);
4329 gen_neon_add(size
, tmp
, tmp2
);
4332 if (!u
) { /* VADD */
4333 if (gen_neon_add(size
, tmp
, tmp2
))
4337 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4338 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4339 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4345 if (!u
) { /* VTST */
4347 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4348 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4349 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4354 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4355 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4356 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4361 case 18: /* Multiply. */
4363 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4364 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4365 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4369 tmp2
= neon_load_reg(rd
, pass
);
4371 gen_neon_rsb(size
, tmp
, tmp2
);
4373 gen_neon_add(size
, tmp
, tmp2
);
4377 if (u
) { /* polynomial */
4378 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4379 } else { /* Integer */
4381 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4382 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4383 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4388 case 20: /* VPMAX */
4389 GEN_NEON_INTEGER_OP(pmax
);
4391 case 21: /* VPMIN */
4392 GEN_NEON_INTEGER_OP(pmin
);
4394 case 22: /* Hultiply high. */
4395 if (!u
) { /* VQDMULH */
4397 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4398 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4401 } else { /* VQRDHMUL */
4403 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4404 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4409 case 23: /* VPADD */
4413 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4414 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4415 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4419 case 26: /* Floating point arithnetic. */
4420 switch ((u
<< 2) | size
) {
4422 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4425 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4428 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4431 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4437 case 27: /* Float multiply. */
4438 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4441 tmp2
= neon_load_reg(rd
, pass
);
4443 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4445 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4449 case 28: /* Float compare. */
4451 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4454 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4456 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4459 case 29: /* Float compare absolute. */
4463 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4465 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4467 case 30: /* Float min/max. */
4469 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4471 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4475 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4477 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4484 /* Save the result. For elementwise operations we can put it
4485 straight into the destination register. For pairwise operations
4486 we have to be careful to avoid clobbering the source operands. */
4487 if (pairwise
&& rd
== rm
) {
4488 neon_store_scratch(pass
, tmp
);
4490 neon_store_reg(rd
, pass
, tmp
);
4494 if (pairwise
&& rd
== rm
) {
4495 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4496 tmp
= neon_load_scratch(pass
);
4497 neon_store_reg(rd
, pass
, tmp
);
4500 /* End of 3 register same size operations. */
4501 } else if (insn
& (1 << 4)) {
4502 if ((insn
& 0x00380080) != 0) {
4503 /* Two registers and shift. */
4504 op
= (insn
>> 8) & 0xf;
4505 if (insn
& (1 << 7)) {
4510 while ((insn
& (1 << (size
+ 19))) == 0)
4513 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4514 /* To avoid excessive dumplication of ops we implement shift
4515 by immediate using the variable shift operations. */
4517 /* Shift by immediate:
4518 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4519 /* Right shifts are encoded as N - shift, where N is the
4520 element size in bits. */
4522 shift
= shift
- (1 << (size
+ 3));
4530 imm
= (uint8_t) shift
;
4535 imm
= (uint16_t) shift
;
4546 for (pass
= 0; pass
< count
; pass
++) {
4548 neon_load_reg64(cpu_V0
, rm
+ pass
);
4549 tcg_gen_movi_i64(cpu_V1
, imm
);
4554 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4556 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4561 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4563 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4568 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4570 case 5: /* VSHL, VSLI */
4571 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4575 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4577 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4579 case 7: /* VQSHLU */
4580 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4583 if (op
== 1 || op
== 3) {
4585 neon_load_reg64(cpu_V0
, rd
+ pass
);
4586 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4587 } else if (op
== 4 || (op
== 5 && u
)) {
4589 cpu_abort(env
, "VS[LR]I.64 not implemented");
4591 neon_store_reg64(cpu_V0
, rd
+ pass
);
4592 } else { /* size < 3 */
4593 /* Operands in T0 and T1. */
4594 tmp
= neon_load_reg(rm
, pass
);
4596 tcg_gen_movi_i32(tmp2
, imm
);
4600 GEN_NEON_INTEGER_OP(shl
);
4604 GEN_NEON_INTEGER_OP(rshl
);
4609 GEN_NEON_INTEGER_OP(shl
);
4611 case 5: /* VSHL, VSLI */
4613 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4614 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4615 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4620 GEN_NEON_INTEGER_OP_ENV(qshl
);
4622 case 7: /* VQSHLU */
4624 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4625 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4626 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4633 if (op
== 1 || op
== 3) {
4635 tmp2
= neon_load_reg(rd
, pass
);
4636 gen_neon_add(size
, tmp2
, tmp
);
4638 } else if (op
== 4 || (op
== 5 && u
)) {
4643 mask
= 0xff >> -shift
;
4645 mask
= (uint8_t)(0xff << shift
);
4651 mask
= 0xffff >> -shift
;
4653 mask
= (uint16_t)(0xffff << shift
);
4657 if (shift
< -31 || shift
> 31) {
4661 mask
= 0xffffffffu
>> -shift
;
4663 mask
= 0xffffffffu
<< shift
;
4669 tmp2
= neon_load_reg(rd
, pass
);
4670 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4671 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4672 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4675 neon_store_reg(rd
, pass
, tmp
);
4678 } else if (op
< 10) {
4679 /* Shift by immediate and narrow:
4680 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4681 shift
= shift
- (1 << (size
+ 3));
4685 imm
= (uint16_t)shift
;
4687 tmp2
= tcg_const_i32(imm
);
4688 TCGV_UNUSED_I64(tmp64
);
4691 imm
= (uint32_t)shift
;
4692 tmp2
= tcg_const_i32(imm
);
4693 TCGV_UNUSED_I64(tmp64
);
4696 tmp64
= tcg_const_i64(shift
);
4703 for (pass
= 0; pass
< 2; pass
++) {
4705 neon_load_reg64(cpu_V0
, rm
+ pass
);
4708 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4710 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4713 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4715 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4718 tmp
= neon_load_reg(rm
+ pass
, 0);
4719 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4720 tmp3
= neon_load_reg(rm
+ pass
, 1);
4721 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4722 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4727 if (op
== 8 && !u
) {
4728 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4731 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4733 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4735 neon_store_reg(rd
, pass
, tmp
);
4738 tcg_temp_free_i64(tmp64
);
4742 } else if (op
== 10) {
4746 tmp
= neon_load_reg(rm
, 0);
4747 tmp2
= neon_load_reg(rm
, 1);
4748 for (pass
= 0; pass
< 2; pass
++) {
4752 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4755 /* The shift is less than the width of the source
4756 type, so we can just shift the whole register. */
4757 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4758 if (size
< 2 || !u
) {
4761 imm
= (0xffu
>> (8 - shift
));
4764 imm
= 0xffff >> (16 - shift
);
4766 imm64
= imm
| (((uint64_t)imm
) << 32);
4767 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4770 neon_store_reg64(cpu_V0
, rd
+ pass
);
4772 } else if (op
== 15 || op
== 16) {
4773 /* VCVT fixed-point. */
4774 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4775 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4778 gen_vfp_ulto(0, shift
);
4780 gen_vfp_slto(0, shift
);
4783 gen_vfp_toul(0, shift
);
4785 gen_vfp_tosl(0, shift
);
4787 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4792 } else { /* (insn & 0x00380080) == 0 */
4795 op
= (insn
>> 8) & 0xf;
4796 /* One register and immediate. */
4797 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4798 invert
= (insn
& (1 << 5)) != 0;
4816 imm
= (imm
<< 8) | (imm
<< 24);
4819 imm
= (imm
< 8) | 0xff;
4822 imm
= (imm
<< 16) | 0xffff;
4825 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4830 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4831 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4837 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4838 if (op
& 1 && op
< 12) {
4839 tmp
= neon_load_reg(rd
, pass
);
4841 /* The immediate value has already been inverted, so
4843 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4845 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4850 if (op
== 14 && invert
) {
4853 for (n
= 0; n
< 4; n
++) {
4854 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4855 val
|= 0xff << (n
* 8);
4857 tcg_gen_movi_i32(tmp
, val
);
4859 tcg_gen_movi_i32(tmp
, imm
);
4862 neon_store_reg(rd
, pass
, tmp
);
4865 } else { /* (insn & 0x00800010 == 0x00800000) */
4867 op
= (insn
>> 8) & 0xf;
4868 if ((insn
& (1 << 6)) == 0) {
4869 /* Three registers of different lengths. */
4873 /* prewiden, src1_wide, src2_wide */
4874 static const int neon_3reg_wide
[16][3] = {
4875 {1, 0, 0}, /* VADDL */
4876 {1, 1, 0}, /* VADDW */
4877 {1, 0, 0}, /* VSUBL */
4878 {1, 1, 0}, /* VSUBW */
4879 {0, 1, 1}, /* VADDHN */
4880 {0, 0, 0}, /* VABAL */
4881 {0, 1, 1}, /* VSUBHN */
4882 {0, 0, 0}, /* VABDL */
4883 {0, 0, 0}, /* VMLAL */
4884 {0, 0, 0}, /* VQDMLAL */
4885 {0, 0, 0}, /* VMLSL */
4886 {0, 0, 0}, /* VQDMLSL */
4887 {0, 0, 0}, /* Integer VMULL */
4888 {0, 0, 0}, /* VQDMULL */
4889 {0, 0, 0} /* Polynomial VMULL */
4892 prewiden
= neon_3reg_wide
[op
][0];
4893 src1_wide
= neon_3reg_wide
[op
][1];
4894 src2_wide
= neon_3reg_wide
[op
][2];
4896 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4899 /* Avoid overlapping operands. Wide source operands are
4900 always aligned so will never overlap with wide
4901 destinations in problematic ways. */
4902 if (rd
== rm
&& !src2_wide
) {
4903 tmp
= neon_load_reg(rm
, 1);
4904 neon_store_scratch(2, tmp
);
4905 } else if (rd
== rn
&& !src1_wide
) {
4906 tmp
= neon_load_reg(rn
, 1);
4907 neon_store_scratch(2, tmp
);
4910 for (pass
= 0; pass
< 2; pass
++) {
4912 neon_load_reg64(cpu_V0
, rn
+ pass
);
4915 if (pass
== 1 && rd
== rn
) {
4916 tmp
= neon_load_scratch(2);
4918 tmp
= neon_load_reg(rn
, pass
);
4921 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4925 neon_load_reg64(cpu_V1
, rm
+ pass
);
4928 if (pass
== 1 && rd
== rm
) {
4929 tmp2
= neon_load_scratch(2);
4931 tmp2
= neon_load_reg(rm
, pass
);
4934 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4938 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4939 gen_neon_addl(size
);
4941 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4942 gen_neon_subl(size
);
4944 case 5: case 7: /* VABAL, VABDL */
4945 switch ((size
<< 1) | u
) {
4947 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4950 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4953 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4956 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4959 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4962 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4969 case 8: case 9: case 10: case 11: case 12: case 13:
4970 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4971 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4975 case 14: /* Polynomial VMULL */
4976 cpu_abort(env
, "Polynomial VMULL not implemented");
4978 default: /* 15 is RESERVED. */
4981 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4983 if (op
== 10 || op
== 11) {
4984 gen_neon_negl(cpu_V0
, size
);
4988 neon_load_reg64(cpu_V1
, rd
+ pass
);
4992 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4993 gen_neon_addl(size
);
4995 case 9: case 11: /* VQDMLAL, VQDMLSL */
4996 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4997 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5000 case 13: /* VQDMULL */
5001 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5006 neon_store_reg64(cpu_V0
, rd
+ pass
);
5007 } else if (op
== 4 || op
== 6) {
5008 /* Narrowing operation. */
5013 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5016 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5019 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5020 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5027 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5030 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5033 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5034 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5035 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5043 neon_store_reg(rd
, 0, tmp3
);
5044 neon_store_reg(rd
, 1, tmp
);
5047 /* Write back the result. */
5048 neon_store_reg64(cpu_V0
, rd
+ pass
);
5052 /* Two registers and a scalar. */
5054 case 0: /* Integer VMLA scalar */
5055 case 1: /* Float VMLA scalar */
5056 case 4: /* Integer VMLS scalar */
5057 case 5: /* Floating point VMLS scalar */
5058 case 8: /* Integer VMUL scalar */
5059 case 9: /* Floating point VMUL scalar */
5060 case 12: /* VQDMULH scalar */
5061 case 13: /* VQRDMULH scalar */
5062 tmp
= neon_get_scalar(size
, rm
);
5063 neon_store_scratch(0, tmp
);
5064 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5065 tmp
= neon_load_scratch(0);
5066 tmp2
= neon_load_reg(rn
, pass
);
5069 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5071 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5073 } else if (op
== 13) {
5075 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5077 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5079 } else if (op
& 1) {
5080 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5083 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5084 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5085 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5092 tmp2
= neon_load_reg(rd
, pass
);
5095 gen_neon_add(size
, tmp
, tmp2
);
5098 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5101 gen_neon_rsb(size
, tmp
, tmp2
);
5104 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5111 neon_store_reg(rd
, pass
, tmp
);
5114 case 2: /* VMLAL sclar */
5115 case 3: /* VQDMLAL scalar */
5116 case 6: /* VMLSL scalar */
5117 case 7: /* VQDMLSL scalar */
5118 case 10: /* VMULL scalar */
5119 case 11: /* VQDMULL scalar */
5120 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5123 tmp2
= neon_get_scalar(size
, rm
);
5124 tmp3
= neon_load_reg(rn
, 1);
5126 for (pass
= 0; pass
< 2; pass
++) {
5128 tmp
= neon_load_reg(rn
, 0);
5132 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5134 if (op
== 6 || op
== 7) {
5135 gen_neon_negl(cpu_V0
, size
);
5138 neon_load_reg64(cpu_V1
, rd
+ pass
);
5142 gen_neon_addl(size
);
5145 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5146 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5152 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5157 neon_store_reg64(cpu_V0
, rd
+ pass
);
5163 default: /* 14 and 15 are RESERVED */
5167 } else { /* size == 3 */
5170 imm
= (insn
>> 8) & 0xf;
5177 neon_load_reg64(cpu_V0
, rn
);
5179 neon_load_reg64(cpu_V1
, rn
+ 1);
5181 } else if (imm
== 8) {
5182 neon_load_reg64(cpu_V0
, rn
+ 1);
5184 neon_load_reg64(cpu_V1
, rm
);
5187 tmp64
= tcg_temp_new_i64();
5189 neon_load_reg64(cpu_V0
, rn
);
5190 neon_load_reg64(tmp64
, rn
+ 1);
5192 neon_load_reg64(cpu_V0
, rn
+ 1);
5193 neon_load_reg64(tmp64
, rm
);
5195 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5196 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5197 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5199 neon_load_reg64(cpu_V1
, rm
);
5201 neon_load_reg64(cpu_V1
, rm
+ 1);
5204 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5205 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5206 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5207 tcg_temp_free_i64(tmp64
);
5210 neon_load_reg64(cpu_V0
, rn
);
5211 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5212 neon_load_reg64(cpu_V1
, rm
);
5213 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5214 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5216 neon_store_reg64(cpu_V0
, rd
);
5218 neon_store_reg64(cpu_V1
, rd
+ 1);
5220 } else if ((insn
& (1 << 11)) == 0) {
5221 /* Two register misc. */
5222 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5223 size
= (insn
>> 18) & 3;
5225 case 0: /* VREV64 */
5228 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5229 tmp
= neon_load_reg(rm
, pass
* 2);
5230 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5232 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5233 case 1: gen_swap_half(tmp
); break;
5234 case 2: /* no-op */ break;
5237 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5239 neon_store_reg(rd
, pass
* 2, tmp2
);
5242 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5243 case 1: gen_swap_half(tmp2
); break;
5246 neon_store_reg(rd
, pass
* 2, tmp2
);
5250 case 4: case 5: /* VPADDL */
5251 case 12: case 13: /* VPADAL */
5254 for (pass
= 0; pass
< q
+ 1; pass
++) {
5255 tmp
= neon_load_reg(rm
, pass
* 2);
5256 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5257 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5258 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5260 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5261 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5262 case 2: tcg_gen_add_i64(CPU_V001
); break;
5267 neon_load_reg64(cpu_V1
, rd
+ pass
);
5268 gen_neon_addl(size
);
5270 neon_store_reg64(cpu_V0
, rd
+ pass
);
5275 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5276 tmp
= neon_load_reg(rm
, n
);
5277 tmp2
= neon_load_reg(rd
, n
+ 1);
5278 neon_store_reg(rm
, n
, tmp2
);
5279 neon_store_reg(rd
, n
+ 1, tmp
);
5287 Rd A3 A2 A1 A0 B2 B0 A2 A0
5288 Rm B3 B2 B1 B0 B3 B1 A3 A1
5292 gen_neon_unzip(rd
, q
, 0, size
);
5293 gen_neon_unzip(rm
, q
, 4, size
);
5295 static int unzip_order_q
[8] =
5296 {0, 2, 4, 6, 1, 3, 5, 7};
5297 for (n
= 0; n
< 8; n
++) {
5298 int reg
= (n
< 4) ? rd
: rm
;
5299 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5300 neon_store_reg(reg
, n
% 4, tmp
);
5303 static int unzip_order
[4] =
5305 for (n
= 0; n
< 4; n
++) {
5306 int reg
= (n
< 2) ? rd
: rm
;
5307 tmp
= neon_load_scratch(unzip_order
[n
]);
5308 neon_store_reg(reg
, n
% 2, tmp
);
5314 Rd A3 A2 A1 A0 B1 A1 B0 A0
5315 Rm B3 B2 B1 B0 B3 A3 B2 A2
5319 count
= (q
? 4 : 2);
5320 for (n
= 0; n
< count
; n
++) {
5321 tmp
= neon_load_reg(rd
, n
);
5322 tmp2
= neon_load_reg(rd
, n
);
5324 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5325 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5326 case 2: /* no-op */; break;
5329 neon_store_scratch(n
* 2, tmp
);
5330 neon_store_scratch(n
* 2 + 1, tmp2
);
5332 for (n
= 0; n
< count
* 2; n
++) {
5333 int reg
= (n
< count
) ? rd
: rm
;
5334 tmp
= neon_load_scratch(n
);
5335 neon_store_reg(reg
, n
% count
, tmp
);
5338 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5342 for (pass
= 0; pass
< 2; pass
++) {
5343 neon_load_reg64(cpu_V0
, rm
+ pass
);
5345 if (op
== 36 && q
== 0) {
5346 gen_neon_narrow(size
, tmp
, cpu_V0
);
5348 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5350 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5355 neon_store_reg(rd
, 0, tmp2
);
5356 neon_store_reg(rd
, 1, tmp
);
5360 case 38: /* VSHLL */
5363 tmp
= neon_load_reg(rm
, 0);
5364 tmp2
= neon_load_reg(rm
, 1);
5365 for (pass
= 0; pass
< 2; pass
++) {
5368 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5369 neon_store_reg64(cpu_V0
, rd
+ pass
);
5372 case 44: /* VCVT.F16.F32 */
5373 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5377 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5378 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5379 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5380 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5381 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5382 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5383 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5384 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5385 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5386 neon_store_reg(rd
, 0, tmp2
);
5388 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5389 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5390 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5391 neon_store_reg(rd
, 1, tmp2
);
5394 case 46: /* VCVT.F32.F16 */
5395 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5398 tmp
= neon_load_reg(rm
, 0);
5399 tmp2
= neon_load_reg(rm
, 1);
5400 tcg_gen_ext16u_i32(tmp3
, tmp
);
5401 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5402 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5403 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5404 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5405 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5407 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5408 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5409 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5410 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5411 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5412 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5418 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5419 if (op
== 30 || op
== 31 || op
>= 58) {
5420 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5421 neon_reg_offset(rm
, pass
));
5424 tmp
= neon_load_reg(rm
, pass
);
5427 case 1: /* VREV32 */
5429 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5430 case 1: gen_swap_half(tmp
); break;
5434 case 2: /* VREV16 */
5441 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5442 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5443 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5449 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5450 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5451 case 2: gen_helper_clz(tmp
, tmp
); break;
5458 gen_helper_neon_cnt_u8(tmp
, tmp
);
5463 tcg_gen_not_i32(tmp
, tmp
);
5465 case 14: /* VQABS */
5467 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5468 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5469 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5473 case 15: /* VQNEG */
5475 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5476 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5477 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5481 case 16: case 19: /* VCGT #0, VCLE #0 */
5482 tmp2
= tcg_const_i32(0);
5484 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5485 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5486 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5489 tcg_temp_free(tmp2
);
5491 tcg_gen_not_i32(tmp
, tmp
);
5493 case 17: case 20: /* VCGE #0, VCLT #0 */
5494 tmp2
= tcg_const_i32(0);
5496 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5497 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5498 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5501 tcg_temp_free(tmp2
);
5503 tcg_gen_not_i32(tmp
, tmp
);
5505 case 18: /* VCEQ #0 */
5506 tmp2
= tcg_const_i32(0);
5508 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5509 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5510 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5513 tcg_temp_free(tmp2
);
5517 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5518 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5519 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5526 tmp2
= tcg_const_i32(0);
5527 gen_neon_rsb(size
, tmp
, tmp2
);
5528 tcg_temp_free(tmp2
);
5530 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5531 tmp2
= tcg_const_i32(0);
5532 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5533 tcg_temp_free(tmp2
);
5535 tcg_gen_not_i32(tmp
, tmp
);
5537 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5538 tmp2
= tcg_const_i32(0);
5539 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5540 tcg_temp_free(tmp2
);
5542 tcg_gen_not_i32(tmp
, tmp
);
5544 case 26: /* Float VCEQ #0 */
5545 tmp2
= tcg_const_i32(0);
5546 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5547 tcg_temp_free(tmp2
);
5549 case 30: /* Float VABS */
5552 case 31: /* Float VNEG */
5556 tmp2
= neon_load_reg(rd
, pass
);
5557 neon_store_reg(rm
, pass
, tmp2
);
5560 tmp2
= neon_load_reg(rd
, pass
);
5562 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5563 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5567 neon_store_reg(rm
, pass
, tmp2
);
5569 case 56: /* Integer VRECPE */
5570 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5572 case 57: /* Integer VRSQRTE */
5573 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5575 case 58: /* Float VRECPE */
5576 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5578 case 59: /* Float VRSQRTE */
5579 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5581 case 60: /* VCVT.F32.S32 */
5584 case 61: /* VCVT.F32.U32 */
5587 case 62: /* VCVT.S32.F32 */
5590 case 63: /* VCVT.U32.F32 */
5594 /* Reserved: 21, 29, 39-56 */
5597 if (op
== 30 || op
== 31 || op
>= 58) {
5598 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5599 neon_reg_offset(rd
, pass
));
5601 neon_store_reg(rd
, pass
, tmp
);
5606 } else if ((insn
& (1 << 10)) == 0) {
5608 n
= ((insn
>> 5) & 0x18) + 8;
5609 if (insn
& (1 << 6)) {
5610 tmp
= neon_load_reg(rd
, 0);
5613 tcg_gen_movi_i32(tmp
, 0);
5615 tmp2
= neon_load_reg(rm
, 0);
5616 tmp4
= tcg_const_i32(rn
);
5617 tmp5
= tcg_const_i32(n
);
5618 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5620 if (insn
& (1 << 6)) {
5621 tmp
= neon_load_reg(rd
, 1);
5624 tcg_gen_movi_i32(tmp
, 0);
5626 tmp3
= neon_load_reg(rm
, 1);
5627 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5628 tcg_temp_free_i32(tmp5
);
5629 tcg_temp_free_i32(tmp4
);
5630 neon_store_reg(rd
, 0, tmp2
);
5631 neon_store_reg(rd
, 1, tmp3
);
5633 } else if ((insn
& 0x380) == 0) {
5635 if (insn
& (1 << 19)) {
5636 tmp
= neon_load_reg(rm
, 1);
5638 tmp
= neon_load_reg(rm
, 0);
5640 if (insn
& (1 << 16)) {
5641 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5642 } else if (insn
& (1 << 17)) {
5643 if ((insn
>> 18) & 1)
5644 gen_neon_dup_high16(tmp
);
5646 gen_neon_dup_low16(tmp
);
5648 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5650 tcg_gen_mov_i32(tmp2
, tmp
);
5651 neon_store_reg(rd
, pass
, tmp2
);
5662 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5664 int crn
= (insn
>> 16) & 0xf;
5665 int crm
= insn
& 0xf;
5666 int op1
= (insn
>> 21) & 7;
5667 int op2
= (insn
>> 5) & 7;
5668 int rt
= (insn
>> 12) & 0xf;
5671 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5672 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5676 tmp
= load_cpu_field(teecr
);
5677 store_reg(s
, rt
, tmp
);
5680 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5682 if (IS_USER(s
) && (env
->teecr
& 1))
5684 tmp
= load_cpu_field(teehbr
);
5685 store_reg(s
, rt
, tmp
);
5689 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5690 op1
, crn
, crm
, op2
);
5694 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5696 int crn
= (insn
>> 16) & 0xf;
5697 int crm
= insn
& 0xf;
5698 int op1
= (insn
>> 21) & 7;
5699 int op2
= (insn
>> 5) & 7;
5700 int rt
= (insn
>> 12) & 0xf;
5703 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5704 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5708 tmp
= load_reg(s
, rt
);
5709 gen_helper_set_teecr(cpu_env
, tmp
);
5713 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5715 if (IS_USER(s
) && (env
->teecr
& 1))
5717 tmp
= load_reg(s
, rt
);
5718 store_cpu_field(tmp
, teehbr
);
5722 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5723 op1
, crn
, crm
, op2
);
5727 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5731 cpnum
= (insn
>> 8) & 0xf;
5732 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5733 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5739 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5740 return disas_iwmmxt_insn(env
, s
, insn
);
5741 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5742 return disas_dsp_insn(env
, s
, insn
);
5747 return disas_vfp_insn (env
, s
, insn
);
5749 /* Coprocessors 7-15 are architecturally reserved by ARM.
5750 Unfortunately Intel decided to ignore this. */
5751 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5753 if (insn
& (1 << 20))
5754 return disas_cp14_read(env
, s
, insn
);
5756 return disas_cp14_write(env
, s
, insn
);
5758 return disas_cp15_insn (env
, s
, insn
);
5761 /* Unknown coprocessor. See if the board has hooked it. */
5762 return disas_cp_insn (env
, s
, insn
);
5767 /* Store a 64-bit value to a register pair. Clobbers val. */
5768 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5772 tcg_gen_trunc_i64_i32(tmp
, val
);
5773 store_reg(s
, rlow
, tmp
);
5775 tcg_gen_shri_i64(val
, val
, 32);
5776 tcg_gen_trunc_i64_i32(tmp
, val
);
5777 store_reg(s
, rhigh
, tmp
);
5780 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5781 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5786 /* Load value and extend to 64 bits. */
5787 tmp
= tcg_temp_new_i64();
5788 tmp2
= load_reg(s
, rlow
);
5789 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5791 tcg_gen_add_i64(val
, val
, tmp
);
5792 tcg_temp_free_i64(tmp
);
5795 /* load and add a 64-bit value from a register pair. */
5796 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5802 /* Load 64-bit value rd:rn. */
5803 tmpl
= load_reg(s
, rlow
);
5804 tmph
= load_reg(s
, rhigh
);
5805 tmp
= tcg_temp_new_i64();
5806 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5809 tcg_gen_add_i64(val
, val
, tmp
);
5810 tcg_temp_free_i64(tmp
);
5813 /* Set N and Z flags from a 64-bit value. */
5814 static void gen_logicq_cc(TCGv_i64 val
)
5816 TCGv tmp
= new_tmp();
5817 gen_helper_logicq_cc(tmp
, val
);
5822 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5824 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5831 insn
= ldl_code(s
->pc
);
5834 /* M variants do not implement ARM mode. */
5839 /* Unconditional instructions. */
5840 if (((insn
>> 25) & 7) == 1) {
5841 /* NEON Data processing. */
5842 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5845 if (disas_neon_data_insn(env
, s
, insn
))
5849 if ((insn
& 0x0f100000) == 0x04000000) {
5850 /* NEON load/store. */
5851 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5854 if (disas_neon_ls_insn(env
, s
, insn
))
5858 if ((insn
& 0x0d70f000) == 0x0550f000)
5860 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5863 if (insn
& (1 << 9)) {
5864 /* BE8 mode not implemented. */
5868 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5869 switch ((insn
>> 4) & 0xf) {
5872 gen_helper_clrex(cpu_env
);
5878 /* We don't emulate caches so these are a no-op. */
5883 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5889 op1
= (insn
& 0x1f);
5890 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5891 addr
= load_reg(s
, 13);
5894 tmp
= tcg_const_i32(op1
);
5895 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
5896 tcg_temp_free_i32(tmp
);
5898 i
= (insn
>> 23) & 3;
5900 case 0: offset
= -4; break; /* DA */
5901 case 1: offset
= 0; break; /* IA */
5902 case 2: offset
= -8; break; /* DB */
5903 case 3: offset
= 4; break; /* IB */
5907 tcg_gen_addi_i32(addr
, addr
, offset
);
5908 tmp
= load_reg(s
, 14);
5909 gen_st32(tmp
, addr
, 0);
5910 tmp
= load_cpu_field(spsr
);
5911 tcg_gen_addi_i32(addr
, addr
, 4);
5912 gen_st32(tmp
, addr
, 0);
5913 if (insn
& (1 << 21)) {
5914 /* Base writeback. */
5916 case 0: offset
= -8; break;
5917 case 1: offset
= 4; break;
5918 case 2: offset
= -4; break;
5919 case 3: offset
= 0; break;
5923 tcg_gen_addi_i32(addr
, addr
, offset
);
5924 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5925 store_reg(s
, 13, addr
);
5927 tmp
= tcg_const_i32(op1
);
5928 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
5929 tcg_temp_free_i32(tmp
);
5935 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5941 rn
= (insn
>> 16) & 0xf;
5942 addr
= load_reg(s
, rn
);
5943 i
= (insn
>> 23) & 3;
5945 case 0: offset
= -4; break; /* DA */
5946 case 1: offset
= 0; break; /* IA */
5947 case 2: offset
= -8; break; /* DB */
5948 case 3: offset
= 4; break; /* IB */
5952 tcg_gen_addi_i32(addr
, addr
, offset
);
5953 /* Load PC into tmp and CPSR into tmp2. */
5954 tmp
= gen_ld32(addr
, 0);
5955 tcg_gen_addi_i32(addr
, addr
, 4);
5956 tmp2
= gen_ld32(addr
, 0);
5957 if (insn
& (1 << 21)) {
5958 /* Base writeback. */
5960 case 0: offset
= -8; break;
5961 case 1: offset
= 4; break;
5962 case 2: offset
= -4; break;
5963 case 3: offset
= 0; break;
5967 tcg_gen_addi_i32(addr
, addr
, offset
);
5968 store_reg(s
, rn
, addr
);
5972 gen_rfe(s
, tmp
, tmp2
);
5974 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5975 /* branch link and change to thumb (blx <offset>) */
5978 val
= (uint32_t)s
->pc
;
5980 tcg_gen_movi_i32(tmp
, val
);
5981 store_reg(s
, 14, tmp
);
5982 /* Sign-extend the 24-bit offset */
5983 offset
= (((int32_t)insn
) << 8) >> 8;
5984 /* offset * 4 + bit24 * 2 + (thumb bit) */
5985 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5986 /* pipeline offset */
5990 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5991 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5992 /* iWMMXt register transfer. */
5993 if (env
->cp15
.c15_cpar
& (1 << 1))
5994 if (!disas_iwmmxt_insn(env
, s
, insn
))
5997 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5998 /* Coprocessor double register transfer. */
5999 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6000 /* Additional coprocessor register transfer. */
6001 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6004 /* cps (privileged) */
6008 if (insn
& (1 << 19)) {
6009 if (insn
& (1 << 8))
6011 if (insn
& (1 << 7))
6013 if (insn
& (1 << 6))
6015 if (insn
& (1 << 18))
6018 if (insn
& (1 << 17)) {
6020 val
|= (insn
& 0x1f);
6023 gen_set_psr_im(s
, mask
, 0, val
);
6030 /* if not always execute, we generate a conditional jump to
6032 s
->condlabel
= gen_new_label();
6033 gen_test_cc(cond
^ 1, s
->condlabel
);
6036 if ((insn
& 0x0f900000) == 0x03000000) {
6037 if ((insn
& (1 << 21)) == 0) {
6039 rd
= (insn
>> 12) & 0xf;
6040 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6041 if ((insn
& (1 << 22)) == 0) {
6044 tcg_gen_movi_i32(tmp
, val
);
6047 tmp
= load_reg(s
, rd
);
6048 tcg_gen_ext16u_i32(tmp
, tmp
);
6049 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6051 store_reg(s
, rd
, tmp
);
6053 if (((insn
>> 12) & 0xf) != 0xf)
6055 if (((insn
>> 16) & 0xf) == 0) {
6056 gen_nop_hint(s
, insn
& 0xff);
6058 /* CPSR = immediate */
6060 shift
= ((insn
>> 8) & 0xf) * 2;
6062 val
= (val
>> shift
) | (val
<< (32 - shift
));
6063 i
= ((insn
& (1 << 22)) != 0);
6064 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6068 } else if ((insn
& 0x0f900000) == 0x01000000
6069 && (insn
& 0x00000090) != 0x00000090) {
6070 /* miscellaneous instructions */
6071 op1
= (insn
>> 21) & 3;
6072 sh
= (insn
>> 4) & 0xf;
6075 case 0x0: /* move program status register */
6078 tmp
= load_reg(s
, rm
);
6079 i
= ((op1
& 2) != 0);
6080 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6084 rd
= (insn
>> 12) & 0xf;
6088 tmp
= load_cpu_field(spsr
);
6091 gen_helper_cpsr_read(tmp
);
6093 store_reg(s
, rd
, tmp
);
6098 /* branch/exchange thumb (bx). */
6099 tmp
= load_reg(s
, rm
);
6101 } else if (op1
== 3) {
6103 rd
= (insn
>> 12) & 0xf;
6104 tmp
= load_reg(s
, rm
);
6105 gen_helper_clz(tmp
, tmp
);
6106 store_reg(s
, rd
, tmp
);
6114 /* Trivial implementation equivalent to bx. */
6115 tmp
= load_reg(s
, rm
);
6125 /* branch link/exchange thumb (blx) */
6126 tmp
= load_reg(s
, rm
);
6128 tcg_gen_movi_i32(tmp2
, s
->pc
);
6129 store_reg(s
, 14, tmp2
);
6132 case 0x5: /* saturating add/subtract */
6133 rd
= (insn
>> 12) & 0xf;
6134 rn
= (insn
>> 16) & 0xf;
6135 tmp
= load_reg(s
, rm
);
6136 tmp2
= load_reg(s
, rn
);
6138 gen_helper_double_saturate(tmp2
, tmp2
);
6140 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6142 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6144 store_reg(s
, rd
, tmp
);
6147 gen_set_condexec(s
);
6148 gen_set_pc_im(s
->pc
- 4);
6149 gen_exception(EXCP_BKPT
);
6150 s
->is_jmp
= DISAS_JUMP
;
6152 case 0x8: /* signed multiply */
6156 rs
= (insn
>> 8) & 0xf;
6157 rn
= (insn
>> 12) & 0xf;
6158 rd
= (insn
>> 16) & 0xf;
6160 /* (32 * 16) >> 16 */
6161 tmp
= load_reg(s
, rm
);
6162 tmp2
= load_reg(s
, rs
);
6164 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6167 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6168 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6170 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6171 tcg_temp_free_i64(tmp64
);
6172 if ((sh
& 2) == 0) {
6173 tmp2
= load_reg(s
, rn
);
6174 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6177 store_reg(s
, rd
, tmp
);
6180 tmp
= load_reg(s
, rm
);
6181 tmp2
= load_reg(s
, rs
);
6182 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6185 tmp64
= tcg_temp_new_i64();
6186 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6188 gen_addq(s
, tmp64
, rn
, rd
);
6189 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6190 tcg_temp_free_i64(tmp64
);
6193 tmp2
= load_reg(s
, rn
);
6194 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6197 store_reg(s
, rd
, tmp
);
6204 } else if (((insn
& 0x0e000000) == 0 &&
6205 (insn
& 0x00000090) != 0x90) ||
6206 ((insn
& 0x0e000000) == (1 << 25))) {
6207 int set_cc
, logic_cc
, shiftop
;
6209 op1
= (insn
>> 21) & 0xf;
6210 set_cc
= (insn
>> 20) & 1;
6211 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6213 /* data processing instruction */
6214 if (insn
& (1 << 25)) {
6215 /* immediate operand */
6217 shift
= ((insn
>> 8) & 0xf) * 2;
6219 val
= (val
>> shift
) | (val
<< (32 - shift
));
6222 tcg_gen_movi_i32(tmp2
, val
);
6223 if (logic_cc
&& shift
) {
6224 gen_set_CF_bit31(tmp2
);
6229 tmp2
= load_reg(s
, rm
);
6230 shiftop
= (insn
>> 5) & 3;
6231 if (!(insn
& (1 << 4))) {
6232 shift
= (insn
>> 7) & 0x1f;
6233 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6235 rs
= (insn
>> 8) & 0xf;
6236 tmp
= load_reg(s
, rs
);
6237 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6240 if (op1
!= 0x0f && op1
!= 0x0d) {
6241 rn
= (insn
>> 16) & 0xf;
6242 tmp
= load_reg(s
, rn
);
6246 rd
= (insn
>> 12) & 0xf;
6249 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6253 store_reg_bx(env
, s
, rd
, tmp
);
6256 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6260 store_reg_bx(env
, s
, rd
, tmp
);
6263 if (set_cc
&& rd
== 15) {
6264 /* SUBS r15, ... is used for exception return. */
6268 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6269 gen_exception_return(s
, tmp
);
6272 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6274 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6276 store_reg_bx(env
, s
, rd
, tmp
);
6281 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6283 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6285 store_reg_bx(env
, s
, rd
, tmp
);
6289 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6291 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6293 store_reg_bx(env
, s
, rd
, tmp
);
6297 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6299 gen_add_carry(tmp
, tmp
, tmp2
);
6301 store_reg_bx(env
, s
, rd
, tmp
);
6305 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6307 gen_sub_carry(tmp
, tmp
, tmp2
);
6309 store_reg_bx(env
, s
, rd
, tmp
);
6313 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6315 gen_sub_carry(tmp
, tmp2
, tmp
);
6317 store_reg_bx(env
, s
, rd
, tmp
);
6321 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6328 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6335 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6341 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6346 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6350 store_reg_bx(env
, s
, rd
, tmp
);
6353 if (logic_cc
&& rd
== 15) {
6354 /* MOVS r15, ... is used for exception return. */
6358 gen_exception_return(s
, tmp2
);
6363 store_reg_bx(env
, s
, rd
, tmp2
);
6367 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6371 store_reg_bx(env
, s
, rd
, tmp
);
6375 tcg_gen_not_i32(tmp2
, tmp2
);
6379 store_reg_bx(env
, s
, rd
, tmp2
);
6382 if (op1
!= 0x0f && op1
!= 0x0d) {
6386 /* other instructions */
6387 op1
= (insn
>> 24) & 0xf;
6391 /* multiplies, extra load/stores */
6392 sh
= (insn
>> 5) & 3;
6395 rd
= (insn
>> 16) & 0xf;
6396 rn
= (insn
>> 12) & 0xf;
6397 rs
= (insn
>> 8) & 0xf;
6399 op1
= (insn
>> 20) & 0xf;
6401 case 0: case 1: case 2: case 3: case 6:
6403 tmp
= load_reg(s
, rs
);
6404 tmp2
= load_reg(s
, rm
);
6405 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6407 if (insn
& (1 << 22)) {
6408 /* Subtract (mls) */
6410 tmp2
= load_reg(s
, rn
);
6411 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6413 } else if (insn
& (1 << 21)) {
6415 tmp2
= load_reg(s
, rn
);
6416 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6419 if (insn
& (1 << 20))
6421 store_reg(s
, rd
, tmp
);
6425 tmp
= load_reg(s
, rs
);
6426 tmp2
= load_reg(s
, rm
);
6427 if (insn
& (1 << 22))
6428 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6430 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6431 if (insn
& (1 << 21)) /* mult accumulate */
6432 gen_addq(s
, tmp64
, rn
, rd
);
6433 if (!(insn
& (1 << 23))) { /* double accumulate */
6435 gen_addq_lo(s
, tmp64
, rn
);
6436 gen_addq_lo(s
, tmp64
, rd
);
6438 if (insn
& (1 << 20))
6439 gen_logicq_cc(tmp64
);
6440 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6441 tcg_temp_free_i64(tmp64
);
6445 rn
= (insn
>> 16) & 0xf;
6446 rd
= (insn
>> 12) & 0xf;
6447 if (insn
& (1 << 23)) {
6448 /* load/store exclusive */
6449 op1
= (insn
>> 21) & 0x3;
6454 addr
= tcg_temp_local_new_i32();
6455 load_reg_var(s
, addr
, rn
);
6456 if (insn
& (1 << 20)) {
6457 gen_helper_mark_exclusive(cpu_env
, addr
);
6460 tmp
= gen_ld32(addr
, IS_USER(s
));
6462 case 1: /* ldrexd */
6463 tmp
= gen_ld32(addr
, IS_USER(s
));
6464 store_reg(s
, rd
, tmp
);
6465 tcg_gen_addi_i32(addr
, addr
, 4);
6466 tmp
= gen_ld32(addr
, IS_USER(s
));
6469 case 2: /* ldrexb */
6470 tmp
= gen_ld8u(addr
, IS_USER(s
));
6472 case 3: /* ldrexh */
6473 tmp
= gen_ld16u(addr
, IS_USER(s
));
6478 store_reg(s
, rd
, tmp
);
6480 int label
= gen_new_label();
6482 tmp2
= tcg_temp_local_new_i32();
6483 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6484 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6485 tmp
= load_reg(s
,rm
);
6488 gen_st32(tmp
, addr
, IS_USER(s
));
6490 case 1: /* strexd */
6491 gen_st32(tmp
, addr
, IS_USER(s
));
6492 tcg_gen_addi_i32(addr
, addr
, 4);
6493 tmp
= load_reg(s
, rm
+ 1);
6494 gen_st32(tmp
, addr
, IS_USER(s
));
6496 case 2: /* strexb */
6497 gen_st8(tmp
, addr
, IS_USER(s
));
6499 case 3: /* strexh */
6500 gen_st16(tmp
, addr
, IS_USER(s
));
6505 gen_set_label(label
);
6506 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6507 tcg_temp_free(tmp2
);
6509 tcg_temp_free(addr
);
6511 /* SWP instruction */
6514 /* ??? This is not really atomic. However we know
6515 we never have multiple CPUs running in parallel,
6516 so it is good enough. */
6517 addr
= load_reg(s
, rn
);
6518 tmp
= load_reg(s
, rm
);
6519 if (insn
& (1 << 22)) {
6520 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6521 gen_st8(tmp
, addr
, IS_USER(s
));
6523 tmp2
= gen_ld32(addr
, IS_USER(s
));
6524 gen_st32(tmp
, addr
, IS_USER(s
));
6527 store_reg(s
, rd
, tmp2
);
6533 /* Misc load/store */
6534 rn
= (insn
>> 16) & 0xf;
6535 rd
= (insn
>> 12) & 0xf;
6536 addr
= load_reg(s
, rn
);
6537 if (insn
& (1 << 24))
6538 gen_add_datah_offset(s
, insn
, 0, addr
);
6540 if (insn
& (1 << 20)) {
6544 tmp
= gen_ld16u(addr
, IS_USER(s
));
6547 tmp
= gen_ld8s(addr
, IS_USER(s
));
6551 tmp
= gen_ld16s(addr
, IS_USER(s
));
6555 } else if (sh
& 2) {
6559 tmp
= load_reg(s
, rd
);
6560 gen_st32(tmp
, addr
, IS_USER(s
));
6561 tcg_gen_addi_i32(addr
, addr
, 4);
6562 tmp
= load_reg(s
, rd
+ 1);
6563 gen_st32(tmp
, addr
, IS_USER(s
));
6567 tmp
= gen_ld32(addr
, IS_USER(s
));
6568 store_reg(s
, rd
, tmp
);
6569 tcg_gen_addi_i32(addr
, addr
, 4);
6570 tmp
= gen_ld32(addr
, IS_USER(s
));
6574 address_offset
= -4;
6577 tmp
= load_reg(s
, rd
);
6578 gen_st16(tmp
, addr
, IS_USER(s
));
6581 /* Perform base writeback before the loaded value to
6582 ensure correct behavior with overlapping index registers.
6583 ldrd with base writeback is is undefined if the
6584 destination and index registers overlap. */
6585 if (!(insn
& (1 << 24))) {
6586 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6587 store_reg(s
, rn
, addr
);
6588 } else if (insn
& (1 << 21)) {
6590 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6591 store_reg(s
, rn
, addr
);
6596 /* Complete the load. */
6597 store_reg(s
, rd
, tmp
);
6606 if (insn
& (1 << 4)) {
6608 /* Armv6 Media instructions. */
6610 rn
= (insn
>> 16) & 0xf;
6611 rd
= (insn
>> 12) & 0xf;
6612 rs
= (insn
>> 8) & 0xf;
6613 switch ((insn
>> 23) & 3) {
6614 case 0: /* Parallel add/subtract. */
6615 op1
= (insn
>> 20) & 7;
6616 tmp
= load_reg(s
, rn
);
6617 tmp2
= load_reg(s
, rm
);
6618 sh
= (insn
>> 5) & 7;
6619 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6621 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6623 store_reg(s
, rd
, tmp
);
6626 if ((insn
& 0x00700020) == 0) {
6627 /* Halfword pack. */
6628 tmp
= load_reg(s
, rn
);
6629 tmp2
= load_reg(s
, rm
);
6630 shift
= (insn
>> 7) & 0x1f;
6631 if (insn
& (1 << 6)) {
6635 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6636 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6637 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6641 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6642 tcg_gen_ext16u_i32(tmp
, tmp
);
6643 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6645 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6647 store_reg(s
, rd
, tmp
);
6648 } else if ((insn
& 0x00200020) == 0x00200000) {
6650 tmp
= load_reg(s
, rm
);
6651 shift
= (insn
>> 7) & 0x1f;
6652 if (insn
& (1 << 6)) {
6655 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6657 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6659 sh
= (insn
>> 16) & 0x1f;
6661 tmp2
= tcg_const_i32(sh
);
6662 if (insn
& (1 << 22))
6663 gen_helper_usat(tmp
, tmp
, tmp2
);
6665 gen_helper_ssat(tmp
, tmp
, tmp2
);
6666 tcg_temp_free_i32(tmp2
);
6668 store_reg(s
, rd
, tmp
);
6669 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6671 tmp
= load_reg(s
, rm
);
6672 sh
= (insn
>> 16) & 0x1f;
6674 tmp2
= tcg_const_i32(sh
);
6675 if (insn
& (1 << 22))
6676 gen_helper_usat16(tmp
, tmp
, tmp2
);
6678 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6679 tcg_temp_free_i32(tmp2
);
6681 store_reg(s
, rd
, tmp
);
6682 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6684 tmp
= load_reg(s
, rn
);
6685 tmp2
= load_reg(s
, rm
);
6687 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6688 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6691 store_reg(s
, rd
, tmp
);
6692 } else if ((insn
& 0x000003e0) == 0x00000060) {
6693 tmp
= load_reg(s
, rm
);
6694 shift
= (insn
>> 10) & 3;
6695 /* ??? In many cases it's not neccessary to do a
6696 rotate, a shift is sufficient. */
6698 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6699 op1
= (insn
>> 20) & 7;
6701 case 0: gen_sxtb16(tmp
); break;
6702 case 2: gen_sxtb(tmp
); break;
6703 case 3: gen_sxth(tmp
); break;
6704 case 4: gen_uxtb16(tmp
); break;
6705 case 6: gen_uxtb(tmp
); break;
6706 case 7: gen_uxth(tmp
); break;
6707 default: goto illegal_op
;
6710 tmp2
= load_reg(s
, rn
);
6711 if ((op1
& 3) == 0) {
6712 gen_add16(tmp
, tmp2
);
6714 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6718 store_reg(s
, rd
, tmp
);
6719 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6721 tmp
= load_reg(s
, rm
);
6722 if (insn
& (1 << 22)) {
6723 if (insn
& (1 << 7)) {
6727 gen_helper_rbit(tmp
, tmp
);
6730 if (insn
& (1 << 7))
6733 tcg_gen_bswap32_i32(tmp
, tmp
);
6735 store_reg(s
, rd
, tmp
);
6740 case 2: /* Multiplies (Type 3). */
6741 tmp
= load_reg(s
, rm
);
6742 tmp2
= load_reg(s
, rs
);
6743 if (insn
& (1 << 20)) {
6744 /* Signed multiply most significant [accumulate]. */
6745 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6746 if (insn
& (1 << 5))
6747 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6748 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6750 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6751 tcg_temp_free_i64(tmp64
);
6753 tmp2
= load_reg(s
, rd
);
6754 if (insn
& (1 << 6)) {
6755 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6757 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6761 store_reg(s
, rn
, tmp
);
6763 if (insn
& (1 << 5))
6764 gen_swap_half(tmp2
);
6765 gen_smul_dual(tmp
, tmp2
);
6766 /* This addition cannot overflow. */
6767 if (insn
& (1 << 6)) {
6768 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6770 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6773 if (insn
& (1 << 22)) {
6774 /* smlald, smlsld */
6775 tmp64
= tcg_temp_new_i64();
6776 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6778 gen_addq(s
, tmp64
, rd
, rn
);
6779 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6780 tcg_temp_free_i64(tmp64
);
6782 /* smuad, smusd, smlad, smlsd */
6785 tmp2
= load_reg(s
, rd
);
6786 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6789 store_reg(s
, rn
, tmp
);
6794 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6796 case 0: /* Unsigned sum of absolute differences. */
6798 tmp
= load_reg(s
, rm
);
6799 tmp2
= load_reg(s
, rs
);
6800 gen_helper_usad8(tmp
, tmp
, tmp2
);
6803 tmp2
= load_reg(s
, rd
);
6804 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6807 store_reg(s
, rn
, tmp
);
6809 case 0x20: case 0x24: case 0x28: case 0x2c:
6810 /* Bitfield insert/clear. */
6812 shift
= (insn
>> 7) & 0x1f;
6813 i
= (insn
>> 16) & 0x1f;
6817 tcg_gen_movi_i32(tmp
, 0);
6819 tmp
= load_reg(s
, rm
);
6822 tmp2
= load_reg(s
, rd
);
6823 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6826 store_reg(s
, rd
, tmp
);
6828 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6829 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6831 tmp
= load_reg(s
, rm
);
6832 shift
= (insn
>> 7) & 0x1f;
6833 i
= ((insn
>> 16) & 0x1f) + 1;
6838 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6840 gen_sbfx(tmp
, shift
, i
);
6843 store_reg(s
, rd
, tmp
);
6853 /* Check for undefined extension instructions
6854 * per the ARM Bible IE:
6855 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6857 sh
= (0xf << 20) | (0xf << 4);
6858 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6862 /* load/store byte/word */
6863 rn
= (insn
>> 16) & 0xf;
6864 rd
= (insn
>> 12) & 0xf;
6865 tmp2
= load_reg(s
, rn
);
6866 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6867 if (insn
& (1 << 24))
6868 gen_add_data_offset(s
, insn
, tmp2
);
6869 if (insn
& (1 << 20)) {
6871 if (insn
& (1 << 22)) {
6872 tmp
= gen_ld8u(tmp2
, i
);
6874 tmp
= gen_ld32(tmp2
, i
);
6878 tmp
= load_reg(s
, rd
);
6879 if (insn
& (1 << 22))
6880 gen_st8(tmp
, tmp2
, i
);
6882 gen_st32(tmp
, tmp2
, i
);
6884 if (!(insn
& (1 << 24))) {
6885 gen_add_data_offset(s
, insn
, tmp2
);
6886 store_reg(s
, rn
, tmp2
);
6887 } else if (insn
& (1 << 21)) {
6888 store_reg(s
, rn
, tmp2
);
6892 if (insn
& (1 << 20)) {
6893 /* Complete the load. */
6897 store_reg(s
, rd
, tmp
);
6903 int j
, n
, user
, loaded_base
;
6905 /* load/store multiple words */
6906 /* XXX: store correct base if write back */
6908 if (insn
& (1 << 22)) {
6910 goto illegal_op
; /* only usable in supervisor mode */
6912 if ((insn
& (1 << 15)) == 0)
6915 rn
= (insn
>> 16) & 0xf;
6916 addr
= load_reg(s
, rn
);
6918 /* compute total size */
6920 TCGV_UNUSED(loaded_var
);
6923 if (insn
& (1 << i
))
6926 /* XXX: test invalid n == 0 case ? */
6927 if (insn
& (1 << 23)) {
6928 if (insn
& (1 << 24)) {
6930 tcg_gen_addi_i32(addr
, addr
, 4);
6932 /* post increment */
6935 if (insn
& (1 << 24)) {
6937 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6939 /* post decrement */
6941 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6946 if (insn
& (1 << i
)) {
6947 if (insn
& (1 << 20)) {
6949 tmp
= gen_ld32(addr
, IS_USER(s
));
6953 tmp2
= tcg_const_i32(i
);
6954 gen_helper_set_user_reg(tmp2
, tmp
);
6955 tcg_temp_free_i32(tmp2
);
6957 } else if (i
== rn
) {
6961 store_reg(s
, i
, tmp
);
6966 /* special case: r15 = PC + 8 */
6967 val
= (long)s
->pc
+ 4;
6969 tcg_gen_movi_i32(tmp
, val
);
6972 tmp2
= tcg_const_i32(i
);
6973 gen_helper_get_user_reg(tmp
, tmp2
);
6974 tcg_temp_free_i32(tmp2
);
6976 tmp
= load_reg(s
, i
);
6978 gen_st32(tmp
, addr
, IS_USER(s
));
6981 /* no need to add after the last transfer */
6983 tcg_gen_addi_i32(addr
, addr
, 4);
6986 if (insn
& (1 << 21)) {
6988 if (insn
& (1 << 23)) {
6989 if (insn
& (1 << 24)) {
6992 /* post increment */
6993 tcg_gen_addi_i32(addr
, addr
, 4);
6996 if (insn
& (1 << 24)) {
6999 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7001 /* post decrement */
7002 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7005 store_reg(s
, rn
, addr
);
7010 store_reg(s
, rn
, loaded_var
);
7012 if ((insn
& (1 << 22)) && !user
) {
7013 /* Restore CPSR from SPSR. */
7014 tmp
= load_cpu_field(spsr
);
7015 gen_set_cpsr(tmp
, 0xffffffff);
7017 s
->is_jmp
= DISAS_UPDATE
;
7026 /* branch (and link) */
7027 val
= (int32_t)s
->pc
;
7028 if (insn
& (1 << 24)) {
7030 tcg_gen_movi_i32(tmp
, val
);
7031 store_reg(s
, 14, tmp
);
7033 offset
= (((int32_t)insn
<< 8) >> 8);
7034 val
+= (offset
<< 2) + 4;
7042 if (disas_coproc_insn(env
, s
, insn
))
7047 gen_set_pc_im(s
->pc
);
7048 s
->is_jmp
= DISAS_SWI
;
7052 gen_set_condexec(s
);
7053 gen_set_pc_im(s
->pc
- 4);
7054 gen_exception(EXCP_UDEF
);
7055 s
->is_jmp
= DISAS_JUMP
;
7061 /* Return true if this is a Thumb-2 logical op. */
7063 thumb2_logic_op(int op
)
7068 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7069 then set condition code flags based on the result of the operation.
7070 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7071 to the high bit of T1.
7072 Returns zero if the opcode is valid. */
7075 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7082 tcg_gen_and_i32(t0
, t0
, t1
);
7086 tcg_gen_andc_i32(t0
, t0
, t1
);
7090 tcg_gen_or_i32(t0
, t0
, t1
);
7094 tcg_gen_not_i32(t1
, t1
);
7095 tcg_gen_or_i32(t0
, t0
, t1
);
7099 tcg_gen_xor_i32(t0
, t0
, t1
);
7104 gen_helper_add_cc(t0
, t0
, t1
);
7106 tcg_gen_add_i32(t0
, t0
, t1
);
7110 gen_helper_adc_cc(t0
, t0
, t1
);
7116 gen_helper_sbc_cc(t0
, t0
, t1
);
7118 gen_sub_carry(t0
, t0
, t1
);
7122 gen_helper_sub_cc(t0
, t0
, t1
);
7124 tcg_gen_sub_i32(t0
, t0
, t1
);
7128 gen_helper_sub_cc(t0
, t1
, t0
);
7130 tcg_gen_sub_i32(t0
, t1
, t0
);
7132 default: /* 5, 6, 7, 9, 12, 15. */
7138 gen_set_CF_bit31(t1
);
7143 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7145 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7147 uint32_t insn
, imm
, shift
, offset
;
7148 uint32_t rd
, rn
, rm
, rs
;
7159 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7160 || arm_feature (env
, ARM_FEATURE_M
))) {
7161 /* Thumb-1 cores may need to treat bl and blx as a pair of
7162 16-bit instructions to get correct prefetch abort behavior. */
7164 if ((insn
& (1 << 12)) == 0) {
7165 /* Second half of blx. */
7166 offset
= ((insn
& 0x7ff) << 1);
7167 tmp
= load_reg(s
, 14);
7168 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7169 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7172 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7173 store_reg(s
, 14, tmp2
);
7177 if (insn
& (1 << 11)) {
7178 /* Second half of bl. */
7179 offset
= ((insn
& 0x7ff) << 1) | 1;
7180 tmp
= load_reg(s
, 14);
7181 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7184 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7185 store_reg(s
, 14, tmp2
);
7189 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7190 /* Instruction spans a page boundary. Implement it as two
7191 16-bit instructions in case the second half causes an
7193 offset
= ((int32_t)insn
<< 21) >> 9;
7194 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7197 /* Fall through to 32-bit decode. */
7200 insn
= lduw_code(s
->pc
);
7202 insn
|= (uint32_t)insn_hw1
<< 16;
7204 if ((insn
& 0xf800e800) != 0xf000e800) {
7208 rn
= (insn
>> 16) & 0xf;
7209 rs
= (insn
>> 12) & 0xf;
7210 rd
= (insn
>> 8) & 0xf;
7212 switch ((insn
>> 25) & 0xf) {
7213 case 0: case 1: case 2: case 3:
7214 /* 16-bit instructions. Should never happen. */
7217 if (insn
& (1 << 22)) {
7218 /* Other load/store, table branch. */
7219 if (insn
& 0x01200000) {
7220 /* Load/store doubleword. */
7223 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7225 addr
= load_reg(s
, rn
);
7227 offset
= (insn
& 0xff) * 4;
7228 if ((insn
& (1 << 23)) == 0)
7230 if (insn
& (1 << 24)) {
7231 tcg_gen_addi_i32(addr
, addr
, offset
);
7234 if (insn
& (1 << 20)) {
7236 tmp
= gen_ld32(addr
, IS_USER(s
));
7237 store_reg(s
, rs
, tmp
);
7238 tcg_gen_addi_i32(addr
, addr
, 4);
7239 tmp
= gen_ld32(addr
, IS_USER(s
));
7240 store_reg(s
, rd
, tmp
);
7243 tmp
= load_reg(s
, rs
);
7244 gen_st32(tmp
, addr
, IS_USER(s
));
7245 tcg_gen_addi_i32(addr
, addr
, 4);
7246 tmp
= load_reg(s
, rd
);
7247 gen_st32(tmp
, addr
, IS_USER(s
));
7249 if (insn
& (1 << 21)) {
7250 /* Base writeback. */
7253 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7254 store_reg(s
, rn
, addr
);
7258 } else if ((insn
& (1 << 23)) == 0) {
7259 /* Load/store exclusive word. */
7260 addr
= tcg_temp_local_new();
7261 load_reg_var(s
, addr
, rn
);
7262 if (insn
& (1 << 20)) {
7263 gen_helper_mark_exclusive(cpu_env
, addr
);
7264 tmp
= gen_ld32(addr
, IS_USER(s
));
7265 store_reg(s
, rd
, tmp
);
7267 int label
= gen_new_label();
7268 tmp2
= tcg_temp_local_new();
7269 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7270 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7271 tmp
= load_reg(s
, rs
);
7272 gen_st32(tmp
, addr
, IS_USER(s
));
7273 gen_set_label(label
);
7274 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7275 tcg_temp_free(tmp2
);
7277 tcg_temp_free(addr
);
7278 } else if ((insn
& (1 << 6)) == 0) {
7282 tcg_gen_movi_i32(addr
, s
->pc
);
7284 addr
= load_reg(s
, rn
);
7286 tmp
= load_reg(s
, rm
);
7287 tcg_gen_add_i32(addr
, addr
, tmp
);
7288 if (insn
& (1 << 4)) {
7290 tcg_gen_add_i32(addr
, addr
, tmp
);
7292 tmp
= gen_ld16u(addr
, IS_USER(s
));
7295 tmp
= gen_ld8u(addr
, IS_USER(s
));
7298 tcg_gen_shli_i32(tmp
, tmp
, 1);
7299 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7300 store_reg(s
, 15, tmp
);
7302 /* Load/store exclusive byte/halfword/doubleword. */
7303 /* ??? These are not really atomic. However we know
7304 we never have multiple CPUs running in parallel,
7305 so it is good enough. */
7306 op
= (insn
>> 4) & 0x3;
7307 addr
= tcg_temp_local_new();
7308 load_reg_var(s
, addr
, rn
);
7309 if (insn
& (1 << 20)) {
7310 gen_helper_mark_exclusive(cpu_env
, addr
);
7313 tmp
= gen_ld8u(addr
, IS_USER(s
));
7316 tmp
= gen_ld16u(addr
, IS_USER(s
));
7319 tmp
= gen_ld32(addr
, IS_USER(s
));
7320 tcg_gen_addi_i32(addr
, addr
, 4);
7321 tmp2
= gen_ld32(addr
, IS_USER(s
));
7322 store_reg(s
, rd
, tmp2
);
7327 store_reg(s
, rs
, tmp
);
7329 int label
= gen_new_label();
7330 tmp2
= tcg_temp_local_new();
7331 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7332 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7333 tmp
= load_reg(s
, rs
);
7336 gen_st8(tmp
, addr
, IS_USER(s
));
7339 gen_st16(tmp
, addr
, IS_USER(s
));
7342 gen_st32(tmp
, addr
, IS_USER(s
));
7343 tcg_gen_addi_i32(addr
, addr
, 4);
7344 tmp
= load_reg(s
, rd
);
7345 gen_st32(tmp
, addr
, IS_USER(s
));
7350 gen_set_label(label
);
7351 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7352 tcg_temp_free(tmp2
);
7354 tcg_temp_free(addr
);
7357 /* Load/store multiple, RFE, SRS. */
7358 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7359 /* Not available in user mode. */
7362 if (insn
& (1 << 20)) {
7364 addr
= load_reg(s
, rn
);
7365 if ((insn
& (1 << 24)) == 0)
7366 tcg_gen_addi_i32(addr
, addr
, -8);
7367 /* Load PC into tmp and CPSR into tmp2. */
7368 tmp
= gen_ld32(addr
, 0);
7369 tcg_gen_addi_i32(addr
, addr
, 4);
7370 tmp2
= gen_ld32(addr
, 0);
7371 if (insn
& (1 << 21)) {
7372 /* Base writeback. */
7373 if (insn
& (1 << 24)) {
7374 tcg_gen_addi_i32(addr
, addr
, 4);
7376 tcg_gen_addi_i32(addr
, addr
, -4);
7378 store_reg(s
, rn
, addr
);
7382 gen_rfe(s
, tmp
, tmp2
);
7386 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7387 addr
= load_reg(s
, 13);
7390 tmp
= tcg_const_i32(op
);
7391 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7392 tcg_temp_free_i32(tmp
);
7394 if ((insn
& (1 << 24)) == 0) {
7395 tcg_gen_addi_i32(addr
, addr
, -8);
7397 tmp
= load_reg(s
, 14);
7398 gen_st32(tmp
, addr
, 0);
7399 tcg_gen_addi_i32(addr
, addr
, 4);
7401 gen_helper_cpsr_read(tmp
);
7402 gen_st32(tmp
, addr
, 0);
7403 if (insn
& (1 << 21)) {
7404 if ((insn
& (1 << 24)) == 0) {
7405 tcg_gen_addi_i32(addr
, addr
, -4);
7407 tcg_gen_addi_i32(addr
, addr
, 4);
7409 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7410 store_reg(s
, 13, addr
);
7412 tmp
= tcg_const_i32(op
);
7413 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7414 tcg_temp_free_i32(tmp
);
7422 /* Load/store multiple. */
7423 addr
= load_reg(s
, rn
);
7425 for (i
= 0; i
< 16; i
++) {
7426 if (insn
& (1 << i
))
7429 if (insn
& (1 << 24)) {
7430 tcg_gen_addi_i32(addr
, addr
, -offset
);
7433 for (i
= 0; i
< 16; i
++) {
7434 if ((insn
& (1 << i
)) == 0)
7436 if (insn
& (1 << 20)) {
7438 tmp
= gen_ld32(addr
, IS_USER(s
));
7442 store_reg(s
, i
, tmp
);
7446 tmp
= load_reg(s
, i
);
7447 gen_st32(tmp
, addr
, IS_USER(s
));
7449 tcg_gen_addi_i32(addr
, addr
, 4);
7451 if (insn
& (1 << 21)) {
7452 /* Base register writeback. */
7453 if (insn
& (1 << 24)) {
7454 tcg_gen_addi_i32(addr
, addr
, -offset
);
7456 /* Fault if writeback register is in register list. */
7457 if (insn
& (1 << rn
))
7459 store_reg(s
, rn
, addr
);
7466 case 5: /* Data processing register constant shift. */
7469 tcg_gen_movi_i32(tmp
, 0);
7471 tmp
= load_reg(s
, rn
);
7473 tmp2
= load_reg(s
, rm
);
7474 op
= (insn
>> 21) & 0xf;
7475 shiftop
= (insn
>> 4) & 3;
7476 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7477 conds
= (insn
& (1 << 20)) != 0;
7478 logic_cc
= (conds
&& thumb2_logic_op(op
));
7479 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7480 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7484 store_reg(s
, rd
, tmp
);
7489 case 13: /* Misc data processing. */
7490 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7491 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7494 case 0: /* Register controlled shift. */
7495 tmp
= load_reg(s
, rn
);
7496 tmp2
= load_reg(s
, rm
);
7497 if ((insn
& 0x70) != 0)
7499 op
= (insn
>> 21) & 3;
7500 logic_cc
= (insn
& (1 << 20)) != 0;
7501 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7504 store_reg_bx(env
, s
, rd
, tmp
);
7506 case 1: /* Sign/zero extend. */
7507 tmp
= load_reg(s
, rm
);
7508 shift
= (insn
>> 4) & 3;
7509 /* ??? In many cases it's not neccessary to do a
7510 rotate, a shift is sufficient. */
7512 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7513 op
= (insn
>> 20) & 7;
7515 case 0: gen_sxth(tmp
); break;
7516 case 1: gen_uxth(tmp
); break;
7517 case 2: gen_sxtb16(tmp
); break;
7518 case 3: gen_uxtb16(tmp
); break;
7519 case 4: gen_sxtb(tmp
); break;
7520 case 5: gen_uxtb(tmp
); break;
7521 default: goto illegal_op
;
7524 tmp2
= load_reg(s
, rn
);
7525 if ((op
>> 1) == 1) {
7526 gen_add16(tmp
, tmp2
);
7528 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7532 store_reg(s
, rd
, tmp
);
7534 case 2: /* SIMD add/subtract. */
7535 op
= (insn
>> 20) & 7;
7536 shift
= (insn
>> 4) & 7;
7537 if ((op
& 3) == 3 || (shift
& 3) == 3)
7539 tmp
= load_reg(s
, rn
);
7540 tmp2
= load_reg(s
, rm
);
7541 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7543 store_reg(s
, rd
, tmp
);
7545 case 3: /* Other data processing. */
7546 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7548 /* Saturating add/subtract. */
7549 tmp
= load_reg(s
, rn
);
7550 tmp2
= load_reg(s
, rm
);
7552 gen_helper_double_saturate(tmp
, tmp
);
7554 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7556 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7559 tmp
= load_reg(s
, rn
);
7561 case 0x0a: /* rbit */
7562 gen_helper_rbit(tmp
, tmp
);
7564 case 0x08: /* rev */
7565 tcg_gen_bswap32_i32(tmp
, tmp
);
7567 case 0x09: /* rev16 */
7570 case 0x0b: /* revsh */
7573 case 0x10: /* sel */
7574 tmp2
= load_reg(s
, rm
);
7576 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7577 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7581 case 0x18: /* clz */
7582 gen_helper_clz(tmp
, tmp
);
7588 store_reg(s
, rd
, tmp
);
7590 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7591 op
= (insn
>> 4) & 0xf;
7592 tmp
= load_reg(s
, rn
);
7593 tmp2
= load_reg(s
, rm
);
7594 switch ((insn
>> 20) & 7) {
7595 case 0: /* 32 x 32 -> 32 */
7596 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7599 tmp2
= load_reg(s
, rs
);
7601 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7603 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7607 case 1: /* 16 x 16 -> 32 */
7608 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7611 tmp2
= load_reg(s
, rs
);
7612 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7616 case 2: /* Dual multiply add. */
7617 case 4: /* Dual multiply subtract. */
7619 gen_swap_half(tmp2
);
7620 gen_smul_dual(tmp
, tmp2
);
7621 /* This addition cannot overflow. */
7622 if (insn
& (1 << 22)) {
7623 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7625 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7630 tmp2
= load_reg(s
, rs
);
7631 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7635 case 3: /* 32 * 16 -> 32msb */
7637 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7640 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7641 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7643 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7644 tcg_temp_free_i64(tmp64
);
7647 tmp2
= load_reg(s
, rs
);
7648 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7652 case 5: case 6: /* 32 * 32 -> 32msb */
7653 gen_imull(tmp
, tmp2
);
7654 if (insn
& (1 << 5)) {
7655 gen_roundqd(tmp
, tmp2
);
7662 tmp2
= load_reg(s
, rs
);
7663 if (insn
& (1 << 21)) {
7664 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7666 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7671 case 7: /* Unsigned sum of absolute differences. */
7672 gen_helper_usad8(tmp
, tmp
, tmp2
);
7675 tmp2
= load_reg(s
, rs
);
7676 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7681 store_reg(s
, rd
, tmp
);
7683 case 6: case 7: /* 64-bit multiply, Divide. */
7684 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7685 tmp
= load_reg(s
, rn
);
7686 tmp2
= load_reg(s
, rm
);
7687 if ((op
& 0x50) == 0x10) {
7689 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7692 gen_helper_udiv(tmp
, tmp
, tmp2
);
7694 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7696 store_reg(s
, rd
, tmp
);
7697 } else if ((op
& 0xe) == 0xc) {
7698 /* Dual multiply accumulate long. */
7700 gen_swap_half(tmp2
);
7701 gen_smul_dual(tmp
, tmp2
);
7703 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7705 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7709 tmp64
= tcg_temp_new_i64();
7710 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7712 gen_addq(s
, tmp64
, rs
, rd
);
7713 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7714 tcg_temp_free_i64(tmp64
);
7717 /* Unsigned 64-bit multiply */
7718 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7722 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7724 tmp64
= tcg_temp_new_i64();
7725 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7728 /* Signed 64-bit multiply */
7729 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7734 gen_addq_lo(s
, tmp64
, rs
);
7735 gen_addq_lo(s
, tmp64
, rd
);
7736 } else if (op
& 0x40) {
7737 /* 64-bit accumulate. */
7738 gen_addq(s
, tmp64
, rs
, rd
);
7740 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7741 tcg_temp_free_i64(tmp64
);
7746 case 6: case 7: case 14: case 15:
7748 if (((insn
>> 24) & 3) == 3) {
7749 /* Translate into the equivalent ARM encoding. */
7750 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7751 if (disas_neon_data_insn(env
, s
, insn
))
7754 if (insn
& (1 << 28))
7756 if (disas_coproc_insn (env
, s
, insn
))
7760 case 8: case 9: case 10: case 11:
7761 if (insn
& (1 << 15)) {
7762 /* Branches, misc control. */
7763 if (insn
& 0x5000) {
7764 /* Unconditional branch. */
7765 /* signextend(hw1[10:0]) -> offset[:12]. */
7766 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7767 /* hw1[10:0] -> offset[11:1]. */
7768 offset
|= (insn
& 0x7ff) << 1;
7769 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7770 offset[24:22] already have the same value because of the
7771 sign extension above. */
7772 offset
^= ((~insn
) & (1 << 13)) << 10;
7773 offset
^= ((~insn
) & (1 << 11)) << 11;
7775 if (insn
& (1 << 14)) {
7776 /* Branch and link. */
7777 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7781 if (insn
& (1 << 12)) {
7786 offset
&= ~(uint32_t)2;
7787 gen_bx_im(s
, offset
);
7789 } else if (((insn
>> 23) & 7) == 7) {
7791 if (insn
& (1 << 13))
7794 if (insn
& (1 << 26)) {
7795 /* Secure monitor call (v6Z) */
7796 goto illegal_op
; /* not implemented. */
7798 op
= (insn
>> 20) & 7;
7800 case 0: /* msr cpsr. */
7802 tmp
= load_reg(s
, rn
);
7803 addr
= tcg_const_i32(insn
& 0xff);
7804 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7805 tcg_temp_free_i32(addr
);
7811 case 1: /* msr spsr. */
7814 tmp
= load_reg(s
, rn
);
7816 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7820 case 2: /* cps, nop-hint. */
7821 if (((insn
>> 8) & 7) == 0) {
7822 gen_nop_hint(s
, insn
& 0xff);
7824 /* Implemented as NOP in user mode. */
7829 if (insn
& (1 << 10)) {
7830 if (insn
& (1 << 7))
7832 if (insn
& (1 << 6))
7834 if (insn
& (1 << 5))
7836 if (insn
& (1 << 9))
7837 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7839 if (insn
& (1 << 8)) {
7841 imm
|= (insn
& 0x1f);
7844 gen_set_psr_im(s
, offset
, 0, imm
);
7847 case 3: /* Special control operations. */
7848 op
= (insn
>> 4) & 0xf;
7851 gen_helper_clrex(cpu_env
);
7856 /* These execute as NOPs. */
7864 /* Trivial implementation equivalent to bx. */
7865 tmp
= load_reg(s
, rn
);
7868 case 5: /* Exception return. */
7869 /* Unpredictable in user mode. */
7871 case 6: /* mrs cpsr. */
7874 addr
= tcg_const_i32(insn
& 0xff);
7875 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7876 tcg_temp_free_i32(addr
);
7878 gen_helper_cpsr_read(tmp
);
7880 store_reg(s
, rd
, tmp
);
7882 case 7: /* mrs spsr. */
7883 /* Not accessible in user mode. */
7884 if (IS_USER(s
) || IS_M(env
))
7886 tmp
= load_cpu_field(spsr
);
7887 store_reg(s
, rd
, tmp
);
7892 /* Conditional branch. */
7893 op
= (insn
>> 22) & 0xf;
7894 /* Generate a conditional jump to next instruction. */
7895 s
->condlabel
= gen_new_label();
7896 gen_test_cc(op
^ 1, s
->condlabel
);
7899 /* offset[11:1] = insn[10:0] */
7900 offset
= (insn
& 0x7ff) << 1;
7901 /* offset[17:12] = insn[21:16]. */
7902 offset
|= (insn
& 0x003f0000) >> 4;
7903 /* offset[31:20] = insn[26]. */
7904 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7905 /* offset[18] = insn[13]. */
7906 offset
|= (insn
& (1 << 13)) << 5;
7907 /* offset[19] = insn[11]. */
7908 offset
|= (insn
& (1 << 11)) << 8;
7910 /* jump to the offset */
7911 gen_jmp(s
, s
->pc
+ offset
);
7914 /* Data processing immediate. */
7915 if (insn
& (1 << 25)) {
7916 if (insn
& (1 << 24)) {
7917 if (insn
& (1 << 20))
7919 /* Bitfield/Saturate. */
7920 op
= (insn
>> 21) & 7;
7922 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7925 tcg_gen_movi_i32(tmp
, 0);
7927 tmp
= load_reg(s
, rn
);
7930 case 2: /* Signed bitfield extract. */
7932 if (shift
+ imm
> 32)
7935 gen_sbfx(tmp
, shift
, imm
);
7937 case 6: /* Unsigned bitfield extract. */
7939 if (shift
+ imm
> 32)
7942 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7944 case 3: /* Bitfield insert/clear. */
7947 imm
= imm
+ 1 - shift
;
7949 tmp2
= load_reg(s
, rd
);
7950 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7956 default: /* Saturate. */
7959 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7961 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7963 tmp2
= tcg_const_i32(imm
);
7966 if ((op
& 1) && shift
== 0)
7967 gen_helper_usat16(tmp
, tmp
, tmp2
);
7969 gen_helper_usat(tmp
, tmp
, tmp2
);
7972 if ((op
& 1) && shift
== 0)
7973 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7975 gen_helper_ssat(tmp
, tmp
, tmp2
);
7977 tcg_temp_free_i32(tmp2
);
7980 store_reg(s
, rd
, tmp
);
7982 imm
= ((insn
& 0x04000000) >> 15)
7983 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7984 if (insn
& (1 << 22)) {
7985 /* 16-bit immediate. */
7986 imm
|= (insn
>> 4) & 0xf000;
7987 if (insn
& (1 << 23)) {
7989 tmp
= load_reg(s
, rd
);
7990 tcg_gen_ext16u_i32(tmp
, tmp
);
7991 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7995 tcg_gen_movi_i32(tmp
, imm
);
7998 /* Add/sub 12-bit immediate. */
8000 offset
= s
->pc
& ~(uint32_t)3;
8001 if (insn
& (1 << 23))
8006 tcg_gen_movi_i32(tmp
, offset
);
8008 tmp
= load_reg(s
, rn
);
8009 if (insn
& (1 << 23))
8010 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8012 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8015 store_reg(s
, rd
, tmp
);
8018 int shifter_out
= 0;
8019 /* modified 12-bit immediate. */
8020 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8021 imm
= (insn
& 0xff);
8024 /* Nothing to do. */
8026 case 1: /* 00XY00XY */
8029 case 2: /* XY00XY00 */
8033 case 3: /* XYXYXYXY */
8037 default: /* Rotated constant. */
8038 shift
= (shift
<< 1) | (imm
>> 7);
8040 imm
= imm
<< (32 - shift
);
8045 tcg_gen_movi_i32(tmp2
, imm
);
8046 rn
= (insn
>> 16) & 0xf;
8049 tcg_gen_movi_i32(tmp
, 0);
8051 tmp
= load_reg(s
, rn
);
8053 op
= (insn
>> 21) & 0xf;
8054 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8055 shifter_out
, tmp
, tmp2
))
8058 rd
= (insn
>> 8) & 0xf;
8060 store_reg(s
, rd
, tmp
);
8067 case 12: /* Load/store single data item. */
8072 if ((insn
& 0x01100000) == 0x01000000) {
8073 if (disas_neon_ls_insn(env
, s
, insn
))
8081 /* s->pc has already been incremented by 4. */
8082 imm
= s
->pc
& 0xfffffffc;
8083 if (insn
& (1 << 23))
8084 imm
+= insn
& 0xfff;
8086 imm
-= insn
& 0xfff;
8087 tcg_gen_movi_i32(addr
, imm
);
8089 addr
= load_reg(s
, rn
);
8090 if (insn
& (1 << 23)) {
8091 /* Positive offset. */
8093 tcg_gen_addi_i32(addr
, addr
, imm
);
8095 op
= (insn
>> 8) & 7;
8098 case 0: case 8: /* Shifted Register. */
8099 shift
= (insn
>> 4) & 0xf;
8102 tmp
= load_reg(s
, rm
);
8104 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8105 tcg_gen_add_i32(addr
, addr
, tmp
);
8108 case 4: /* Negative offset. */
8109 tcg_gen_addi_i32(addr
, addr
, -imm
);
8111 case 6: /* User privilege. */
8112 tcg_gen_addi_i32(addr
, addr
, imm
);
8115 case 1: /* Post-decrement. */
8118 case 3: /* Post-increment. */
8122 case 5: /* Pre-decrement. */
8125 case 7: /* Pre-increment. */
8126 tcg_gen_addi_i32(addr
, addr
, imm
);
8134 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8135 if (insn
& (1 << 20)) {
8137 if (rs
== 15 && op
!= 2) {
8140 /* Memory hint. Implemented as NOP. */
8143 case 0: tmp
= gen_ld8u(addr
, user
); break;
8144 case 4: tmp
= gen_ld8s(addr
, user
); break;
8145 case 1: tmp
= gen_ld16u(addr
, user
); break;
8146 case 5: tmp
= gen_ld16s(addr
, user
); break;
8147 case 2: tmp
= gen_ld32(addr
, user
); break;
8148 default: goto illegal_op
;
8153 store_reg(s
, rs
, tmp
);
8160 tmp
= load_reg(s
, rs
);
8162 case 0: gen_st8(tmp
, addr
, user
); break;
8163 case 1: gen_st16(tmp
, addr
, user
); break;
8164 case 2: gen_st32(tmp
, addr
, user
); break;
8165 default: goto illegal_op
;
8169 tcg_gen_addi_i32(addr
, addr
, imm
);
8171 store_reg(s
, rn
, addr
);
8185 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8187 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8194 if (s
->condexec_mask
) {
8195 cond
= s
->condexec_cond
;
8196 s
->condlabel
= gen_new_label();
8197 gen_test_cc(cond
^ 1, s
->condlabel
);
8201 insn
= lduw_code(s
->pc
);
8204 switch (insn
>> 12) {
8208 op
= (insn
>> 11) & 3;
8211 rn
= (insn
>> 3) & 7;
8212 tmp
= load_reg(s
, rn
);
8213 if (insn
& (1 << 10)) {
8216 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8219 rm
= (insn
>> 6) & 7;
8220 tmp2
= load_reg(s
, rm
);
8222 if (insn
& (1 << 9)) {
8223 if (s
->condexec_mask
)
8224 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8226 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8228 if (s
->condexec_mask
)
8229 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8231 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8234 store_reg(s
, rd
, tmp
);
8236 /* shift immediate */
8237 rm
= (insn
>> 3) & 7;
8238 shift
= (insn
>> 6) & 0x1f;
8239 tmp
= load_reg(s
, rm
);
8240 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8241 if (!s
->condexec_mask
)
8243 store_reg(s
, rd
, tmp
);
8247 /* arithmetic large immediate */
8248 op
= (insn
>> 11) & 3;
8249 rd
= (insn
>> 8) & 0x7;
8250 if (op
== 0) { /* mov */
8252 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8253 if (!s
->condexec_mask
)
8255 store_reg(s
, rd
, tmp
);
8257 tmp
= load_reg(s
, rd
);
8259 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8262 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8267 if (s
->condexec_mask
)
8268 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8270 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8272 store_reg(s
, rd
, tmp
);
8275 if (s
->condexec_mask
)
8276 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8278 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8280 store_reg(s
, rd
, tmp
);
8286 if (insn
& (1 << 11)) {
8287 rd
= (insn
>> 8) & 7;
8288 /* load pc-relative. Bit 1 of PC is ignored. */
8289 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8290 val
&= ~(uint32_t)2;
8292 tcg_gen_movi_i32(addr
, val
);
8293 tmp
= gen_ld32(addr
, IS_USER(s
));
8295 store_reg(s
, rd
, tmp
);
8298 if (insn
& (1 << 10)) {
8299 /* data processing extended or blx */
8300 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8301 rm
= (insn
>> 3) & 0xf;
8302 op
= (insn
>> 8) & 3;
8305 tmp
= load_reg(s
, rd
);
8306 tmp2
= load_reg(s
, rm
);
8307 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8309 store_reg(s
, rd
, tmp
);
8312 tmp
= load_reg(s
, rd
);
8313 tmp2
= load_reg(s
, rm
);
8314 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8318 case 2: /* mov/cpy */
8319 tmp
= load_reg(s
, rm
);
8320 store_reg(s
, rd
, tmp
);
8322 case 3:/* branch [and link] exchange thumb register */
8323 tmp
= load_reg(s
, rm
);
8324 if (insn
& (1 << 7)) {
8325 val
= (uint32_t)s
->pc
| 1;
8327 tcg_gen_movi_i32(tmp2
, val
);
8328 store_reg(s
, 14, tmp2
);
8336 /* data processing register */
8338 rm
= (insn
>> 3) & 7;
8339 op
= (insn
>> 6) & 0xf;
8340 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8341 /* the shift/rotate ops want the operands backwards */
8350 if (op
== 9) { /* neg */
8352 tcg_gen_movi_i32(tmp
, 0);
8353 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8354 tmp
= load_reg(s
, rd
);
8359 tmp2
= load_reg(s
, rm
);
8362 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8363 if (!s
->condexec_mask
)
8367 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8368 if (!s
->condexec_mask
)
8372 if (s
->condexec_mask
) {
8373 gen_helper_shl(tmp2
, tmp2
, tmp
);
8375 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8380 if (s
->condexec_mask
) {
8381 gen_helper_shr(tmp2
, tmp2
, tmp
);
8383 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8388 if (s
->condexec_mask
) {
8389 gen_helper_sar(tmp2
, tmp2
, tmp
);
8391 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8396 if (s
->condexec_mask
)
8399 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8402 if (s
->condexec_mask
)
8403 gen_sub_carry(tmp
, tmp
, tmp2
);
8405 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8408 if (s
->condexec_mask
) {
8409 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8410 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8412 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8417 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8422 if (s
->condexec_mask
)
8423 tcg_gen_neg_i32(tmp
, tmp2
);
8425 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8428 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8432 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8436 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8437 if (!s
->condexec_mask
)
8441 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8442 if (!s
->condexec_mask
)
8446 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8447 if (!s
->condexec_mask
)
8451 tcg_gen_not_i32(tmp2
, tmp2
);
8452 if (!s
->condexec_mask
)
8460 store_reg(s
, rm
, tmp2
);
8464 store_reg(s
, rd
, tmp
);
8474 /* load/store register offset. */
8476 rn
= (insn
>> 3) & 7;
8477 rm
= (insn
>> 6) & 7;
8478 op
= (insn
>> 9) & 7;
8479 addr
= load_reg(s
, rn
);
8480 tmp
= load_reg(s
, rm
);
8481 tcg_gen_add_i32(addr
, addr
, tmp
);
8484 if (op
< 3) /* store */
8485 tmp
= load_reg(s
, rd
);
8489 gen_st32(tmp
, addr
, IS_USER(s
));
8492 gen_st16(tmp
, addr
, IS_USER(s
));
8495 gen_st8(tmp
, addr
, IS_USER(s
));
8498 tmp
= gen_ld8s(addr
, IS_USER(s
));
8501 tmp
= gen_ld32(addr
, IS_USER(s
));
8504 tmp
= gen_ld16u(addr
, IS_USER(s
));
8507 tmp
= gen_ld8u(addr
, IS_USER(s
));
8510 tmp
= gen_ld16s(addr
, IS_USER(s
));
8513 if (op
>= 3) /* load */
8514 store_reg(s
, rd
, tmp
);
8519 /* load/store word immediate offset */
8521 rn
= (insn
>> 3) & 7;
8522 addr
= load_reg(s
, rn
);
8523 val
= (insn
>> 4) & 0x7c;
8524 tcg_gen_addi_i32(addr
, addr
, val
);
8526 if (insn
& (1 << 11)) {
8528 tmp
= gen_ld32(addr
, IS_USER(s
));
8529 store_reg(s
, rd
, tmp
);
8532 tmp
= load_reg(s
, rd
);
8533 gen_st32(tmp
, addr
, IS_USER(s
));
8539 /* load/store byte immediate offset */
8541 rn
= (insn
>> 3) & 7;
8542 addr
= load_reg(s
, rn
);
8543 val
= (insn
>> 6) & 0x1f;
8544 tcg_gen_addi_i32(addr
, addr
, val
);
8546 if (insn
& (1 << 11)) {
8548 tmp
= gen_ld8u(addr
, IS_USER(s
));
8549 store_reg(s
, rd
, tmp
);
8552 tmp
= load_reg(s
, rd
);
8553 gen_st8(tmp
, addr
, IS_USER(s
));
8559 /* load/store halfword immediate offset */
8561 rn
= (insn
>> 3) & 7;
8562 addr
= load_reg(s
, rn
);
8563 val
= (insn
>> 5) & 0x3e;
8564 tcg_gen_addi_i32(addr
, addr
, val
);
8566 if (insn
& (1 << 11)) {
8568 tmp
= gen_ld16u(addr
, IS_USER(s
));
8569 store_reg(s
, rd
, tmp
);
8572 tmp
= load_reg(s
, rd
);
8573 gen_st16(tmp
, addr
, IS_USER(s
));
8579 /* load/store from stack */
8580 rd
= (insn
>> 8) & 7;
8581 addr
= load_reg(s
, 13);
8582 val
= (insn
& 0xff) * 4;
8583 tcg_gen_addi_i32(addr
, addr
, val
);
8585 if (insn
& (1 << 11)) {
8587 tmp
= gen_ld32(addr
, IS_USER(s
));
8588 store_reg(s
, rd
, tmp
);
8591 tmp
= load_reg(s
, rd
);
8592 gen_st32(tmp
, addr
, IS_USER(s
));
8598 /* add to high reg */
8599 rd
= (insn
>> 8) & 7;
8600 if (insn
& (1 << 11)) {
8602 tmp
= load_reg(s
, 13);
8604 /* PC. bit 1 is ignored. */
8606 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8608 val
= (insn
& 0xff) * 4;
8609 tcg_gen_addi_i32(tmp
, tmp
, val
);
8610 store_reg(s
, rd
, tmp
);
8615 op
= (insn
>> 8) & 0xf;
8618 /* adjust stack pointer */
8619 tmp
= load_reg(s
, 13);
8620 val
= (insn
& 0x7f) * 4;
8621 if (insn
& (1 << 7))
8622 val
= -(int32_t)val
;
8623 tcg_gen_addi_i32(tmp
, tmp
, val
);
8624 store_reg(s
, 13, tmp
);
8627 case 2: /* sign/zero extend. */
8630 rm
= (insn
>> 3) & 7;
8631 tmp
= load_reg(s
, rm
);
8632 switch ((insn
>> 6) & 3) {
8633 case 0: gen_sxth(tmp
); break;
8634 case 1: gen_sxtb(tmp
); break;
8635 case 2: gen_uxth(tmp
); break;
8636 case 3: gen_uxtb(tmp
); break;
8638 store_reg(s
, rd
, tmp
);
8640 case 4: case 5: case 0xc: case 0xd:
8642 addr
= load_reg(s
, 13);
8643 if (insn
& (1 << 8))
8647 for (i
= 0; i
< 8; i
++) {
8648 if (insn
& (1 << i
))
8651 if ((insn
& (1 << 11)) == 0) {
8652 tcg_gen_addi_i32(addr
, addr
, -offset
);
8654 for (i
= 0; i
< 8; i
++) {
8655 if (insn
& (1 << i
)) {
8656 if (insn
& (1 << 11)) {
8658 tmp
= gen_ld32(addr
, IS_USER(s
));
8659 store_reg(s
, i
, tmp
);
8662 tmp
= load_reg(s
, i
);
8663 gen_st32(tmp
, addr
, IS_USER(s
));
8665 /* advance to the next address. */
8666 tcg_gen_addi_i32(addr
, addr
, 4);
8670 if (insn
& (1 << 8)) {
8671 if (insn
& (1 << 11)) {
8673 tmp
= gen_ld32(addr
, IS_USER(s
));
8674 /* don't set the pc until the rest of the instruction
8678 tmp
= load_reg(s
, 14);
8679 gen_st32(tmp
, addr
, IS_USER(s
));
8681 tcg_gen_addi_i32(addr
, addr
, 4);
8683 if ((insn
& (1 << 11)) == 0) {
8684 tcg_gen_addi_i32(addr
, addr
, -offset
);
8686 /* write back the new stack pointer */
8687 store_reg(s
, 13, addr
);
8688 /* set the new PC value */
8689 if ((insn
& 0x0900) == 0x0900)
8693 case 1: case 3: case 9: case 11: /* czb */
8695 tmp
= load_reg(s
, rm
);
8696 s
->condlabel
= gen_new_label();
8698 if (insn
& (1 << 11))
8699 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8701 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8703 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8704 val
= (uint32_t)s
->pc
+ 2;
8709 case 15: /* IT, nop-hint. */
8710 if ((insn
& 0xf) == 0) {
8711 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8715 s
->condexec_cond
= (insn
>> 4) & 0xe;
8716 s
->condexec_mask
= insn
& 0x1f;
8717 /* No actual code generated for this insn, just setup state. */
8720 case 0xe: /* bkpt */
8721 gen_set_condexec(s
);
8722 gen_set_pc_im(s
->pc
- 2);
8723 gen_exception(EXCP_BKPT
);
8724 s
->is_jmp
= DISAS_JUMP
;
8729 rn
= (insn
>> 3) & 0x7;
8731 tmp
= load_reg(s
, rn
);
8732 switch ((insn
>> 6) & 3) {
8733 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8734 case 1: gen_rev16(tmp
); break;
8735 case 3: gen_revsh(tmp
); break;
8736 default: goto illegal_op
;
8738 store_reg(s
, rd
, tmp
);
8746 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8749 addr
= tcg_const_i32(16);
8750 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8751 tcg_temp_free_i32(addr
);
8755 addr
= tcg_const_i32(17);
8756 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8757 tcg_temp_free_i32(addr
);
8759 tcg_temp_free_i32(tmp
);
8762 if (insn
& (1 << 4))
8763 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8766 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8776 /* load/store multiple */
8777 rn
= (insn
>> 8) & 0x7;
8778 addr
= load_reg(s
, rn
);
8779 for (i
= 0; i
< 8; i
++) {
8780 if (insn
& (1 << i
)) {
8781 if (insn
& (1 << 11)) {
8783 tmp
= gen_ld32(addr
, IS_USER(s
));
8784 store_reg(s
, i
, tmp
);
8787 tmp
= load_reg(s
, i
);
8788 gen_st32(tmp
, addr
, IS_USER(s
));
8790 /* advance to the next address */
8791 tcg_gen_addi_i32(addr
, addr
, 4);
8794 /* Base register writeback. */
8795 if ((insn
& (1 << rn
)) == 0) {
8796 store_reg(s
, rn
, addr
);
8803 /* conditional branch or swi */
8804 cond
= (insn
>> 8) & 0xf;
8810 gen_set_condexec(s
);
8811 gen_set_pc_im(s
->pc
);
8812 s
->is_jmp
= DISAS_SWI
;
8815 /* generate a conditional jump to next instruction */
8816 s
->condlabel
= gen_new_label();
8817 gen_test_cc(cond
^ 1, s
->condlabel
);
8820 /* jump to the offset */
8821 val
= (uint32_t)s
->pc
+ 2;
8822 offset
= ((int32_t)insn
<< 24) >> 24;
8828 if (insn
& (1 << 11)) {
8829 if (disas_thumb2_insn(env
, s
, insn
))
8833 /* unconditional branch */
8834 val
= (uint32_t)s
->pc
;
8835 offset
= ((int32_t)insn
<< 21) >> 21;
8836 val
+= (offset
<< 1) + 2;
8841 if (disas_thumb2_insn(env
, s
, insn
))
8847 gen_set_condexec(s
);
8848 gen_set_pc_im(s
->pc
- 4);
8849 gen_exception(EXCP_UDEF
);
8850 s
->is_jmp
= DISAS_JUMP
;
8854 gen_set_condexec(s
);
8855 gen_set_pc_im(s
->pc
- 2);
8856 gen_exception(EXCP_UDEF
);
8857 s
->is_jmp
= DISAS_JUMP
;
8860 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8861 basic block 'tb'. If search_pc is TRUE, also generate PC
8862 information for each intermediate instruction. */
8863 static inline void gen_intermediate_code_internal(CPUState
*env
,
8864 TranslationBlock
*tb
,
8867 DisasContext dc1
, *dc
= &dc1
;
8869 uint16_t *gen_opc_end
;
8871 target_ulong pc_start
;
8872 uint32_t next_page_start
;
8876 /* generate intermediate code */
8883 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8885 dc
->is_jmp
= DISAS_NEXT
;
8887 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8889 dc
->thumb
= env
->thumb
;
8890 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8891 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8892 #if !defined(CONFIG_USER_ONLY)
8894 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8896 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8899 cpu_F0s
= tcg_temp_new_i32();
8900 cpu_F1s
= tcg_temp_new_i32();
8901 cpu_F0d
= tcg_temp_new_i64();
8902 cpu_F1d
= tcg_temp_new_i64();
8905 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8906 cpu_M0
= tcg_temp_new_i64();
8907 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8910 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8912 max_insns
= CF_COUNT_MASK
;
8915 /* Reset the conditional execution bits immediately. This avoids
8916 complications trying to do it at the end of the block. */
8917 if (env
->condexec_bits
)
8919 TCGv tmp
= new_tmp();
8920 tcg_gen_movi_i32(tmp
, 0);
8921 store_cpu_field(tmp
, condexec_bits
);
8924 #ifdef CONFIG_USER_ONLY
8925 /* Intercept jump to the magic kernel page. */
8926 if (dc
->pc
>= 0xffff0000) {
8927 /* We always get here via a jump, so know we are not in a
8928 conditional execution block. */
8929 gen_exception(EXCP_KERNEL_TRAP
);
8930 dc
->is_jmp
= DISAS_UPDATE
;
8934 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8935 /* We always get here via a jump, so know we are not in a
8936 conditional execution block. */
8937 gen_exception(EXCP_EXCEPTION_EXIT
);
8938 dc
->is_jmp
= DISAS_UPDATE
;
8943 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8944 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8945 if (bp
->pc
== dc
->pc
) {
8946 gen_set_condexec(dc
);
8947 gen_set_pc_im(dc
->pc
);
8948 gen_exception(EXCP_DEBUG
);
8949 dc
->is_jmp
= DISAS_JUMP
;
8950 /* Advance PC so that clearing the breakpoint will
8951 invalidate this TB. */
8953 goto done_generating
;
8959 j
= gen_opc_ptr
- gen_opc_buf
;
8963 gen_opc_instr_start
[lj
++] = 0;
8965 gen_opc_pc
[lj
] = dc
->pc
;
8966 gen_opc_instr_start
[lj
] = 1;
8967 gen_opc_icount
[lj
] = num_insns
;
8970 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8974 disas_thumb_insn(env
, dc
);
8975 if (dc
->condexec_mask
) {
8976 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8977 | ((dc
->condexec_mask
>> 4) & 1);
8978 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8979 if (dc
->condexec_mask
== 0) {
8980 dc
->condexec_cond
= 0;
8984 disas_arm_insn(env
, dc
);
8987 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8991 if (dc
->condjmp
&& !dc
->is_jmp
) {
8992 gen_set_label(dc
->condlabel
);
8995 /* Translation stops when a conditional branch is encountered.
8996 * Otherwise the subsequent code could get translated several times.
8997 * Also stop translation when a page boundary is reached. This
8998 * ensures prefetch aborts occur at the right place. */
9000 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9001 !env
->singlestep_enabled
&&
9003 dc
->pc
< next_page_start
&&
9004 num_insns
< max_insns
);
9006 if (tb
->cflags
& CF_LAST_IO
) {
9008 /* FIXME: This can theoretically happen with self-modifying
9010 cpu_abort(env
, "IO on conditional branch instruction");
9015 /* At this stage dc->condjmp will only be set when the skipped
9016 instruction was a conditional branch or trap, and the PC has
9017 already been written. */
9018 if (unlikely(env
->singlestep_enabled
)) {
9019 /* Make sure the pc is updated, and raise a debug exception. */
9021 gen_set_condexec(dc
);
9022 if (dc
->is_jmp
== DISAS_SWI
) {
9023 gen_exception(EXCP_SWI
);
9025 gen_exception(EXCP_DEBUG
);
9027 gen_set_label(dc
->condlabel
);
9029 if (dc
->condjmp
|| !dc
->is_jmp
) {
9030 gen_set_pc_im(dc
->pc
);
9033 gen_set_condexec(dc
);
9034 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9035 gen_exception(EXCP_SWI
);
9037 /* FIXME: Single stepping a WFI insn will not halt
9039 gen_exception(EXCP_DEBUG
);
9042 /* While branches must always occur at the end of an IT block,
9043 there are a few other things that can cause us to terminate
9044 the TB in the middel of an IT block:
9045 - Exception generating instructions (bkpt, swi, undefined).
9047 - Hardware watchpoints.
9048 Hardware breakpoints have already been handled and skip this code.
9050 gen_set_condexec(dc
);
9051 switch(dc
->is_jmp
) {
9053 gen_goto_tb(dc
, 1, dc
->pc
);
9058 /* indicate that the hash table must be used to find the next TB */
9062 /* nothing more to generate */
9068 gen_exception(EXCP_SWI
);
9072 gen_set_label(dc
->condlabel
);
9073 gen_set_condexec(dc
);
9074 gen_goto_tb(dc
, 1, dc
->pc
);
9080 gen_icount_end(tb
, num_insns
);
9081 *gen_opc_ptr
= INDEX_op_end
;
9084 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9085 qemu_log("----------------\n");
9086 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9087 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9092 j
= gen_opc_ptr
- gen_opc_buf
;
9095 gen_opc_instr_start
[lj
++] = 0;
9097 tb
->size
= dc
->pc
- pc_start
;
9098 tb
->icount
= num_insns
;
9102 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9104 gen_intermediate_code_internal(env
, tb
, 0);
9107 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9109 gen_intermediate_code_internal(env
, tb
, 1);
9112 static const char *cpu_mode_names
[16] = {
9113 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9114 "???", "???", "???", "und", "???", "???", "???", "sys"
9117 void cpu_dump_state(CPUState
*env
, FILE *f
,
9118 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9128 /* ??? This assumes float64 and double have the same layout.
9129 Oh well, it's only debug dumps. */
9138 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9140 cpu_fprintf(f
, "\n");
9142 cpu_fprintf(f
, " ");
9144 psr
= cpsr_read(env
);
9145 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9147 psr
& (1 << 31) ? 'N' : '-',
9148 psr
& (1 << 30) ? 'Z' : '-',
9149 psr
& (1 << 29) ? 'C' : '-',
9150 psr
& (1 << 28) ? 'V' : '-',
9151 psr
& CPSR_T
? 'T' : 'A',
9152 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9155 for (i
= 0; i
< 16; i
++) {
9156 d
.d
= env
->vfp
.regs
[i
];
9160 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9161 i
* 2, (int)s0
.i
, s0
.s
,
9162 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9163 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9166 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9170 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9171 unsigned long searched_pc
, int pc_pos
, void *puc
)
9173 env
->regs
[15] = gen_opc_pc
[pc_pos
];