4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
79 static TCGv_i32 cpu_exclusive_addr
;
80 static TCGv_i32 cpu_exclusive_val
;
81 static TCGv_i32 cpu_exclusive_high
;
82 #ifdef CONFIG_USER_ONLY
83 static TCGv_i32 cpu_exclusive_test
;
84 static TCGv_i32 cpu_exclusive_info
;
87 /* FIXME: These should be removed. */
88 static TCGv cpu_F0s
, cpu_F1s
;
89 static TCGv_i64 cpu_F0d
, cpu_F1d
;
91 #include "gen-icount.h"
93 static const char *regnames
[] =
94 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
95 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
97 /* initialize TCG globals. */
98 void arm_translate_init(void)
102 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
104 for (i
= 0; i
< 16; i
++) {
105 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
106 offsetof(CPUState
, regs
[i
]),
109 cpu_exclusive_addr
= tcg_global_mem_new_i32(TCG_AREG0
,
110 offsetof(CPUState
, exclusive_addr
), "exclusive_addr");
111 cpu_exclusive_val
= tcg_global_mem_new_i32(TCG_AREG0
,
112 offsetof(CPUState
, exclusive_val
), "exclusive_val");
113 cpu_exclusive_high
= tcg_global_mem_new_i32(TCG_AREG0
,
114 offsetof(CPUState
, exclusive_high
), "exclusive_high");
115 #ifdef CONFIG_USER_ONLY
116 cpu_exclusive_test
= tcg_global_mem_new_i32(TCG_AREG0
,
117 offsetof(CPUState
, exclusive_test
), "exclusive_test");
118 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
119 offsetof(CPUState
, exclusive_info
), "exclusive_info");
126 static int num_temps
;
128 /* Allocate a temporary variable. */
129 static TCGv_i32
new_tmp(void)
132 return tcg_temp_new_i32();
135 /* Release a temporary variable. */
136 static void dead_tmp(TCGv tmp
)
142 static inline TCGv
load_cpu_offset(int offset
)
144 TCGv tmp
= new_tmp();
145 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
149 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
151 static inline void store_cpu_offset(TCGv var
, int offset
)
153 tcg_gen_st_i32(var
, cpu_env
, offset
);
157 #define store_cpu_field(var, name) \
158 store_cpu_offset(var, offsetof(CPUState, name))
160 /* Set a variable to the value of a CPU register. */
161 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
165 /* normaly, since we updated PC, we need only to add one insn */
167 addr
= (long)s
->pc
+ 2;
169 addr
= (long)s
->pc
+ 4;
170 tcg_gen_movi_i32(var
, addr
);
172 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
176 /* Create a new temporary and set it to the value of a CPU register. */
177 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
179 TCGv tmp
= new_tmp();
180 load_reg_var(s
, tmp
, reg
);
184 /* Set a CPU register. The source must be a temporary and will be
186 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
189 tcg_gen_andi_i32(var
, var
, ~1);
190 s
->is_jmp
= DISAS_JUMP
;
192 tcg_gen_mov_i32(cpu_R
[reg
], var
);
196 /* Value extensions. */
197 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
198 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
199 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
200 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
202 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
203 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
206 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
208 TCGv tmp_mask
= tcg_const_i32(mask
);
209 gen_helper_cpsr_write(var
, tmp_mask
);
210 tcg_temp_free_i32(tmp_mask
);
212 /* Set NZCV flags from the high 4 bits of var. */
213 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
215 static void gen_exception(int excp
)
217 TCGv tmp
= new_tmp();
218 tcg_gen_movi_i32(tmp
, excp
);
219 gen_helper_exception(tmp
);
223 static void gen_smul_dual(TCGv a
, TCGv b
)
225 TCGv tmp1
= new_tmp();
226 TCGv tmp2
= new_tmp();
227 tcg_gen_ext16s_i32(tmp1
, a
);
228 tcg_gen_ext16s_i32(tmp2
, b
);
229 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
231 tcg_gen_sari_i32(a
, a
, 16);
232 tcg_gen_sari_i32(b
, b
, 16);
233 tcg_gen_mul_i32(b
, b
, a
);
234 tcg_gen_mov_i32(a
, tmp1
);
238 /* Byteswap each halfword. */
239 static void gen_rev16(TCGv var
)
241 TCGv tmp
= new_tmp();
242 tcg_gen_shri_i32(tmp
, var
, 8);
243 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
244 tcg_gen_shli_i32(var
, var
, 8);
245 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
246 tcg_gen_or_i32(var
, var
, tmp
);
250 /* Byteswap low halfword and sign extend. */
251 static void gen_revsh(TCGv var
)
253 TCGv tmp
= new_tmp();
254 tcg_gen_shri_i32(tmp
, var
, 8);
255 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
256 tcg_gen_shli_i32(var
, var
, 8);
257 tcg_gen_ext8s_i32(var
, var
);
258 tcg_gen_or_i32(var
, var
, tmp
);
262 /* Unsigned bitfield extract. */
263 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
266 tcg_gen_shri_i32(var
, var
, shift
);
267 tcg_gen_andi_i32(var
, var
, mask
);
270 /* Signed bitfield extract. */
271 static void gen_sbfx(TCGv var
, int shift
, int width
)
276 tcg_gen_sari_i32(var
, var
, shift
);
277 if (shift
+ width
< 32) {
278 signbit
= 1u << (width
- 1);
279 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
280 tcg_gen_xori_i32(var
, var
, signbit
);
281 tcg_gen_subi_i32(var
, var
, signbit
);
285 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
286 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
288 tcg_gen_andi_i32(val
, val
, mask
);
289 tcg_gen_shli_i32(val
, val
, shift
);
290 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
291 tcg_gen_or_i32(dest
, base
, val
);
294 /* Round the top 32 bits of a 64-bit value. */
295 static void gen_roundqd(TCGv a
, TCGv b
)
297 tcg_gen_shri_i32(a
, a
, 31);
298 tcg_gen_add_i32(a
, a
, b
);
301 /* FIXME: Most targets have native widening multiplication.
302 It would be good to use that instead of a full wide multiply. */
303 /* 32x32->64 multiply. Marks inputs as dead. */
304 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
306 TCGv_i64 tmp1
= tcg_temp_new_i64();
307 TCGv_i64 tmp2
= tcg_temp_new_i64();
309 tcg_gen_extu_i32_i64(tmp1
, a
);
311 tcg_gen_extu_i32_i64(tmp2
, b
);
313 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
314 tcg_temp_free_i64(tmp2
);
318 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
320 TCGv_i64 tmp1
= tcg_temp_new_i64();
321 TCGv_i64 tmp2
= tcg_temp_new_i64();
323 tcg_gen_ext_i32_i64(tmp1
, a
);
325 tcg_gen_ext_i32_i64(tmp2
, b
);
327 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
328 tcg_temp_free_i64(tmp2
);
332 /* Signed 32x32->64 multiply. */
333 static void gen_imull(TCGv a
, TCGv b
)
335 TCGv_i64 tmp1
= tcg_temp_new_i64();
336 TCGv_i64 tmp2
= tcg_temp_new_i64();
338 tcg_gen_ext_i32_i64(tmp1
, a
);
339 tcg_gen_ext_i32_i64(tmp2
, b
);
340 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
341 tcg_temp_free_i64(tmp2
);
342 tcg_gen_trunc_i64_i32(a
, tmp1
);
343 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
344 tcg_gen_trunc_i64_i32(b
, tmp1
);
345 tcg_temp_free_i64(tmp1
);
348 /* Swap low and high halfwords. */
349 static void gen_swap_half(TCGv var
)
351 TCGv tmp
= new_tmp();
352 tcg_gen_shri_i32(tmp
, var
, 16);
353 tcg_gen_shli_i32(var
, var
, 16);
354 tcg_gen_or_i32(var
, var
, tmp
);
358 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
359 tmp = (t0 ^ t1) & 0x8000;
362 t0 = (t0 + t1) ^ tmp;
365 static void gen_add16(TCGv t0
, TCGv t1
)
367 TCGv tmp
= new_tmp();
368 tcg_gen_xor_i32(tmp
, t0
, t1
);
369 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
370 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
371 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
372 tcg_gen_add_i32(t0
, t0
, t1
);
373 tcg_gen_xor_i32(t0
, t0
, tmp
);
378 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
380 /* Set CF to the top bit of var. */
381 static void gen_set_CF_bit31(TCGv var
)
383 TCGv tmp
= new_tmp();
384 tcg_gen_shri_i32(tmp
, var
, 31);
389 /* Set N and Z flags from var. */
390 static inline void gen_logic_CC(TCGv var
)
392 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
393 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
397 static void gen_adc(TCGv t0
, TCGv t1
)
400 tcg_gen_add_i32(t0
, t0
, t1
);
401 tmp
= load_cpu_field(CF
);
402 tcg_gen_add_i32(t0
, t0
, tmp
);
406 /* dest = T0 + T1 + CF. */
407 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
410 tcg_gen_add_i32(dest
, t0
, t1
);
411 tmp
= load_cpu_field(CF
);
412 tcg_gen_add_i32(dest
, dest
, tmp
);
416 /* dest = T0 - T1 + CF - 1. */
417 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
420 tcg_gen_sub_i32(dest
, t0
, t1
);
421 tmp
= load_cpu_field(CF
);
422 tcg_gen_add_i32(dest
, dest
, tmp
);
423 tcg_gen_subi_i32(dest
, dest
, 1);
427 /* FIXME: Implement this natively. */
428 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
430 static void shifter_out_im(TCGv var
, int shift
)
432 TCGv tmp
= new_tmp();
434 tcg_gen_andi_i32(tmp
, var
, 1);
436 tcg_gen_shri_i32(tmp
, var
, shift
);
438 tcg_gen_andi_i32(tmp
, tmp
, 1);
444 /* Shift by immediate. Includes special handling for shift == 0. */
445 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
451 shifter_out_im(var
, 32 - shift
);
452 tcg_gen_shli_i32(var
, var
, shift
);
458 tcg_gen_shri_i32(var
, var
, 31);
461 tcg_gen_movi_i32(var
, 0);
464 shifter_out_im(var
, shift
- 1);
465 tcg_gen_shri_i32(var
, var
, shift
);
472 shifter_out_im(var
, shift
- 1);
475 tcg_gen_sari_i32(var
, var
, shift
);
477 case 3: /* ROR/RRX */
480 shifter_out_im(var
, shift
- 1);
481 tcg_gen_rotri_i32(var
, var
, shift
); break;
483 TCGv tmp
= load_cpu_field(CF
);
485 shifter_out_im(var
, 0);
486 tcg_gen_shri_i32(var
, var
, 1);
487 tcg_gen_shli_i32(tmp
, tmp
, 31);
488 tcg_gen_or_i32(var
, var
, tmp
);
494 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
495 TCGv shift
, int flags
)
499 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
500 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
501 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
502 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
506 case 0: gen_helper_shl(var
, var
, shift
); break;
507 case 1: gen_helper_shr(var
, var
, shift
); break;
508 case 2: gen_helper_sar(var
, var
, shift
); break;
509 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
510 tcg_gen_rotr_i32(var
, var
, shift
); break;
516 #define PAS_OP(pfx) \
518 case 0: gen_pas_helper(glue(pfx,add16)); break; \
519 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
520 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
521 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
522 case 4: gen_pas_helper(glue(pfx,add8)); break; \
523 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
525 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
530 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
532 tmp
= tcg_temp_new_ptr();
533 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
535 tcg_temp_free_ptr(tmp
);
538 tmp
= tcg_temp_new_ptr();
539 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
541 tcg_temp_free_ptr(tmp
);
543 #undef gen_pas_helper
544 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
557 #undef gen_pas_helper
562 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
563 #define PAS_OP(pfx) \
565 case 0: gen_pas_helper(glue(pfx,add8)); break; \
566 case 1: gen_pas_helper(glue(pfx,add16)); break; \
567 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
568 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
569 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
570 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
572 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
577 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
579 tmp
= tcg_temp_new_ptr();
580 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
582 tcg_temp_free_ptr(tmp
);
585 tmp
= tcg_temp_new_ptr();
586 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
588 tcg_temp_free_ptr(tmp
);
590 #undef gen_pas_helper
591 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
604 #undef gen_pas_helper
609 static void gen_test_cc(int cc
, int label
)
617 tmp
= load_cpu_field(ZF
);
618 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
621 tmp
= load_cpu_field(ZF
);
622 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
625 tmp
= load_cpu_field(CF
);
626 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
629 tmp
= load_cpu_field(CF
);
630 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
633 tmp
= load_cpu_field(NF
);
634 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
637 tmp
= load_cpu_field(NF
);
638 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
641 tmp
= load_cpu_field(VF
);
642 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
645 tmp
= load_cpu_field(VF
);
646 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
648 case 8: /* hi: C && !Z */
649 inv
= gen_new_label();
650 tmp
= load_cpu_field(CF
);
651 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
653 tmp
= load_cpu_field(ZF
);
654 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
657 case 9: /* ls: !C || Z */
658 tmp
= load_cpu_field(CF
);
659 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
661 tmp
= load_cpu_field(ZF
);
662 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
664 case 10: /* ge: N == V -> N ^ V == 0 */
665 tmp
= load_cpu_field(VF
);
666 tmp2
= load_cpu_field(NF
);
667 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
669 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
671 case 11: /* lt: N != V -> N ^ V != 0 */
672 tmp
= load_cpu_field(VF
);
673 tmp2
= load_cpu_field(NF
);
674 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
676 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
678 case 12: /* gt: !Z && N == V */
679 inv
= gen_new_label();
680 tmp
= load_cpu_field(ZF
);
681 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
683 tmp
= load_cpu_field(VF
);
684 tmp2
= load_cpu_field(NF
);
685 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
687 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
690 case 13: /* le: Z || N != V */
691 tmp
= load_cpu_field(ZF
);
692 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
694 tmp
= load_cpu_field(VF
);
695 tmp2
= load_cpu_field(NF
);
696 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
698 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
701 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
707 static const uint8_t table_logic_cc
[16] = {
726 /* Set PC and Thumb state from an immediate address. */
727 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
731 s
->is_jmp
= DISAS_UPDATE
;
732 if (s
->thumb
!= (addr
& 1)) {
734 tcg_gen_movi_i32(tmp
, addr
& 1);
735 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
738 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
741 /* Set PC and Thumb state from var. var is marked as dead. */
742 static inline void gen_bx(DisasContext
*s
, TCGv var
)
744 s
->is_jmp
= DISAS_UPDATE
;
745 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
746 tcg_gen_andi_i32(var
, var
, 1);
747 store_cpu_field(var
, thumb
);
750 /* Variant of store_reg which uses branch&exchange logic when storing
751 to r15 in ARM architecture v7 and above. The source must be a temporary
752 and will be marked as dead. */
753 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
756 if (reg
== 15 && ENABLE_ARCH_7
) {
759 store_reg(s
, reg
, var
);
763 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
765 TCGv tmp
= new_tmp();
766 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
769 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
771 TCGv tmp
= new_tmp();
772 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
775 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
777 TCGv tmp
= new_tmp();
778 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
781 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
783 TCGv tmp
= new_tmp();
784 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
787 static inline TCGv
gen_ld32(TCGv addr
, int index
)
789 TCGv tmp
= new_tmp();
790 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
793 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
795 TCGv_i64 tmp
= tcg_temp_new_i64();
796 tcg_gen_qemu_ld64(tmp
, addr
, index
);
799 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
801 tcg_gen_qemu_st8(val
, addr
, index
);
804 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
806 tcg_gen_qemu_st16(val
, addr
, index
);
809 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
811 tcg_gen_qemu_st32(val
, addr
, index
);
814 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
816 tcg_gen_qemu_st64(val
, addr
, index
);
817 tcg_temp_free_i64(val
);
820 static inline void gen_set_pc_im(uint32_t val
)
822 tcg_gen_movi_i32(cpu_R
[15], val
);
825 /* Force a TB lookup after an instruction that changes the CPU state. */
826 static inline void gen_lookup_tb(DisasContext
*s
)
828 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
829 s
->is_jmp
= DISAS_UPDATE
;
832 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
835 int val
, rm
, shift
, shiftop
;
838 if (!(insn
& (1 << 25))) {
841 if (!(insn
& (1 << 23)))
844 tcg_gen_addi_i32(var
, var
, val
);
848 shift
= (insn
>> 7) & 0x1f;
849 shiftop
= (insn
>> 5) & 3;
850 offset
= load_reg(s
, rm
);
851 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
852 if (!(insn
& (1 << 23)))
853 tcg_gen_sub_i32(var
, var
, offset
);
855 tcg_gen_add_i32(var
, var
, offset
);
860 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
866 if (insn
& (1 << 22)) {
868 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
869 if (!(insn
& (1 << 23)))
873 tcg_gen_addi_i32(var
, var
, val
);
877 tcg_gen_addi_i32(var
, var
, extra
);
879 offset
= load_reg(s
, rm
);
880 if (!(insn
& (1 << 23)))
881 tcg_gen_sub_i32(var
, var
, offset
);
883 tcg_gen_add_i32(var
, var
, offset
);
888 #define VFP_OP2(name) \
889 static inline void gen_vfp_##name(int dp) \
892 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
894 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
904 static inline void gen_vfp_abs(int dp
)
907 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
909 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
912 static inline void gen_vfp_neg(int dp
)
915 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
917 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
920 static inline void gen_vfp_sqrt(int dp
)
923 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
925 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
928 static inline void gen_vfp_cmp(int dp
)
931 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
933 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
936 static inline void gen_vfp_cmpe(int dp
)
939 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
941 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
944 static inline void gen_vfp_F1_ld0(int dp
)
947 tcg_gen_movi_i64(cpu_F1d
, 0);
949 tcg_gen_movi_i32(cpu_F1s
, 0);
952 static inline void gen_vfp_uito(int dp
)
955 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
957 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
960 static inline void gen_vfp_sito(int dp
)
963 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
965 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
968 static inline void gen_vfp_toui(int dp
)
971 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
973 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
976 static inline void gen_vfp_touiz(int dp
)
979 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
981 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
984 static inline void gen_vfp_tosi(int dp
)
987 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
989 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
992 static inline void gen_vfp_tosiz(int dp
)
995 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
997 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1000 #define VFP_GEN_FIX(name) \
1001 static inline void gen_vfp_##name(int dp, int shift) \
1003 TCGv tmp_shift = tcg_const_i32(shift); \
1005 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1007 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1008 tcg_temp_free_i32(tmp_shift); \
1020 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1023 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1025 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1028 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1031 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1033 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1037 vfp_reg_offset (int dp
, int reg
)
1040 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1042 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1043 + offsetof(CPU_DoubleU
, l
.upper
);
1045 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1046 + offsetof(CPU_DoubleU
, l
.lower
);
1050 /* Return the offset of a 32-bit piece of a NEON register.
1051 zero is the least significant end of the register. */
1053 neon_reg_offset (int reg
, int n
)
1057 return vfp_reg_offset(0, sreg
);
1060 static TCGv
neon_load_reg(int reg
, int pass
)
1062 TCGv tmp
= new_tmp();
1063 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1067 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1069 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1073 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1075 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1078 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1080 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1083 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1084 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1085 #define tcg_gen_st_f32 tcg_gen_st_i32
1086 #define tcg_gen_st_f64 tcg_gen_st_i64
1088 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1091 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1093 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1096 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1099 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1101 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1104 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1107 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1109 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1112 #define ARM_CP_RW_BIT (1 << 20)
1114 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1116 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1119 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1121 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1124 static inline TCGv
iwmmxt_load_creg(int reg
)
1126 TCGv var
= new_tmp();
1127 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1131 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1133 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1137 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1139 iwmmxt_store_reg(cpu_M0
, rn
);
1142 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1144 iwmmxt_load_reg(cpu_M0
, rn
);
1147 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1149 iwmmxt_load_reg(cpu_V1
, rn
);
1150 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1153 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1155 iwmmxt_load_reg(cpu_V1
, rn
);
1156 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1159 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1161 iwmmxt_load_reg(cpu_V1
, rn
);
1162 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1165 #define IWMMXT_OP(name) \
1166 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1168 iwmmxt_load_reg(cpu_V1, rn); \
1169 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1172 #define IWMMXT_OP_ENV(name) \
1173 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1175 iwmmxt_load_reg(cpu_V1, rn); \
1176 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1179 #define IWMMXT_OP_ENV_SIZE(name) \
1180 IWMMXT_OP_ENV(name##b) \
1181 IWMMXT_OP_ENV(name##w) \
1182 IWMMXT_OP_ENV(name##l)
1184 #define IWMMXT_OP_ENV1(name) \
1185 static inline void gen_op_iwmmxt_##name##_M0(void) \
1187 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1201 IWMMXT_OP_ENV_SIZE(unpackl
)
1202 IWMMXT_OP_ENV_SIZE(unpackh
)
1204 IWMMXT_OP_ENV1(unpacklub
)
1205 IWMMXT_OP_ENV1(unpackluw
)
1206 IWMMXT_OP_ENV1(unpacklul
)
1207 IWMMXT_OP_ENV1(unpackhub
)
1208 IWMMXT_OP_ENV1(unpackhuw
)
1209 IWMMXT_OP_ENV1(unpackhul
)
1210 IWMMXT_OP_ENV1(unpacklsb
)
1211 IWMMXT_OP_ENV1(unpacklsw
)
1212 IWMMXT_OP_ENV1(unpacklsl
)
1213 IWMMXT_OP_ENV1(unpackhsb
)
1214 IWMMXT_OP_ENV1(unpackhsw
)
1215 IWMMXT_OP_ENV1(unpackhsl
)
1217 IWMMXT_OP_ENV_SIZE(cmpeq
)
1218 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1219 IWMMXT_OP_ENV_SIZE(cmpgts
)
1221 IWMMXT_OP_ENV_SIZE(mins
)
1222 IWMMXT_OP_ENV_SIZE(minu
)
1223 IWMMXT_OP_ENV_SIZE(maxs
)
1224 IWMMXT_OP_ENV_SIZE(maxu
)
1226 IWMMXT_OP_ENV_SIZE(subn
)
1227 IWMMXT_OP_ENV_SIZE(addn
)
1228 IWMMXT_OP_ENV_SIZE(subu
)
1229 IWMMXT_OP_ENV_SIZE(addu
)
1230 IWMMXT_OP_ENV_SIZE(subs
)
1231 IWMMXT_OP_ENV_SIZE(adds
)
1233 IWMMXT_OP_ENV(avgb0
)
1234 IWMMXT_OP_ENV(avgb1
)
1235 IWMMXT_OP_ENV(avgw0
)
1236 IWMMXT_OP_ENV(avgw1
)
1240 IWMMXT_OP_ENV(packuw
)
1241 IWMMXT_OP_ENV(packul
)
1242 IWMMXT_OP_ENV(packuq
)
1243 IWMMXT_OP_ENV(packsw
)
1244 IWMMXT_OP_ENV(packsl
)
1245 IWMMXT_OP_ENV(packsq
)
1247 static void gen_op_iwmmxt_set_mup(void)
1250 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1251 tcg_gen_ori_i32(tmp
, tmp
, 2);
1252 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1255 static void gen_op_iwmmxt_set_cup(void)
1258 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1259 tcg_gen_ori_i32(tmp
, tmp
, 1);
1260 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1263 static void gen_op_iwmmxt_setpsr_nz(void)
1265 TCGv tmp
= new_tmp();
1266 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1267 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1270 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1272 iwmmxt_load_reg(cpu_V1
, rn
);
1273 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1274 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1277 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1283 rd
= (insn
>> 16) & 0xf;
1284 tmp
= load_reg(s
, rd
);
1286 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1287 if (insn
& (1 << 24)) {
1289 if (insn
& (1 << 23))
1290 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1292 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1293 tcg_gen_mov_i32(dest
, tmp
);
1294 if (insn
& (1 << 21))
1295 store_reg(s
, rd
, tmp
);
1298 } else if (insn
& (1 << 21)) {
1300 tcg_gen_mov_i32(dest
, tmp
);
1301 if (insn
& (1 << 23))
1302 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1304 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1305 store_reg(s
, rd
, tmp
);
1306 } else if (!(insn
& (1 << 23)))
1311 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1313 int rd
= (insn
>> 0) & 0xf;
1316 if (insn
& (1 << 8)) {
1317 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1320 tmp
= iwmmxt_load_creg(rd
);
1324 iwmmxt_load_reg(cpu_V0
, rd
);
1325 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1327 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1328 tcg_gen_mov_i32(dest
, tmp
);
1333 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1334 (ie. an undefined instruction). */
1335 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1338 int rdhi
, rdlo
, rd0
, rd1
, i
;
1340 TCGv tmp
, tmp2
, tmp3
;
1342 if ((insn
& 0x0e000e00) == 0x0c000000) {
1343 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1345 rdlo
= (insn
>> 12) & 0xf;
1346 rdhi
= (insn
>> 16) & 0xf;
1347 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1348 iwmmxt_load_reg(cpu_V0
, wrd
);
1349 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1350 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1351 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1352 } else { /* TMCRR */
1353 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1354 iwmmxt_store_reg(cpu_V0
, wrd
);
1355 gen_op_iwmmxt_set_mup();
1360 wrd
= (insn
>> 12) & 0xf;
1362 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1366 if (insn
& ARM_CP_RW_BIT
) {
1367 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1369 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1370 iwmmxt_store_creg(wrd
, tmp
);
1373 if (insn
& (1 << 8)) {
1374 if (insn
& (1 << 22)) { /* WLDRD */
1375 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1377 } else { /* WLDRW wRd */
1378 tmp
= gen_ld32(addr
, IS_USER(s
));
1381 if (insn
& (1 << 22)) { /* WLDRH */
1382 tmp
= gen_ld16u(addr
, IS_USER(s
));
1383 } else { /* WLDRB */
1384 tmp
= gen_ld8u(addr
, IS_USER(s
));
1388 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1391 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1394 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1395 tmp
= iwmmxt_load_creg(wrd
);
1396 gen_st32(tmp
, addr
, IS_USER(s
));
1398 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1400 if (insn
& (1 << 8)) {
1401 if (insn
& (1 << 22)) { /* WSTRD */
1403 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1404 } else { /* WSTRW wRd */
1405 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1406 gen_st32(tmp
, addr
, IS_USER(s
));
1409 if (insn
& (1 << 22)) { /* WSTRH */
1410 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1411 gen_st16(tmp
, addr
, IS_USER(s
));
1412 } else { /* WSTRB */
1413 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1414 gen_st8(tmp
, addr
, IS_USER(s
));
1423 if ((insn
& 0x0f000000) != 0x0e000000)
1426 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1427 case 0x000: /* WOR */
1428 wrd
= (insn
>> 12) & 0xf;
1429 rd0
= (insn
>> 0) & 0xf;
1430 rd1
= (insn
>> 16) & 0xf;
1431 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1432 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1433 gen_op_iwmmxt_setpsr_nz();
1434 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1435 gen_op_iwmmxt_set_mup();
1436 gen_op_iwmmxt_set_cup();
1438 case 0x011: /* TMCR */
1441 rd
= (insn
>> 12) & 0xf;
1442 wrd
= (insn
>> 16) & 0xf;
1444 case ARM_IWMMXT_wCID
:
1445 case ARM_IWMMXT_wCASF
:
1447 case ARM_IWMMXT_wCon
:
1448 gen_op_iwmmxt_set_cup();
1450 case ARM_IWMMXT_wCSSF
:
1451 tmp
= iwmmxt_load_creg(wrd
);
1452 tmp2
= load_reg(s
, rd
);
1453 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1455 iwmmxt_store_creg(wrd
, tmp
);
1457 case ARM_IWMMXT_wCGR0
:
1458 case ARM_IWMMXT_wCGR1
:
1459 case ARM_IWMMXT_wCGR2
:
1460 case ARM_IWMMXT_wCGR3
:
1461 gen_op_iwmmxt_set_cup();
1462 tmp
= load_reg(s
, rd
);
1463 iwmmxt_store_creg(wrd
, tmp
);
1469 case 0x100: /* WXOR */
1470 wrd
= (insn
>> 12) & 0xf;
1471 rd0
= (insn
>> 0) & 0xf;
1472 rd1
= (insn
>> 16) & 0xf;
1473 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1474 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1475 gen_op_iwmmxt_setpsr_nz();
1476 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1477 gen_op_iwmmxt_set_mup();
1478 gen_op_iwmmxt_set_cup();
1480 case 0x111: /* TMRC */
1483 rd
= (insn
>> 12) & 0xf;
1484 wrd
= (insn
>> 16) & 0xf;
1485 tmp
= iwmmxt_load_creg(wrd
);
1486 store_reg(s
, rd
, tmp
);
1488 case 0x300: /* WANDN */
1489 wrd
= (insn
>> 12) & 0xf;
1490 rd0
= (insn
>> 0) & 0xf;
1491 rd1
= (insn
>> 16) & 0xf;
1492 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1493 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1494 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1495 gen_op_iwmmxt_setpsr_nz();
1496 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1497 gen_op_iwmmxt_set_mup();
1498 gen_op_iwmmxt_set_cup();
1500 case 0x200: /* WAND */
1501 wrd
= (insn
>> 12) & 0xf;
1502 rd0
= (insn
>> 0) & 0xf;
1503 rd1
= (insn
>> 16) & 0xf;
1504 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1505 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1506 gen_op_iwmmxt_setpsr_nz();
1507 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1508 gen_op_iwmmxt_set_mup();
1509 gen_op_iwmmxt_set_cup();
1511 case 0x810: case 0xa10: /* WMADD */
1512 wrd
= (insn
>> 12) & 0xf;
1513 rd0
= (insn
>> 0) & 0xf;
1514 rd1
= (insn
>> 16) & 0xf;
1515 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1516 if (insn
& (1 << 21))
1517 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1519 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1520 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1521 gen_op_iwmmxt_set_mup();
1523 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1524 wrd
= (insn
>> 12) & 0xf;
1525 rd0
= (insn
>> 16) & 0xf;
1526 rd1
= (insn
>> 0) & 0xf;
1527 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1528 switch ((insn
>> 22) & 3) {
1530 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1533 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1536 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1541 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1542 gen_op_iwmmxt_set_mup();
1543 gen_op_iwmmxt_set_cup();
1545 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1546 wrd
= (insn
>> 12) & 0xf;
1547 rd0
= (insn
>> 16) & 0xf;
1548 rd1
= (insn
>> 0) & 0xf;
1549 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1550 switch ((insn
>> 22) & 3) {
1552 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1555 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1558 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1563 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1564 gen_op_iwmmxt_set_mup();
1565 gen_op_iwmmxt_set_cup();
1567 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1568 wrd
= (insn
>> 12) & 0xf;
1569 rd0
= (insn
>> 16) & 0xf;
1570 rd1
= (insn
>> 0) & 0xf;
1571 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1572 if (insn
& (1 << 22))
1573 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1575 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1576 if (!(insn
& (1 << 20)))
1577 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1578 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1579 gen_op_iwmmxt_set_mup();
1581 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1582 wrd
= (insn
>> 12) & 0xf;
1583 rd0
= (insn
>> 16) & 0xf;
1584 rd1
= (insn
>> 0) & 0xf;
1585 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1586 if (insn
& (1 << 21)) {
1587 if (insn
& (1 << 20))
1588 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1590 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1592 if (insn
& (1 << 20))
1593 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1595 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1597 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1598 gen_op_iwmmxt_set_mup();
1600 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1601 wrd
= (insn
>> 12) & 0xf;
1602 rd0
= (insn
>> 16) & 0xf;
1603 rd1
= (insn
>> 0) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1605 if (insn
& (1 << 21))
1606 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1608 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1609 if (!(insn
& (1 << 20))) {
1610 iwmmxt_load_reg(cpu_V1
, wrd
);
1611 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1613 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1614 gen_op_iwmmxt_set_mup();
1616 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1617 wrd
= (insn
>> 12) & 0xf;
1618 rd0
= (insn
>> 16) & 0xf;
1619 rd1
= (insn
>> 0) & 0xf;
1620 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1621 switch ((insn
>> 22) & 3) {
1623 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1626 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1629 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1634 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1635 gen_op_iwmmxt_set_mup();
1636 gen_op_iwmmxt_set_cup();
1638 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1639 wrd
= (insn
>> 12) & 0xf;
1640 rd0
= (insn
>> 16) & 0xf;
1641 rd1
= (insn
>> 0) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1643 if (insn
& (1 << 22)) {
1644 if (insn
& (1 << 20))
1645 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1647 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1649 if (insn
& (1 << 20))
1650 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1652 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1654 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1655 gen_op_iwmmxt_set_mup();
1656 gen_op_iwmmxt_set_cup();
1658 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1659 wrd
= (insn
>> 12) & 0xf;
1660 rd0
= (insn
>> 16) & 0xf;
1661 rd1
= (insn
>> 0) & 0xf;
1662 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1663 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1664 tcg_gen_andi_i32(tmp
, tmp
, 7);
1665 iwmmxt_load_reg(cpu_V1
, rd1
);
1666 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1668 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1669 gen_op_iwmmxt_set_mup();
1671 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1672 if (((insn
>> 6) & 3) == 3)
1674 rd
= (insn
>> 12) & 0xf;
1675 wrd
= (insn
>> 16) & 0xf;
1676 tmp
= load_reg(s
, rd
);
1677 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1678 switch ((insn
>> 6) & 3) {
1680 tmp2
= tcg_const_i32(0xff);
1681 tmp3
= tcg_const_i32((insn
& 7) << 3);
1684 tmp2
= tcg_const_i32(0xffff);
1685 tmp3
= tcg_const_i32((insn
& 3) << 4);
1688 tmp2
= tcg_const_i32(0xffffffff);
1689 tmp3
= tcg_const_i32((insn
& 1) << 5);
1695 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1696 tcg_temp_free(tmp3
);
1697 tcg_temp_free(tmp2
);
1699 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1700 gen_op_iwmmxt_set_mup();
1702 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1703 rd
= (insn
>> 12) & 0xf;
1704 wrd
= (insn
>> 16) & 0xf;
1705 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1707 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1709 switch ((insn
>> 22) & 3) {
1711 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1712 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1714 tcg_gen_ext8s_i32(tmp
, tmp
);
1716 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1720 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1721 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1723 tcg_gen_ext16s_i32(tmp
, tmp
);
1725 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1729 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1730 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1733 store_reg(s
, rd
, tmp
);
1735 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1736 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1738 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1739 switch ((insn
>> 22) & 3) {
1741 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1744 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1747 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1750 tcg_gen_shli_i32(tmp
, tmp
, 28);
1754 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1755 if (((insn
>> 6) & 3) == 3)
1757 rd
= (insn
>> 12) & 0xf;
1758 wrd
= (insn
>> 16) & 0xf;
1759 tmp
= load_reg(s
, rd
);
1760 switch ((insn
>> 6) & 3) {
1762 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1765 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1768 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1772 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1773 gen_op_iwmmxt_set_mup();
1775 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1776 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1778 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1780 tcg_gen_mov_i32(tmp2
, tmp
);
1781 switch ((insn
>> 22) & 3) {
1783 for (i
= 0; i
< 7; i
++) {
1784 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1785 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1789 for (i
= 0; i
< 3; i
++) {
1790 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1791 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1795 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1796 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1803 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1804 wrd
= (insn
>> 12) & 0xf;
1805 rd0
= (insn
>> 16) & 0xf;
1806 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1807 switch ((insn
>> 22) & 3) {
1809 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1812 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1815 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1820 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1821 gen_op_iwmmxt_set_mup();
1823 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1824 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1826 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1828 tcg_gen_mov_i32(tmp2
, tmp
);
1829 switch ((insn
>> 22) & 3) {
1831 for (i
= 0; i
< 7; i
++) {
1832 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1833 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1837 for (i
= 0; i
< 3; i
++) {
1838 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1839 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1843 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1844 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1851 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1852 rd
= (insn
>> 12) & 0xf;
1853 rd0
= (insn
>> 16) & 0xf;
1854 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1856 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1858 switch ((insn
>> 22) & 3) {
1860 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1863 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1866 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1869 store_reg(s
, rd
, tmp
);
1871 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1872 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1873 wrd
= (insn
>> 12) & 0xf;
1874 rd0
= (insn
>> 16) & 0xf;
1875 rd1
= (insn
>> 0) & 0xf;
1876 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1877 switch ((insn
>> 22) & 3) {
1879 if (insn
& (1 << 21))
1880 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1882 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1885 if (insn
& (1 << 21))
1886 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1888 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1891 if (insn
& (1 << 21))
1892 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1894 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1899 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1900 gen_op_iwmmxt_set_mup();
1901 gen_op_iwmmxt_set_cup();
1903 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1904 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1905 wrd
= (insn
>> 12) & 0xf;
1906 rd0
= (insn
>> 16) & 0xf;
1907 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1908 switch ((insn
>> 22) & 3) {
1910 if (insn
& (1 << 21))
1911 gen_op_iwmmxt_unpacklsb_M0();
1913 gen_op_iwmmxt_unpacklub_M0();
1916 if (insn
& (1 << 21))
1917 gen_op_iwmmxt_unpacklsw_M0();
1919 gen_op_iwmmxt_unpackluw_M0();
1922 if (insn
& (1 << 21))
1923 gen_op_iwmmxt_unpacklsl_M0();
1925 gen_op_iwmmxt_unpacklul_M0();
1930 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1931 gen_op_iwmmxt_set_mup();
1932 gen_op_iwmmxt_set_cup();
1934 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1935 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1936 wrd
= (insn
>> 12) & 0xf;
1937 rd0
= (insn
>> 16) & 0xf;
1938 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1939 switch ((insn
>> 22) & 3) {
1941 if (insn
& (1 << 21))
1942 gen_op_iwmmxt_unpackhsb_M0();
1944 gen_op_iwmmxt_unpackhub_M0();
1947 if (insn
& (1 << 21))
1948 gen_op_iwmmxt_unpackhsw_M0();
1950 gen_op_iwmmxt_unpackhuw_M0();
1953 if (insn
& (1 << 21))
1954 gen_op_iwmmxt_unpackhsl_M0();
1956 gen_op_iwmmxt_unpackhul_M0();
1961 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1962 gen_op_iwmmxt_set_mup();
1963 gen_op_iwmmxt_set_cup();
1965 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1966 case 0x214: case 0x614: case 0xa14: case 0xe14:
1967 if (((insn
>> 22) & 3) == 0)
1969 wrd
= (insn
>> 12) & 0xf;
1970 rd0
= (insn
>> 16) & 0xf;
1971 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1973 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1977 switch ((insn
>> 22) & 3) {
1979 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1982 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1985 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1989 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1990 gen_op_iwmmxt_set_mup();
1991 gen_op_iwmmxt_set_cup();
1993 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1994 case 0x014: case 0x414: case 0x814: case 0xc14:
1995 if (((insn
>> 22) & 3) == 0)
1997 wrd
= (insn
>> 12) & 0xf;
1998 rd0
= (insn
>> 16) & 0xf;
1999 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2001 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2005 switch ((insn
>> 22) & 3) {
2007 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2010 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2013 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2017 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2018 gen_op_iwmmxt_set_mup();
2019 gen_op_iwmmxt_set_cup();
2021 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2022 case 0x114: case 0x514: case 0x914: case 0xd14:
2023 if (((insn
>> 22) & 3) == 0)
2025 wrd
= (insn
>> 12) & 0xf;
2026 rd0
= (insn
>> 16) & 0xf;
2027 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2029 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2033 switch ((insn
>> 22) & 3) {
2035 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2038 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2041 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2045 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2046 gen_op_iwmmxt_set_mup();
2047 gen_op_iwmmxt_set_cup();
2049 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2050 case 0x314: case 0x714: case 0xb14: case 0xf14:
2051 if (((insn
>> 22) & 3) == 0)
2053 wrd
= (insn
>> 12) & 0xf;
2054 rd0
= (insn
>> 16) & 0xf;
2055 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2057 switch ((insn
>> 22) & 3) {
2059 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2063 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2066 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2070 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2073 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2077 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2081 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2082 gen_op_iwmmxt_set_mup();
2083 gen_op_iwmmxt_set_cup();
2085 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2086 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2087 wrd
= (insn
>> 12) & 0xf;
2088 rd0
= (insn
>> 16) & 0xf;
2089 rd1
= (insn
>> 0) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2091 switch ((insn
>> 22) & 3) {
2093 if (insn
& (1 << 21))
2094 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2096 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2099 if (insn
& (1 << 21))
2100 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2102 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2105 if (insn
& (1 << 21))
2106 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2108 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2113 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2114 gen_op_iwmmxt_set_mup();
2116 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2117 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2118 wrd
= (insn
>> 12) & 0xf;
2119 rd0
= (insn
>> 16) & 0xf;
2120 rd1
= (insn
>> 0) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2122 switch ((insn
>> 22) & 3) {
2124 if (insn
& (1 << 21))
2125 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2127 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2130 if (insn
& (1 << 21))
2131 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2133 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2136 if (insn
& (1 << 21))
2137 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2139 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2144 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2145 gen_op_iwmmxt_set_mup();
2147 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2148 case 0x402: case 0x502: case 0x602: case 0x702:
2149 wrd
= (insn
>> 12) & 0xf;
2150 rd0
= (insn
>> 16) & 0xf;
2151 rd1
= (insn
>> 0) & 0xf;
2152 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2153 tmp
= tcg_const_i32((insn
>> 20) & 3);
2154 iwmmxt_load_reg(cpu_V1
, rd1
);
2155 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2158 gen_op_iwmmxt_set_mup();
2160 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2161 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2162 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2163 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2164 wrd
= (insn
>> 12) & 0xf;
2165 rd0
= (insn
>> 16) & 0xf;
2166 rd1
= (insn
>> 0) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2168 switch ((insn
>> 20) & 0xf) {
2170 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2173 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2176 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2179 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2182 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2185 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2188 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2191 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2194 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2199 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2200 gen_op_iwmmxt_set_mup();
2201 gen_op_iwmmxt_set_cup();
2203 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2204 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2205 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2206 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2207 wrd
= (insn
>> 12) & 0xf;
2208 rd0
= (insn
>> 16) & 0xf;
2209 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2210 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2211 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2213 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2214 gen_op_iwmmxt_set_mup();
2215 gen_op_iwmmxt_set_cup();
2217 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2218 case 0x418: case 0x518: case 0x618: case 0x718:
2219 case 0x818: case 0x918: case 0xa18: case 0xb18:
2220 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2221 wrd
= (insn
>> 12) & 0xf;
2222 rd0
= (insn
>> 16) & 0xf;
2223 rd1
= (insn
>> 0) & 0xf;
2224 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2225 switch ((insn
>> 20) & 0xf) {
2227 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2230 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2233 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2236 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2239 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2242 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2245 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2248 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2251 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2256 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2257 gen_op_iwmmxt_set_mup();
2258 gen_op_iwmmxt_set_cup();
2260 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2261 case 0x408: case 0x508: case 0x608: case 0x708:
2262 case 0x808: case 0x908: case 0xa08: case 0xb08:
2263 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2264 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2266 wrd
= (insn
>> 12) & 0xf;
2267 rd0
= (insn
>> 16) & 0xf;
2268 rd1
= (insn
>> 0) & 0xf;
2269 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2270 switch ((insn
>> 22) & 3) {
2272 if (insn
& (1 << 21))
2273 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2275 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2278 if (insn
& (1 << 21))
2279 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2281 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2284 if (insn
& (1 << 21))
2285 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2287 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2290 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2291 gen_op_iwmmxt_set_mup();
2292 gen_op_iwmmxt_set_cup();
2294 case 0x201: case 0x203: case 0x205: case 0x207:
2295 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2296 case 0x211: case 0x213: case 0x215: case 0x217:
2297 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2298 wrd
= (insn
>> 5) & 0xf;
2299 rd0
= (insn
>> 12) & 0xf;
2300 rd1
= (insn
>> 0) & 0xf;
2301 if (rd0
== 0xf || rd1
== 0xf)
2303 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2304 tmp
= load_reg(s
, rd0
);
2305 tmp2
= load_reg(s
, rd1
);
2306 switch ((insn
>> 16) & 0xf) {
2307 case 0x0: /* TMIA */
2308 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2310 case 0x8: /* TMIAPH */
2311 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2313 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2314 if (insn
& (1 << 16))
2315 tcg_gen_shri_i32(tmp
, tmp
, 16);
2316 if (insn
& (1 << 17))
2317 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2318 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2327 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2328 gen_op_iwmmxt_set_mup();
2337 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2338 (ie. an undefined instruction). */
2339 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2341 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2344 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2345 /* Multiply with Internal Accumulate Format */
2346 rd0
= (insn
>> 12) & 0xf;
2348 acc
= (insn
>> 5) & 7;
2353 tmp
= load_reg(s
, rd0
);
2354 tmp2
= load_reg(s
, rd1
);
2355 switch ((insn
>> 16) & 0xf) {
2357 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2359 case 0x8: /* MIAPH */
2360 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2362 case 0xc: /* MIABB */
2363 case 0xd: /* MIABT */
2364 case 0xe: /* MIATB */
2365 case 0xf: /* MIATT */
2366 if (insn
& (1 << 16))
2367 tcg_gen_shri_i32(tmp
, tmp
, 16);
2368 if (insn
& (1 << 17))
2369 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2370 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2378 gen_op_iwmmxt_movq_wRn_M0(acc
);
2382 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2383 /* Internal Accumulator Access Format */
2384 rdhi
= (insn
>> 16) & 0xf;
2385 rdlo
= (insn
>> 12) & 0xf;
2391 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2392 iwmmxt_load_reg(cpu_V0
, acc
);
2393 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2394 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2395 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2396 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2398 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2399 iwmmxt_store_reg(cpu_V0
, acc
);
2407 /* Disassemble system coprocessor instruction. Return nonzero if
2408 instruction is not defined. */
2409 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2412 uint32_t rd
= (insn
>> 12) & 0xf;
2413 uint32_t cp
= (insn
>> 8) & 0xf;
2418 if (insn
& ARM_CP_RW_BIT
) {
2419 if (!env
->cp
[cp
].cp_read
)
2421 gen_set_pc_im(s
->pc
);
2423 tmp2
= tcg_const_i32(insn
);
2424 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2425 tcg_temp_free(tmp2
);
2426 store_reg(s
, rd
, tmp
);
2428 if (!env
->cp
[cp
].cp_write
)
2430 gen_set_pc_im(s
->pc
);
2431 tmp
= load_reg(s
, rd
);
2432 tmp2
= tcg_const_i32(insn
);
2433 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2434 tcg_temp_free(tmp2
);
2440 static int cp15_user_ok(uint32_t insn
)
2442 int cpn
= (insn
>> 16) & 0xf;
2443 int cpm
= insn
& 0xf;
2444 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2446 if (cpn
== 13 && cpm
== 0) {
2448 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2452 /* ISB, DSB, DMB. */
2453 if ((cpm
== 5 && op
== 4)
2454 || (cpm
== 10 && (op
== 4 || op
== 5)))
2460 static int cp15_tls_load_store(CPUState
*env
, DisasContext
*s
, uint32_t insn
, uint32_t rd
)
2463 int cpn
= (insn
>> 16) & 0xf;
2464 int cpm
= insn
& 0xf;
2465 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2467 if (!arm_feature(env
, ARM_FEATURE_V6K
))
2470 if (!(cpn
== 13 && cpm
== 0))
2473 if (insn
& ARM_CP_RW_BIT
) {
2476 tmp
= load_cpu_field(cp15
.c13_tls1
);
2479 tmp
= load_cpu_field(cp15
.c13_tls2
);
2482 tmp
= load_cpu_field(cp15
.c13_tls3
);
2487 store_reg(s
, rd
, tmp
);
2490 tmp
= load_reg(s
, rd
);
2493 store_cpu_field(tmp
, cp15
.c13_tls1
);
2496 store_cpu_field(tmp
, cp15
.c13_tls2
);
2499 store_cpu_field(tmp
, cp15
.c13_tls3
);
2509 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2510 instruction is not defined. */
2511 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2516 /* M profile cores use memory mapped registers instead of cp15. */
2517 if (arm_feature(env
, ARM_FEATURE_M
))
2520 if ((insn
& (1 << 25)) == 0) {
2521 if (insn
& (1 << 20)) {
2525 /* mcrr. Used for block cache operations, so implement as no-op. */
2528 if ((insn
& (1 << 4)) == 0) {
2532 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2535 if ((insn
& 0x0fff0fff) == 0x0e070f90
2536 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2537 /* Wait for interrupt. */
2538 gen_set_pc_im(s
->pc
);
2539 s
->is_jmp
= DISAS_WFI
;
2542 rd
= (insn
>> 12) & 0xf;
2544 if (cp15_tls_load_store(env
, s
, insn
, rd
))
2547 tmp2
= tcg_const_i32(insn
);
2548 if (insn
& ARM_CP_RW_BIT
) {
2550 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2551 /* If the destination register is r15 then sets condition codes. */
2553 store_reg(s
, rd
, tmp
);
2557 tmp
= load_reg(s
, rd
);
2558 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2560 /* Normally we would always end the TB here, but Linux
2561 * arch/arm/mach-pxa/sleep.S expects two instructions following
2562 * an MMU enable to execute from cache. Imitate this behaviour. */
2563 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2564 (insn
& 0x0fff0fff) != 0x0e010f10)
2567 tcg_temp_free_i32(tmp2
);
2571 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2572 #define VFP_SREG(insn, bigbit, smallbit) \
2573 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2574 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2575 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2576 reg = (((insn) >> (bigbit)) & 0x0f) \
2577 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2579 if (insn & (1 << (smallbit))) \
2581 reg = ((insn) >> (bigbit)) & 0x0f; \
2584 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2585 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2586 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2587 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2588 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2589 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2591 /* Move between integer and VFP cores. */
2592 static TCGv
gen_vfp_mrs(void)
2594 TCGv tmp
= new_tmp();
2595 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2599 static void gen_vfp_msr(TCGv tmp
)
2601 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2606 vfp_enabled(CPUState
* env
)
2608 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2611 static void gen_neon_dup_u8(TCGv var
, int shift
)
2613 TCGv tmp
= new_tmp();
2615 tcg_gen_shri_i32(var
, var
, shift
);
2616 tcg_gen_ext8u_i32(var
, var
);
2617 tcg_gen_shli_i32(tmp
, var
, 8);
2618 tcg_gen_or_i32(var
, var
, tmp
);
2619 tcg_gen_shli_i32(tmp
, var
, 16);
2620 tcg_gen_or_i32(var
, var
, tmp
);
2624 static void gen_neon_dup_low16(TCGv var
)
2626 TCGv tmp
= new_tmp();
2627 tcg_gen_ext16u_i32(var
, var
);
2628 tcg_gen_shli_i32(tmp
, var
, 16);
2629 tcg_gen_or_i32(var
, var
, tmp
);
2633 static void gen_neon_dup_high16(TCGv var
)
2635 TCGv tmp
= new_tmp();
2636 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2637 tcg_gen_shri_i32(tmp
, var
, 16);
2638 tcg_gen_or_i32(var
, var
, tmp
);
2642 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2643 (ie. an undefined instruction). */
2644 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2646 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2652 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2655 if (!vfp_enabled(env
)) {
2656 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2657 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2659 rn
= (insn
>> 16) & 0xf;
2660 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2661 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2664 dp
= ((insn
& 0xf00) == 0xb00);
2665 switch ((insn
>> 24) & 0xf) {
2667 if (insn
& (1 << 4)) {
2668 /* single register transfer */
2669 rd
= (insn
>> 12) & 0xf;
2674 VFP_DREG_N(rn
, insn
);
2677 if (insn
& 0x00c00060
2678 && !arm_feature(env
, ARM_FEATURE_NEON
))
2681 pass
= (insn
>> 21) & 1;
2682 if (insn
& (1 << 22)) {
2684 offset
= ((insn
>> 5) & 3) * 8;
2685 } else if (insn
& (1 << 5)) {
2687 offset
= (insn
& (1 << 6)) ? 16 : 0;
2692 if (insn
& ARM_CP_RW_BIT
) {
2694 tmp
= neon_load_reg(rn
, pass
);
2698 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2699 if (insn
& (1 << 23))
2705 if (insn
& (1 << 23)) {
2707 tcg_gen_shri_i32(tmp
, tmp
, 16);
2713 tcg_gen_sari_i32(tmp
, tmp
, 16);
2722 store_reg(s
, rd
, tmp
);
2725 tmp
= load_reg(s
, rd
);
2726 if (insn
& (1 << 23)) {
2729 gen_neon_dup_u8(tmp
, 0);
2730 } else if (size
== 1) {
2731 gen_neon_dup_low16(tmp
);
2733 for (n
= 0; n
<= pass
* 2; n
++) {
2735 tcg_gen_mov_i32(tmp2
, tmp
);
2736 neon_store_reg(rn
, n
, tmp2
);
2738 neon_store_reg(rn
, n
, tmp
);
2743 tmp2
= neon_load_reg(rn
, pass
);
2744 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2748 tmp2
= neon_load_reg(rn
, pass
);
2749 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2755 neon_store_reg(rn
, pass
, tmp
);
2759 if ((insn
& 0x6f) != 0x00)
2761 rn
= VFP_SREG_N(insn
);
2762 if (insn
& ARM_CP_RW_BIT
) {
2764 if (insn
& (1 << 21)) {
2765 /* system register */
2770 /* VFP2 allows access to FSID from userspace.
2771 VFP3 restricts all id registers to privileged
2774 && arm_feature(env
, ARM_FEATURE_VFP3
))
2776 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2781 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2783 case ARM_VFP_FPINST
:
2784 case ARM_VFP_FPINST2
:
2785 /* Not present in VFP3. */
2787 || arm_feature(env
, ARM_FEATURE_VFP3
))
2789 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2793 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2794 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2797 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2803 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2805 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2811 gen_mov_F0_vreg(0, rn
);
2812 tmp
= gen_vfp_mrs();
2815 /* Set the 4 flag bits in the CPSR. */
2819 store_reg(s
, rd
, tmp
);
2823 tmp
= load_reg(s
, rd
);
2824 if (insn
& (1 << 21)) {
2826 /* system register */
2831 /* Writes are ignored. */
2834 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2841 /* TODO: VFP subarchitecture support.
2842 * For now, keep the EN bit only */
2843 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2844 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2847 case ARM_VFP_FPINST
:
2848 case ARM_VFP_FPINST2
:
2849 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2856 gen_mov_vreg_F0(0, rn
);
2861 /* data processing */
2862 /* The opcode is in bits 23, 21, 20 and 6. */
2863 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2867 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2869 /* rn is register number */
2870 VFP_DREG_N(rn
, insn
);
2873 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2874 /* Integer or single precision destination. */
2875 rd
= VFP_SREG_D(insn
);
2877 VFP_DREG_D(rd
, insn
);
2880 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2881 /* Integer source. */
2882 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2884 VFP_DREG_M(rm
, insn
);
2887 rn
= VFP_SREG_N(insn
);
2888 if (op
== 15 && rn
== 15) {
2889 /* Double precision destination. */
2890 VFP_DREG_D(rd
, insn
);
2892 rd
= VFP_SREG_D(insn
);
2894 rm
= VFP_SREG_M(insn
);
2897 veclen
= env
->vfp
.vec_len
;
2898 if (op
== 15 && rn
> 3)
2901 /* Shut up compiler warnings. */
2912 /* Figure out what type of vector operation this is. */
2913 if ((rd
& bank_mask
) == 0) {
2918 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2920 delta_d
= env
->vfp
.vec_stride
+ 1;
2922 if ((rm
& bank_mask
) == 0) {
2923 /* mixed scalar/vector */
2932 /* Load the initial operands. */
2937 /* Integer source */
2938 gen_mov_F0_vreg(0, rm
);
2943 gen_mov_F0_vreg(dp
, rd
);
2944 gen_mov_F1_vreg(dp
, rm
);
2948 /* Compare with zero */
2949 gen_mov_F0_vreg(dp
, rd
);
2960 /* Source and destination the same. */
2961 gen_mov_F0_vreg(dp
, rd
);
2964 /* One source operand. */
2965 gen_mov_F0_vreg(dp
, rm
);
2969 /* Two source operands. */
2970 gen_mov_F0_vreg(dp
, rn
);
2971 gen_mov_F1_vreg(dp
, rm
);
2975 /* Perform the calculation. */
2977 case 0: /* mac: fd + (fn * fm) */
2979 gen_mov_F1_vreg(dp
, rd
);
2982 case 1: /* nmac: fd - (fn * fm) */
2985 gen_mov_F1_vreg(dp
, rd
);
2988 case 2: /* msc: -fd + (fn * fm) */
2990 gen_mov_F1_vreg(dp
, rd
);
2993 case 3: /* nmsc: -fd - (fn * fm) */
2996 gen_mov_F1_vreg(dp
, rd
);
2999 case 4: /* mul: fn * fm */
3002 case 5: /* nmul: -(fn * fm) */
3006 case 6: /* add: fn + fm */
3009 case 7: /* sub: fn - fm */
3012 case 8: /* div: fn / fm */
3015 case 14: /* fconst */
3016 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3019 n
= (insn
<< 12) & 0x80000000;
3020 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3027 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3034 tcg_gen_movi_i32(cpu_F0s
, n
);
3037 case 15: /* extension space */
3051 case 4: /* vcvtb.f32.f16 */
3052 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3054 tmp
= gen_vfp_mrs();
3055 tcg_gen_ext16u_i32(tmp
, tmp
);
3056 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3059 case 5: /* vcvtt.f32.f16 */
3060 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3062 tmp
= gen_vfp_mrs();
3063 tcg_gen_shri_i32(tmp
, tmp
, 16);
3064 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3067 case 6: /* vcvtb.f16.f32 */
3068 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3071 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3072 gen_mov_F0_vreg(0, rd
);
3073 tmp2
= gen_vfp_mrs();
3074 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3075 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3079 case 7: /* vcvtt.f16.f32 */
3080 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3083 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3084 tcg_gen_shli_i32(tmp
, tmp
, 16);
3085 gen_mov_F0_vreg(0, rd
);
3086 tmp2
= gen_vfp_mrs();
3087 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3088 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3101 case 11: /* cmpez */
3105 case 15: /* single<->double conversion */
3107 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3109 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3111 case 16: /* fuito */
3114 case 17: /* fsito */
3117 case 20: /* fshto */
3118 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3120 gen_vfp_shto(dp
, 16 - rm
);
3122 case 21: /* fslto */
3123 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3125 gen_vfp_slto(dp
, 32 - rm
);
3127 case 22: /* fuhto */
3128 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3130 gen_vfp_uhto(dp
, 16 - rm
);
3132 case 23: /* fulto */
3133 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3135 gen_vfp_ulto(dp
, 32 - rm
);
3137 case 24: /* ftoui */
3140 case 25: /* ftouiz */
3143 case 26: /* ftosi */
3146 case 27: /* ftosiz */
3149 case 28: /* ftosh */
3150 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3152 gen_vfp_tosh(dp
, 16 - rm
);
3154 case 29: /* ftosl */
3155 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3157 gen_vfp_tosl(dp
, 32 - rm
);
3159 case 30: /* ftouh */
3160 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3162 gen_vfp_touh(dp
, 16 - rm
);
3164 case 31: /* ftoul */
3165 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3167 gen_vfp_toul(dp
, 32 - rm
);
3169 default: /* undefined */
3170 printf ("rn:%d\n", rn
);
3174 default: /* undefined */
3175 printf ("op:%d\n", op
);
3179 /* Write back the result. */
3180 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3181 ; /* Comparison, do nothing. */
3182 else if (op
== 15 && rn
> 17)
3183 /* Integer result. */
3184 gen_mov_vreg_F0(0, rd
);
3185 else if (op
== 15 && rn
== 15)
3187 gen_mov_vreg_F0(!dp
, rd
);
3189 gen_mov_vreg_F0(dp
, rd
);
3191 /* break out of the loop if we have finished */
3195 if (op
== 15 && delta_m
== 0) {
3196 /* single source one-many */
3198 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3200 gen_mov_vreg_F0(dp
, rd
);
3204 /* Setup the next operands. */
3206 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3210 /* One source operand. */
3211 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3213 gen_mov_F0_vreg(dp
, rm
);
3215 /* Two source operands. */
3216 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3218 gen_mov_F0_vreg(dp
, rn
);
3220 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3222 gen_mov_F1_vreg(dp
, rm
);
3230 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3231 /* two-register transfer */
3232 rn
= (insn
>> 16) & 0xf;
3233 rd
= (insn
>> 12) & 0xf;
3235 VFP_DREG_M(rm
, insn
);
3237 rm
= VFP_SREG_M(insn
);
3240 if (insn
& ARM_CP_RW_BIT
) {
3243 gen_mov_F0_vreg(0, rm
* 2);
3244 tmp
= gen_vfp_mrs();
3245 store_reg(s
, rd
, tmp
);
3246 gen_mov_F0_vreg(0, rm
* 2 + 1);
3247 tmp
= gen_vfp_mrs();
3248 store_reg(s
, rn
, tmp
);
3250 gen_mov_F0_vreg(0, rm
);
3251 tmp
= gen_vfp_mrs();
3252 store_reg(s
, rn
, tmp
);
3253 gen_mov_F0_vreg(0, rm
+ 1);
3254 tmp
= gen_vfp_mrs();
3255 store_reg(s
, rd
, tmp
);
3260 tmp
= load_reg(s
, rd
);
3262 gen_mov_vreg_F0(0, rm
* 2);
3263 tmp
= load_reg(s
, rn
);
3265 gen_mov_vreg_F0(0, rm
* 2 + 1);
3267 tmp
= load_reg(s
, rn
);
3269 gen_mov_vreg_F0(0, rm
);
3270 tmp
= load_reg(s
, rd
);
3272 gen_mov_vreg_F0(0, rm
+ 1);
3277 rn
= (insn
>> 16) & 0xf;
3279 VFP_DREG_D(rd
, insn
);
3281 rd
= VFP_SREG_D(insn
);
3282 if (s
->thumb
&& rn
== 15) {
3284 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3286 addr
= load_reg(s
, rn
);
3288 if ((insn
& 0x01200000) == 0x01000000) {
3289 /* Single load/store */
3290 offset
= (insn
& 0xff) << 2;
3291 if ((insn
& (1 << 23)) == 0)
3293 tcg_gen_addi_i32(addr
, addr
, offset
);
3294 if (insn
& (1 << 20)) {
3295 gen_vfp_ld(s
, dp
, addr
);
3296 gen_mov_vreg_F0(dp
, rd
);
3298 gen_mov_F0_vreg(dp
, rd
);
3299 gen_vfp_st(s
, dp
, addr
);
3303 /* load/store multiple */
3305 n
= (insn
>> 1) & 0x7f;
3309 if (insn
& (1 << 24)) /* pre-decrement */
3310 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3316 for (i
= 0; i
< n
; i
++) {
3317 if (insn
& ARM_CP_RW_BIT
) {
3319 gen_vfp_ld(s
, dp
, addr
);
3320 gen_mov_vreg_F0(dp
, rd
+ i
);
3323 gen_mov_F0_vreg(dp
, rd
+ i
);
3324 gen_vfp_st(s
, dp
, addr
);
3326 tcg_gen_addi_i32(addr
, addr
, offset
);
3328 if (insn
& (1 << 21)) {
3330 if (insn
& (1 << 24))
3331 offset
= -offset
* n
;
3332 else if (dp
&& (insn
& 1))
3338 tcg_gen_addi_i32(addr
, addr
, offset
);
3339 store_reg(s
, rn
, addr
);
3347 /* Should never happen. */
3353 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3355 TranslationBlock
*tb
;
3358 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3360 gen_set_pc_im(dest
);
3361 tcg_gen_exit_tb((long)tb
+ n
);
3363 gen_set_pc_im(dest
);
3368 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3370 if (unlikely(s
->singlestep_enabled
)) {
3371 /* An indirect jump so that we still trigger the debug exception. */
3376 gen_goto_tb(s
, 0, dest
);
3377 s
->is_jmp
= DISAS_TB_JUMP
;
3381 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3384 tcg_gen_sari_i32(t0
, t0
, 16);
3388 tcg_gen_sari_i32(t1
, t1
, 16);
3391 tcg_gen_mul_i32(t0
, t0
, t1
);
3394 /* Return the mask of PSR bits set by a MSR instruction. */
3395 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3399 if (flags
& (1 << 0))
3401 if (flags
& (1 << 1))
3403 if (flags
& (1 << 2))
3405 if (flags
& (1 << 3))
3408 /* Mask out undefined bits. */
3409 mask
&= ~CPSR_RESERVED
;
3410 if (!arm_feature(env
, ARM_FEATURE_V6
))
3411 mask
&= ~(CPSR_E
| CPSR_GE
);
3412 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3414 /* Mask out execution state bits. */
3417 /* Mask out privileged bits. */
3423 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3424 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3428 /* ??? This is also undefined in system mode. */
3432 tmp
= load_cpu_field(spsr
);
3433 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3434 tcg_gen_andi_i32(t0
, t0
, mask
);
3435 tcg_gen_or_i32(tmp
, tmp
, t0
);
3436 store_cpu_field(tmp
, spsr
);
3438 gen_set_cpsr(t0
, mask
);
3445 /* Returns nonzero if access to the PSR is not permitted. */
3446 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3450 tcg_gen_movi_i32(tmp
, val
);
3451 return gen_set_psr(s
, mask
, spsr
, tmp
);
3454 /* Generate an old-style exception return. Marks pc as dead. */
3455 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3458 store_reg(s
, 15, pc
);
3459 tmp
= load_cpu_field(spsr
);
3460 gen_set_cpsr(tmp
, 0xffffffff);
3462 s
->is_jmp
= DISAS_UPDATE
;
3465 /* Generate a v6 exception return. Marks both values as dead. */
3466 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3468 gen_set_cpsr(cpsr
, 0xffffffff);
3470 store_reg(s
, 15, pc
);
3471 s
->is_jmp
= DISAS_UPDATE
;
3475 gen_set_condexec (DisasContext
*s
)
3477 if (s
->condexec_mask
) {
3478 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3479 TCGv tmp
= new_tmp();
3480 tcg_gen_movi_i32(tmp
, val
);
3481 store_cpu_field(tmp
, condexec_bits
);
3485 static void gen_nop_hint(DisasContext
*s
, int val
)
3489 gen_set_pc_im(s
->pc
);
3490 s
->is_jmp
= DISAS_WFI
;
3494 /* TODO: Implement SEV and WFE. May help SMP performance. */
3500 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3502 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3505 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3506 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3507 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3513 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3516 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3517 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3518 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3523 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3524 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3525 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3526 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3527 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3529 /* FIXME: This is wrong. They set the wrong overflow bit. */
3530 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3531 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3532 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3533 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3535 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3536 switch ((size << 1) | u) { \
3538 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3541 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3544 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3547 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3550 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3553 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3555 default: return 1; \
3558 #define GEN_NEON_INTEGER_OP(name) do { \
3559 switch ((size << 1) | u) { \
3561 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3564 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3567 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3570 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3573 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3576 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3578 default: return 1; \
3581 static TCGv
neon_load_scratch(int scratch
)
3583 TCGv tmp
= new_tmp();
3584 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3588 static void neon_store_scratch(int scratch
, TCGv var
)
3590 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3594 static inline TCGv
neon_get_scalar(int size
, int reg
)
3598 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3600 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3602 gen_neon_dup_low16(tmp
);
3604 gen_neon_dup_high16(tmp
);
3610 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3618 tcg_gen_andi_i32(rd
, t0
, 0xff);
3619 tcg_gen_shri_i32(tmp
, t0
, 8);
3620 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3621 tcg_gen_or_i32(rd
, rd
, tmp
);
3622 tcg_gen_shli_i32(tmp
, t1
, 16);
3623 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3624 tcg_gen_or_i32(rd
, rd
, tmp
);
3625 tcg_gen_shli_i32(tmp
, t1
, 8);
3626 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3627 tcg_gen_or_i32(rd
, rd
, tmp
);
3629 tcg_gen_shri_i32(rm
, t0
, 8);
3630 tcg_gen_andi_i32(rm
, rm
, 0xff);
3631 tcg_gen_shri_i32(tmp
, t0
, 16);
3632 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3633 tcg_gen_or_i32(rm
, rm
, tmp
);
3634 tcg_gen_shli_i32(tmp
, t1
, 8);
3635 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3636 tcg_gen_or_i32(rm
, rm
, tmp
);
3637 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3638 tcg_gen_or_i32(t1
, rm
, tmp
);
3639 tcg_gen_mov_i32(t0
, rd
);
3646 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3654 tcg_gen_andi_i32(rd
, t0
, 0xff);
3655 tcg_gen_shli_i32(tmp
, t1
, 8);
3656 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3657 tcg_gen_or_i32(rd
, rd
, tmp
);
3658 tcg_gen_shli_i32(tmp
, t0
, 16);
3659 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3660 tcg_gen_or_i32(rd
, rd
, tmp
);
3661 tcg_gen_shli_i32(tmp
, t1
, 24);
3662 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3663 tcg_gen_or_i32(rd
, rd
, tmp
);
3665 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3666 tcg_gen_shri_i32(tmp
, t0
, 8);
3667 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3668 tcg_gen_or_i32(rm
, rm
, tmp
);
3669 tcg_gen_shri_i32(tmp
, t1
, 8);
3670 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3671 tcg_gen_or_i32(rm
, rm
, tmp
);
3672 tcg_gen_shri_i32(tmp
, t0
, 16);
3673 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3674 tcg_gen_or_i32(t1
, rm
, tmp
);
3675 tcg_gen_mov_i32(t0
, rd
);
3682 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3689 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3690 tcg_gen_shli_i32(tmp2
, t1
, 16);
3691 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3692 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3693 tcg_gen_shri_i32(tmp2
, t0
, 16);
3694 tcg_gen_or_i32(t1
, t1
, tmp2
);
3695 tcg_gen_mov_i32(t0
, tmp
);
3701 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3706 for (n
= 0; n
< q
+ 1; n
+= 2) {
3707 t0
= neon_load_reg(reg
, n
);
3708 t1
= neon_load_reg(reg
, n
+ 1);
3710 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3711 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3712 case 2: /* no-op */; break;
3715 neon_store_scratch(tmp
+ n
, t0
);
3716 neon_store_scratch(tmp
+ n
+ 1, t1
);
3720 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3727 tcg_gen_shli_i32(rd
, t0
, 8);
3728 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3729 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3730 tcg_gen_or_i32(rd
, rd
, tmp
);
3732 tcg_gen_shri_i32(t1
, t1
, 8);
3733 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3734 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3735 tcg_gen_or_i32(t1
, t1
, tmp
);
3736 tcg_gen_mov_i32(t0
, rd
);
3742 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3749 tcg_gen_shli_i32(rd
, t0
, 16);
3750 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3751 tcg_gen_or_i32(rd
, rd
, tmp
);
3752 tcg_gen_shri_i32(t1
, t1
, 16);
3753 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3754 tcg_gen_or_i32(t1
, t1
, tmp
);
3755 tcg_gen_mov_i32(t0
, rd
);
3766 } neon_ls_element_type
[11] = {
3780 /* Translate a NEON load/store element instruction. Return nonzero if the
3781 instruction is invalid. */
3782 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3801 if (!vfp_enabled(env
))
3803 VFP_DREG_D(rd
, insn
);
3804 rn
= (insn
>> 16) & 0xf;
3806 load
= (insn
& (1 << 21)) != 0;
3808 if ((insn
& (1 << 23)) == 0) {
3809 /* Load store all elements. */
3810 op
= (insn
>> 8) & 0xf;
3811 size
= (insn
>> 6) & 3;
3814 nregs
= neon_ls_element_type
[op
].nregs
;
3815 interleave
= neon_ls_element_type
[op
].interleave
;
3816 spacing
= neon_ls_element_type
[op
].spacing
;
3817 if (size
== 3 && (interleave
| spacing
) != 1)
3819 load_reg_var(s
, addr
, rn
);
3820 stride
= (1 << size
) * interleave
;
3821 for (reg
= 0; reg
< nregs
; reg
++) {
3822 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3823 load_reg_var(s
, addr
, rn
);
3824 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3825 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3826 load_reg_var(s
, addr
, rn
);
3827 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3831 tmp64
= gen_ld64(addr
, IS_USER(s
));
3832 neon_store_reg64(tmp64
, rd
);
3833 tcg_temp_free_i64(tmp64
);
3835 tmp64
= tcg_temp_new_i64();
3836 neon_load_reg64(tmp64
, rd
);
3837 gen_st64(tmp64
, addr
, IS_USER(s
));
3839 tcg_gen_addi_i32(addr
, addr
, stride
);
3841 for (pass
= 0; pass
< 2; pass
++) {
3844 tmp
= gen_ld32(addr
, IS_USER(s
));
3845 neon_store_reg(rd
, pass
, tmp
);
3847 tmp
= neon_load_reg(rd
, pass
);
3848 gen_st32(tmp
, addr
, IS_USER(s
));
3850 tcg_gen_addi_i32(addr
, addr
, stride
);
3851 } else if (size
== 1) {
3853 tmp
= gen_ld16u(addr
, IS_USER(s
));
3854 tcg_gen_addi_i32(addr
, addr
, stride
);
3855 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3856 tcg_gen_addi_i32(addr
, addr
, stride
);
3857 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3858 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3860 neon_store_reg(rd
, pass
, tmp
);
3862 tmp
= neon_load_reg(rd
, pass
);
3864 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3865 gen_st16(tmp
, addr
, IS_USER(s
));
3866 tcg_gen_addi_i32(addr
, addr
, stride
);
3867 gen_st16(tmp2
, addr
, IS_USER(s
));
3868 tcg_gen_addi_i32(addr
, addr
, stride
);
3870 } else /* size == 0 */ {
3873 for (n
= 0; n
< 4; n
++) {
3874 tmp
= gen_ld8u(addr
, IS_USER(s
));
3875 tcg_gen_addi_i32(addr
, addr
, stride
);
3879 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3880 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3884 neon_store_reg(rd
, pass
, tmp2
);
3886 tmp2
= neon_load_reg(rd
, pass
);
3887 for (n
= 0; n
< 4; n
++) {
3890 tcg_gen_mov_i32(tmp
, tmp2
);
3892 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3894 gen_st8(tmp
, addr
, IS_USER(s
));
3895 tcg_gen_addi_i32(addr
, addr
, stride
);
3906 size
= (insn
>> 10) & 3;
3908 /* Load single element to all lanes. */
3911 size
= (insn
>> 6) & 3;
3912 nregs
= ((insn
>> 8) & 3) + 1;
3913 stride
= (insn
& (1 << 5)) ? 2 : 1;
3914 load_reg_var(s
, addr
, rn
);
3915 for (reg
= 0; reg
< nregs
; reg
++) {
3918 tmp
= gen_ld8u(addr
, IS_USER(s
));
3919 gen_neon_dup_u8(tmp
, 0);
3922 tmp
= gen_ld16u(addr
, IS_USER(s
));
3923 gen_neon_dup_low16(tmp
);
3926 tmp
= gen_ld32(addr
, IS_USER(s
));
3930 default: /* Avoid compiler warnings. */
3933 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3935 tcg_gen_mov_i32(tmp2
, tmp
);
3936 neon_store_reg(rd
, 0, tmp2
);
3937 neon_store_reg(rd
, 1, tmp
);
3940 stride
= (1 << size
) * nregs
;
3942 /* Single element. */
3943 pass
= (insn
>> 7) & 1;
3946 shift
= ((insn
>> 5) & 3) * 8;
3950 shift
= ((insn
>> 6) & 1) * 16;
3951 stride
= (insn
& (1 << 5)) ? 2 : 1;
3955 stride
= (insn
& (1 << 6)) ? 2 : 1;
3960 nregs
= ((insn
>> 8) & 3) + 1;
3961 load_reg_var(s
, addr
, rn
);
3962 for (reg
= 0; reg
< nregs
; reg
++) {
3966 tmp
= gen_ld8u(addr
, IS_USER(s
));
3969 tmp
= gen_ld16u(addr
, IS_USER(s
));
3972 tmp
= gen_ld32(addr
, IS_USER(s
));
3974 default: /* Avoid compiler warnings. */
3978 tmp2
= neon_load_reg(rd
, pass
);
3979 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3982 neon_store_reg(rd
, pass
, tmp
);
3983 } else { /* Store */
3984 tmp
= neon_load_reg(rd
, pass
);
3986 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3989 gen_st8(tmp
, addr
, IS_USER(s
));
3992 gen_st16(tmp
, addr
, IS_USER(s
));
3995 gen_st32(tmp
, addr
, IS_USER(s
));
4000 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4002 stride
= nregs
* (1 << size
);
4009 base
= load_reg(s
, rn
);
4011 tcg_gen_addi_i32(base
, base
, stride
);
4014 index
= load_reg(s
, rm
);
4015 tcg_gen_add_i32(base
, base
, index
);
4018 store_reg(s
, rn
, base
);
4023 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4024 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4026 tcg_gen_and_i32(t
, t
, c
);
4027 tcg_gen_andc_i32(f
, f
, c
);
4028 tcg_gen_or_i32(dest
, t
, f
);
4031 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4034 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4035 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4036 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4041 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4044 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4045 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4046 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4051 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4054 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4055 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4056 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4061 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4067 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4068 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4073 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4074 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4081 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4082 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4087 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4088 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4095 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4099 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4100 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4101 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4106 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4107 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4108 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4115 static inline void gen_neon_addl(int size
)
4118 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4119 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4120 case 2: tcg_gen_add_i64(CPU_V001
); break;
4125 static inline void gen_neon_subl(int size
)
4128 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4129 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4130 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4135 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4138 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4139 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4140 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4145 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4148 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4149 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4154 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4158 switch ((size
<< 1) | u
) {
4159 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4160 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4161 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4162 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4164 tmp
= gen_muls_i64_i32(a
, b
);
4165 tcg_gen_mov_i64(dest
, tmp
);
4168 tmp
= gen_mulu_i64_i32(a
, b
);
4169 tcg_gen_mov_i64(dest
, tmp
);
4175 /* Translate a NEON data processing instruction. Return nonzero if the
4176 instruction is invalid.
4177 We process data in a mixture of 32-bit and 64-bit chunks.
4178 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4180 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4193 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4196 if (!vfp_enabled(env
))
4198 q
= (insn
& (1 << 6)) != 0;
4199 u
= (insn
>> 24) & 1;
4200 VFP_DREG_D(rd
, insn
);
4201 VFP_DREG_N(rn
, insn
);
4202 VFP_DREG_M(rm
, insn
);
4203 size
= (insn
>> 20) & 3;
4204 if ((insn
& (1 << 23)) == 0) {
4205 /* Three register same length. */
4206 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4207 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4208 || op
== 10 || op
== 11 || op
== 16)) {
4209 /* 64-bit element instructions. */
4210 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4211 neon_load_reg64(cpu_V0
, rn
+ pass
);
4212 neon_load_reg64(cpu_V1
, rm
+ pass
);
4216 gen_helper_neon_add_saturate_u64(CPU_V001
);
4218 gen_helper_neon_add_saturate_s64(CPU_V001
);
4223 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4225 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4230 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4232 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4237 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4240 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4244 case 10: /* VRSHL */
4246 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4248 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4251 case 11: /* VQRSHL */
4253 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4256 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4262 tcg_gen_sub_i64(CPU_V001
);
4264 tcg_gen_add_i64(CPU_V001
);
4270 neon_store_reg64(cpu_V0
, rd
+ pass
);
4277 case 10: /* VRSHL */
4278 case 11: /* VQRSHL */
4281 /* Shift instruction operands are reversed. */
4288 case 20: /* VPMAX */
4289 case 21: /* VPMIN */
4290 case 23: /* VPADD */
4293 case 26: /* VPADD (float) */
4294 pairwise
= (u
&& size
< 2);
4296 case 30: /* VPMIN/VPMAX (float) */
4304 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4313 tmp
= neon_load_reg(rn
, n
);
4314 tmp2
= neon_load_reg(rn
, n
+ 1);
4316 tmp
= neon_load_reg(rm
, n
);
4317 tmp2
= neon_load_reg(rm
, n
+ 1);
4321 tmp
= neon_load_reg(rn
, pass
);
4322 tmp2
= neon_load_reg(rm
, pass
);
4326 GEN_NEON_INTEGER_OP(hadd
);
4329 GEN_NEON_INTEGER_OP_ENV(qadd
);
4331 case 2: /* VRHADD */
4332 GEN_NEON_INTEGER_OP(rhadd
);
4334 case 3: /* Logic ops. */
4335 switch ((u
<< 2) | size
) {
4337 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4340 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4343 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4346 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4349 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4352 tmp3
= neon_load_reg(rd
, pass
);
4353 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4357 tmp3
= neon_load_reg(rd
, pass
);
4358 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4362 tmp3
= neon_load_reg(rd
, pass
);
4363 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4369 GEN_NEON_INTEGER_OP(hsub
);
4372 GEN_NEON_INTEGER_OP_ENV(qsub
);
4375 GEN_NEON_INTEGER_OP(cgt
);
4378 GEN_NEON_INTEGER_OP(cge
);
4381 GEN_NEON_INTEGER_OP(shl
);
4384 GEN_NEON_INTEGER_OP_ENV(qshl
);
4386 case 10: /* VRSHL */
4387 GEN_NEON_INTEGER_OP(rshl
);
4389 case 11: /* VQRSHL */
4390 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4393 GEN_NEON_INTEGER_OP(max
);
4396 GEN_NEON_INTEGER_OP(min
);
4399 GEN_NEON_INTEGER_OP(abd
);
4402 GEN_NEON_INTEGER_OP(abd
);
4404 tmp2
= neon_load_reg(rd
, pass
);
4405 gen_neon_add(size
, tmp
, tmp2
);
4408 if (!u
) { /* VADD */
4409 if (gen_neon_add(size
, tmp
, tmp2
))
4413 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4414 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4415 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4421 if (!u
) { /* VTST */
4423 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4424 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4425 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4430 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4431 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4432 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4437 case 18: /* Multiply. */
4439 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4440 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4441 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4445 tmp2
= neon_load_reg(rd
, pass
);
4447 gen_neon_rsb(size
, tmp
, tmp2
);
4449 gen_neon_add(size
, tmp
, tmp2
);
4453 if (u
) { /* polynomial */
4454 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4455 } else { /* Integer */
4457 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4458 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4459 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4464 case 20: /* VPMAX */
4465 GEN_NEON_INTEGER_OP(pmax
);
4467 case 21: /* VPMIN */
4468 GEN_NEON_INTEGER_OP(pmin
);
4470 case 22: /* Hultiply high. */
4471 if (!u
) { /* VQDMULH */
4473 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4474 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4477 } else { /* VQRDHMUL */
4479 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4480 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4485 case 23: /* VPADD */
4489 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4490 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4491 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4495 case 26: /* Floating point arithnetic. */
4496 switch ((u
<< 2) | size
) {
4498 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4501 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4504 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4507 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4513 case 27: /* Float multiply. */
4514 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4517 tmp2
= neon_load_reg(rd
, pass
);
4519 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4521 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4525 case 28: /* Float compare. */
4527 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4530 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4532 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4535 case 29: /* Float compare absolute. */
4539 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4541 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4543 case 30: /* Float min/max. */
4545 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4547 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4551 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4553 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4560 /* Save the result. For elementwise operations we can put it
4561 straight into the destination register. For pairwise operations
4562 we have to be careful to avoid clobbering the source operands. */
4563 if (pairwise
&& rd
== rm
) {
4564 neon_store_scratch(pass
, tmp
);
4566 neon_store_reg(rd
, pass
, tmp
);
4570 if (pairwise
&& rd
== rm
) {
4571 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4572 tmp
= neon_load_scratch(pass
);
4573 neon_store_reg(rd
, pass
, tmp
);
4576 /* End of 3 register same size operations. */
4577 } else if (insn
& (1 << 4)) {
4578 if ((insn
& 0x00380080) != 0) {
4579 /* Two registers and shift. */
4580 op
= (insn
>> 8) & 0xf;
4581 if (insn
& (1 << 7)) {
4586 while ((insn
& (1 << (size
+ 19))) == 0)
4589 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4590 /* To avoid excessive dumplication of ops we implement shift
4591 by immediate using the variable shift operations. */
4593 /* Shift by immediate:
4594 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4595 /* Right shifts are encoded as N - shift, where N is the
4596 element size in bits. */
4598 shift
= shift
- (1 << (size
+ 3));
4606 imm
= (uint8_t) shift
;
4611 imm
= (uint16_t) shift
;
4622 for (pass
= 0; pass
< count
; pass
++) {
4624 neon_load_reg64(cpu_V0
, rm
+ pass
);
4625 tcg_gen_movi_i64(cpu_V1
, imm
);
4630 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4632 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4637 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4639 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4644 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4646 case 5: /* VSHL, VSLI */
4647 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4651 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4653 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4655 case 7: /* VQSHLU */
4656 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4659 if (op
== 1 || op
== 3) {
4661 neon_load_reg64(cpu_V0
, rd
+ pass
);
4662 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4663 } else if (op
== 4 || (op
== 5 && u
)) {
4665 cpu_abort(env
, "VS[LR]I.64 not implemented");
4667 neon_store_reg64(cpu_V0
, rd
+ pass
);
4668 } else { /* size < 3 */
4669 /* Operands in T0 and T1. */
4670 tmp
= neon_load_reg(rm
, pass
);
4672 tcg_gen_movi_i32(tmp2
, imm
);
4676 GEN_NEON_INTEGER_OP(shl
);
4680 GEN_NEON_INTEGER_OP(rshl
);
4685 GEN_NEON_INTEGER_OP(shl
);
4687 case 5: /* VSHL, VSLI */
4689 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4690 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4691 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4696 GEN_NEON_INTEGER_OP_ENV(qshl
);
4698 case 7: /* VQSHLU */
4700 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4701 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4702 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4709 if (op
== 1 || op
== 3) {
4711 tmp2
= neon_load_reg(rd
, pass
);
4712 gen_neon_add(size
, tmp2
, tmp
);
4714 } else if (op
== 4 || (op
== 5 && u
)) {
4719 mask
= 0xff >> -shift
;
4721 mask
= (uint8_t)(0xff << shift
);
4727 mask
= 0xffff >> -shift
;
4729 mask
= (uint16_t)(0xffff << shift
);
4733 if (shift
< -31 || shift
> 31) {
4737 mask
= 0xffffffffu
>> -shift
;
4739 mask
= 0xffffffffu
<< shift
;
4745 tmp2
= neon_load_reg(rd
, pass
);
4746 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4747 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4748 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4751 neon_store_reg(rd
, pass
, tmp
);
4754 } else if (op
< 10) {
4755 /* Shift by immediate and narrow:
4756 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4757 shift
= shift
- (1 << (size
+ 3));
4761 imm
= (uint16_t)shift
;
4763 tmp2
= tcg_const_i32(imm
);
4764 TCGV_UNUSED_I64(tmp64
);
4767 imm
= (uint32_t)shift
;
4768 tmp2
= tcg_const_i32(imm
);
4769 TCGV_UNUSED_I64(tmp64
);
4772 tmp64
= tcg_const_i64(shift
);
4779 for (pass
= 0; pass
< 2; pass
++) {
4781 neon_load_reg64(cpu_V0
, rm
+ pass
);
4784 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4786 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4789 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4791 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4794 tmp
= neon_load_reg(rm
+ pass
, 0);
4795 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4796 tmp3
= neon_load_reg(rm
+ pass
, 1);
4797 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4798 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4803 if (op
== 8 && !u
) {
4804 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4807 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4809 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4811 neon_store_reg(rd
, pass
, tmp
);
4814 tcg_temp_free_i64(tmp64
);
4818 } else if (op
== 10) {
4822 tmp
= neon_load_reg(rm
, 0);
4823 tmp2
= neon_load_reg(rm
, 1);
4824 for (pass
= 0; pass
< 2; pass
++) {
4828 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4831 /* The shift is less than the width of the source
4832 type, so we can just shift the whole register. */
4833 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4834 if (size
< 2 || !u
) {
4837 imm
= (0xffu
>> (8 - shift
));
4840 imm
= 0xffff >> (16 - shift
);
4842 imm64
= imm
| (((uint64_t)imm
) << 32);
4843 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4846 neon_store_reg64(cpu_V0
, rd
+ pass
);
4848 } else if (op
== 15 || op
== 16) {
4849 /* VCVT fixed-point. */
4850 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4851 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4854 gen_vfp_ulto(0, shift
);
4856 gen_vfp_slto(0, shift
);
4859 gen_vfp_toul(0, shift
);
4861 gen_vfp_tosl(0, shift
);
4863 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4868 } else { /* (insn & 0x00380080) == 0 */
4871 op
= (insn
>> 8) & 0xf;
4872 /* One register and immediate. */
4873 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4874 invert
= (insn
& (1 << 5)) != 0;
4892 imm
= (imm
<< 8) | (imm
<< 24);
4895 imm
= (imm
<< 8) | 0xff;
4898 imm
= (imm
<< 16) | 0xffff;
4901 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4906 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4907 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4913 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4914 if (op
& 1 && op
< 12) {
4915 tmp
= neon_load_reg(rd
, pass
);
4917 /* The immediate value has already been inverted, so
4919 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4921 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4926 if (op
== 14 && invert
) {
4929 for (n
= 0; n
< 4; n
++) {
4930 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4931 val
|= 0xff << (n
* 8);
4933 tcg_gen_movi_i32(tmp
, val
);
4935 tcg_gen_movi_i32(tmp
, imm
);
4938 neon_store_reg(rd
, pass
, tmp
);
4941 } else { /* (insn & 0x00800010 == 0x00800000) */
4943 op
= (insn
>> 8) & 0xf;
4944 if ((insn
& (1 << 6)) == 0) {
4945 /* Three registers of different lengths. */
4949 /* prewiden, src1_wide, src2_wide */
4950 static const int neon_3reg_wide
[16][3] = {
4951 {1, 0, 0}, /* VADDL */
4952 {1, 1, 0}, /* VADDW */
4953 {1, 0, 0}, /* VSUBL */
4954 {1, 1, 0}, /* VSUBW */
4955 {0, 1, 1}, /* VADDHN */
4956 {0, 0, 0}, /* VABAL */
4957 {0, 1, 1}, /* VSUBHN */
4958 {0, 0, 0}, /* VABDL */
4959 {0, 0, 0}, /* VMLAL */
4960 {0, 0, 0}, /* VQDMLAL */
4961 {0, 0, 0}, /* VMLSL */
4962 {0, 0, 0}, /* VQDMLSL */
4963 {0, 0, 0}, /* Integer VMULL */
4964 {0, 0, 0}, /* VQDMULL */
4965 {0, 0, 0} /* Polynomial VMULL */
4968 prewiden
= neon_3reg_wide
[op
][0];
4969 src1_wide
= neon_3reg_wide
[op
][1];
4970 src2_wide
= neon_3reg_wide
[op
][2];
4972 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4975 /* Avoid overlapping operands. Wide source operands are
4976 always aligned so will never overlap with wide
4977 destinations in problematic ways. */
4978 if (rd
== rm
&& !src2_wide
) {
4979 tmp
= neon_load_reg(rm
, 1);
4980 neon_store_scratch(2, tmp
);
4981 } else if (rd
== rn
&& !src1_wide
) {
4982 tmp
= neon_load_reg(rn
, 1);
4983 neon_store_scratch(2, tmp
);
4986 for (pass
= 0; pass
< 2; pass
++) {
4988 neon_load_reg64(cpu_V0
, rn
+ pass
);
4991 if (pass
== 1 && rd
== rn
) {
4992 tmp
= neon_load_scratch(2);
4994 tmp
= neon_load_reg(rn
, pass
);
4997 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5001 neon_load_reg64(cpu_V1
, rm
+ pass
);
5004 if (pass
== 1 && rd
== rm
) {
5005 tmp2
= neon_load_scratch(2);
5007 tmp2
= neon_load_reg(rm
, pass
);
5010 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5014 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5015 gen_neon_addl(size
);
5017 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5018 gen_neon_subl(size
);
5020 case 5: case 7: /* VABAL, VABDL */
5021 switch ((size
<< 1) | u
) {
5023 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5026 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5029 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5032 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5035 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5038 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5045 case 8: case 9: case 10: case 11: case 12: case 13:
5046 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5047 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5051 case 14: /* Polynomial VMULL */
5052 cpu_abort(env
, "Polynomial VMULL not implemented");
5054 default: /* 15 is RESERVED. */
5057 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5059 if (op
== 10 || op
== 11) {
5060 gen_neon_negl(cpu_V0
, size
);
5064 neon_load_reg64(cpu_V1
, rd
+ pass
);
5068 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5069 gen_neon_addl(size
);
5071 case 9: case 11: /* VQDMLAL, VQDMLSL */
5072 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5073 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5076 case 13: /* VQDMULL */
5077 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5082 neon_store_reg64(cpu_V0
, rd
+ pass
);
5083 } else if (op
== 4 || op
== 6) {
5084 /* Narrowing operation. */
5089 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5092 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5095 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5096 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5103 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5106 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5109 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5110 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5111 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5119 neon_store_reg(rd
, 0, tmp3
);
5120 neon_store_reg(rd
, 1, tmp
);
5123 /* Write back the result. */
5124 neon_store_reg64(cpu_V0
, rd
+ pass
);
5128 /* Two registers and a scalar. */
5130 case 0: /* Integer VMLA scalar */
5131 case 1: /* Float VMLA scalar */
5132 case 4: /* Integer VMLS scalar */
5133 case 5: /* Floating point VMLS scalar */
5134 case 8: /* Integer VMUL scalar */
5135 case 9: /* Floating point VMUL scalar */
5136 case 12: /* VQDMULH scalar */
5137 case 13: /* VQRDMULH scalar */
5138 tmp
= neon_get_scalar(size
, rm
);
5139 neon_store_scratch(0, tmp
);
5140 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5141 tmp
= neon_load_scratch(0);
5142 tmp2
= neon_load_reg(rn
, pass
);
5145 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5147 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5149 } else if (op
== 13) {
5151 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5153 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5155 } else if (op
& 1) {
5156 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5159 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5160 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5161 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5168 tmp2
= neon_load_reg(rd
, pass
);
5171 gen_neon_add(size
, tmp
, tmp2
);
5174 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5177 gen_neon_rsb(size
, tmp
, tmp2
);
5180 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5187 neon_store_reg(rd
, pass
, tmp
);
5190 case 2: /* VMLAL sclar */
5191 case 3: /* VQDMLAL scalar */
5192 case 6: /* VMLSL scalar */
5193 case 7: /* VQDMLSL scalar */
5194 case 10: /* VMULL scalar */
5195 case 11: /* VQDMULL scalar */
5196 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5199 tmp2
= neon_get_scalar(size
, rm
);
5200 tmp3
= neon_load_reg(rn
, 1);
5202 for (pass
= 0; pass
< 2; pass
++) {
5204 tmp
= neon_load_reg(rn
, 0);
5208 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5210 if (op
== 6 || op
== 7) {
5211 gen_neon_negl(cpu_V0
, size
);
5214 neon_load_reg64(cpu_V1
, rd
+ pass
);
5218 gen_neon_addl(size
);
5221 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5222 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5228 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5233 neon_store_reg64(cpu_V0
, rd
+ pass
);
5239 default: /* 14 and 15 are RESERVED */
5243 } else { /* size == 3 */
5246 imm
= (insn
>> 8) & 0xf;
5252 neon_load_reg64(cpu_V0
, rn
);
5254 neon_load_reg64(cpu_V1
, rn
+ 1);
5256 } else if (imm
== 8) {
5257 neon_load_reg64(cpu_V0
, rn
+ 1);
5259 neon_load_reg64(cpu_V1
, rm
);
5262 tmp64
= tcg_temp_new_i64();
5264 neon_load_reg64(cpu_V0
, rn
);
5265 neon_load_reg64(tmp64
, rn
+ 1);
5267 neon_load_reg64(cpu_V0
, rn
+ 1);
5268 neon_load_reg64(tmp64
, rm
);
5270 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5271 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5272 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5274 neon_load_reg64(cpu_V1
, rm
);
5276 neon_load_reg64(cpu_V1
, rm
+ 1);
5279 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5280 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5281 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5282 tcg_temp_free_i64(tmp64
);
5285 neon_load_reg64(cpu_V0
, rn
);
5286 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5287 neon_load_reg64(cpu_V1
, rm
);
5288 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5289 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5291 neon_store_reg64(cpu_V0
, rd
);
5293 neon_store_reg64(cpu_V1
, rd
+ 1);
5295 } else if ((insn
& (1 << 11)) == 0) {
5296 /* Two register misc. */
5297 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5298 size
= (insn
>> 18) & 3;
5300 case 0: /* VREV64 */
5303 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5304 tmp
= neon_load_reg(rm
, pass
* 2);
5305 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5307 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5308 case 1: gen_swap_half(tmp
); break;
5309 case 2: /* no-op */ break;
5312 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5314 neon_store_reg(rd
, pass
* 2, tmp2
);
5317 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5318 case 1: gen_swap_half(tmp2
); break;
5321 neon_store_reg(rd
, pass
* 2, tmp2
);
5325 case 4: case 5: /* VPADDL */
5326 case 12: case 13: /* VPADAL */
5329 for (pass
= 0; pass
< q
+ 1; pass
++) {
5330 tmp
= neon_load_reg(rm
, pass
* 2);
5331 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5332 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5333 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5335 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5336 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5337 case 2: tcg_gen_add_i64(CPU_V001
); break;
5342 neon_load_reg64(cpu_V1
, rd
+ pass
);
5343 gen_neon_addl(size
);
5345 neon_store_reg64(cpu_V0
, rd
+ pass
);
5350 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5351 tmp
= neon_load_reg(rm
, n
);
5352 tmp2
= neon_load_reg(rd
, n
+ 1);
5353 neon_store_reg(rm
, n
, tmp2
);
5354 neon_store_reg(rd
, n
+ 1, tmp
);
5362 Rd A3 A2 A1 A0 B2 B0 A2 A0
5363 Rm B3 B2 B1 B0 B3 B1 A3 A1
5367 gen_neon_unzip(rd
, q
, 0, size
);
5368 gen_neon_unzip(rm
, q
, 4, size
);
5370 static int unzip_order_q
[8] =
5371 {0, 2, 4, 6, 1, 3, 5, 7};
5372 for (n
= 0; n
< 8; n
++) {
5373 int reg
= (n
< 4) ? rd
: rm
;
5374 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5375 neon_store_reg(reg
, n
% 4, tmp
);
5378 static int unzip_order
[4] =
5380 for (n
= 0; n
< 4; n
++) {
5381 int reg
= (n
< 2) ? rd
: rm
;
5382 tmp
= neon_load_scratch(unzip_order
[n
]);
5383 neon_store_reg(reg
, n
% 2, tmp
);
5389 Rd A3 A2 A1 A0 B1 A1 B0 A0
5390 Rm B3 B2 B1 B0 B3 A3 B2 A2
5394 count
= (q
? 4 : 2);
5395 for (n
= 0; n
< count
; n
++) {
5396 tmp
= neon_load_reg(rd
, n
);
5397 tmp2
= neon_load_reg(rd
, n
);
5399 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5400 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5401 case 2: /* no-op */; break;
5404 neon_store_scratch(n
* 2, tmp
);
5405 neon_store_scratch(n
* 2 + 1, tmp2
);
5407 for (n
= 0; n
< count
* 2; n
++) {
5408 int reg
= (n
< count
) ? rd
: rm
;
5409 tmp
= neon_load_scratch(n
);
5410 neon_store_reg(reg
, n
% count
, tmp
);
5413 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5417 for (pass
= 0; pass
< 2; pass
++) {
5418 neon_load_reg64(cpu_V0
, rm
+ pass
);
5420 if (op
== 36 && q
== 0) {
5421 gen_neon_narrow(size
, tmp
, cpu_V0
);
5423 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5425 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5430 neon_store_reg(rd
, 0, tmp2
);
5431 neon_store_reg(rd
, 1, tmp
);
5435 case 38: /* VSHLL */
5438 tmp
= neon_load_reg(rm
, 0);
5439 tmp2
= neon_load_reg(rm
, 1);
5440 for (pass
= 0; pass
< 2; pass
++) {
5443 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5444 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5445 neon_store_reg64(cpu_V0
, rd
+ pass
);
5448 case 44: /* VCVT.F16.F32 */
5449 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5453 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5454 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5455 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5456 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5457 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5458 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5459 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5460 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5461 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5462 neon_store_reg(rd
, 0, tmp2
);
5464 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5465 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5466 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5467 neon_store_reg(rd
, 1, tmp2
);
5470 case 46: /* VCVT.F32.F16 */
5471 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5474 tmp
= neon_load_reg(rm
, 0);
5475 tmp2
= neon_load_reg(rm
, 1);
5476 tcg_gen_ext16u_i32(tmp3
, tmp
);
5477 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5478 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5479 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5480 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5481 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5483 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5484 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5485 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5486 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5487 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5488 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5494 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5495 if (op
== 30 || op
== 31 || op
>= 58) {
5496 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5497 neon_reg_offset(rm
, pass
));
5500 tmp
= neon_load_reg(rm
, pass
);
5503 case 1: /* VREV32 */
5505 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5506 case 1: gen_swap_half(tmp
); break;
5510 case 2: /* VREV16 */
5517 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5518 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5519 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5525 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5526 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5527 case 2: gen_helper_clz(tmp
, tmp
); break;
5534 gen_helper_neon_cnt_u8(tmp
, tmp
);
5539 tcg_gen_not_i32(tmp
, tmp
);
5541 case 14: /* VQABS */
5543 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5544 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5545 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5549 case 15: /* VQNEG */
5551 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5552 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5553 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5557 case 16: case 19: /* VCGT #0, VCLE #0 */
5558 tmp2
= tcg_const_i32(0);
5560 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5561 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5562 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5565 tcg_temp_free(tmp2
);
5567 tcg_gen_not_i32(tmp
, tmp
);
5569 case 17: case 20: /* VCGE #0, VCLT #0 */
5570 tmp2
= tcg_const_i32(0);
5572 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5573 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5574 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5577 tcg_temp_free(tmp2
);
5579 tcg_gen_not_i32(tmp
, tmp
);
5581 case 18: /* VCEQ #0 */
5582 tmp2
= tcg_const_i32(0);
5584 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5585 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5586 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5589 tcg_temp_free(tmp2
);
5593 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5594 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5595 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5602 tmp2
= tcg_const_i32(0);
5603 gen_neon_rsb(size
, tmp
, tmp2
);
5604 tcg_temp_free(tmp2
);
5606 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5607 tmp2
= tcg_const_i32(0);
5608 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5609 tcg_temp_free(tmp2
);
5611 tcg_gen_not_i32(tmp
, tmp
);
5613 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5614 tmp2
= tcg_const_i32(0);
5615 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5616 tcg_temp_free(tmp2
);
5618 tcg_gen_not_i32(tmp
, tmp
);
5620 case 26: /* Float VCEQ #0 */
5621 tmp2
= tcg_const_i32(0);
5622 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5623 tcg_temp_free(tmp2
);
5625 case 30: /* Float VABS */
5628 case 31: /* Float VNEG */
5632 tmp2
= neon_load_reg(rd
, pass
);
5633 neon_store_reg(rm
, pass
, tmp2
);
5636 tmp2
= neon_load_reg(rd
, pass
);
5638 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5639 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5643 neon_store_reg(rm
, pass
, tmp2
);
5645 case 56: /* Integer VRECPE */
5646 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5648 case 57: /* Integer VRSQRTE */
5649 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5651 case 58: /* Float VRECPE */
5652 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5654 case 59: /* Float VRSQRTE */
5655 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5657 case 60: /* VCVT.F32.S32 */
5660 case 61: /* VCVT.F32.U32 */
5663 case 62: /* VCVT.S32.F32 */
5666 case 63: /* VCVT.U32.F32 */
5670 /* Reserved: 21, 29, 39-56 */
5673 if (op
== 30 || op
== 31 || op
>= 58) {
5674 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5675 neon_reg_offset(rd
, pass
));
5677 neon_store_reg(rd
, pass
, tmp
);
5682 } else if ((insn
& (1 << 10)) == 0) {
5684 n
= ((insn
>> 5) & 0x18) + 8;
5685 if (insn
& (1 << 6)) {
5686 tmp
= neon_load_reg(rd
, 0);
5689 tcg_gen_movi_i32(tmp
, 0);
5691 tmp2
= neon_load_reg(rm
, 0);
5692 tmp4
= tcg_const_i32(rn
);
5693 tmp5
= tcg_const_i32(n
);
5694 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5696 if (insn
& (1 << 6)) {
5697 tmp
= neon_load_reg(rd
, 1);
5700 tcg_gen_movi_i32(tmp
, 0);
5702 tmp3
= neon_load_reg(rm
, 1);
5703 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5704 tcg_temp_free_i32(tmp5
);
5705 tcg_temp_free_i32(tmp4
);
5706 neon_store_reg(rd
, 0, tmp2
);
5707 neon_store_reg(rd
, 1, tmp3
);
5709 } else if ((insn
& 0x380) == 0) {
5711 if (insn
& (1 << 19)) {
5712 tmp
= neon_load_reg(rm
, 1);
5714 tmp
= neon_load_reg(rm
, 0);
5716 if (insn
& (1 << 16)) {
5717 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5718 } else if (insn
& (1 << 17)) {
5719 if ((insn
>> 18) & 1)
5720 gen_neon_dup_high16(tmp
);
5722 gen_neon_dup_low16(tmp
);
5724 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5726 tcg_gen_mov_i32(tmp2
, tmp
);
5727 neon_store_reg(rd
, pass
, tmp2
);
5738 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5740 int crn
= (insn
>> 16) & 0xf;
5741 int crm
= insn
& 0xf;
5742 int op1
= (insn
>> 21) & 7;
5743 int op2
= (insn
>> 5) & 7;
5744 int rt
= (insn
>> 12) & 0xf;
5747 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5748 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5752 tmp
= load_cpu_field(teecr
);
5753 store_reg(s
, rt
, tmp
);
5756 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5758 if (IS_USER(s
) && (env
->teecr
& 1))
5760 tmp
= load_cpu_field(teehbr
);
5761 store_reg(s
, rt
, tmp
);
5765 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5766 op1
, crn
, crm
, op2
);
5770 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5772 int crn
= (insn
>> 16) & 0xf;
5773 int crm
= insn
& 0xf;
5774 int op1
= (insn
>> 21) & 7;
5775 int op2
= (insn
>> 5) & 7;
5776 int rt
= (insn
>> 12) & 0xf;
5779 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5780 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5784 tmp
= load_reg(s
, rt
);
5785 gen_helper_set_teecr(cpu_env
, tmp
);
5789 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5791 if (IS_USER(s
) && (env
->teecr
& 1))
5793 tmp
= load_reg(s
, rt
);
5794 store_cpu_field(tmp
, teehbr
);
5798 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5799 op1
, crn
, crm
, op2
);
5803 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5807 cpnum
= (insn
>> 8) & 0xf;
5808 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5809 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5815 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5816 return disas_iwmmxt_insn(env
, s
, insn
);
5817 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5818 return disas_dsp_insn(env
, s
, insn
);
5823 return disas_vfp_insn (env
, s
, insn
);
5825 /* Coprocessors 7-15 are architecturally reserved by ARM.
5826 Unfortunately Intel decided to ignore this. */
5827 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5829 if (insn
& (1 << 20))
5830 return disas_cp14_read(env
, s
, insn
);
5832 return disas_cp14_write(env
, s
, insn
);
5834 return disas_cp15_insn (env
, s
, insn
);
5837 /* Unknown coprocessor. See if the board has hooked it. */
5838 return disas_cp_insn (env
, s
, insn
);
5843 /* Store a 64-bit value to a register pair. Clobbers val. */
5844 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5848 tcg_gen_trunc_i64_i32(tmp
, val
);
5849 store_reg(s
, rlow
, tmp
);
5851 tcg_gen_shri_i64(val
, val
, 32);
5852 tcg_gen_trunc_i64_i32(tmp
, val
);
5853 store_reg(s
, rhigh
, tmp
);
5856 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5857 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5862 /* Load value and extend to 64 bits. */
5863 tmp
= tcg_temp_new_i64();
5864 tmp2
= load_reg(s
, rlow
);
5865 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5867 tcg_gen_add_i64(val
, val
, tmp
);
5868 tcg_temp_free_i64(tmp
);
5871 /* load and add a 64-bit value from a register pair. */
5872 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5878 /* Load 64-bit value rd:rn. */
5879 tmpl
= load_reg(s
, rlow
);
5880 tmph
= load_reg(s
, rhigh
);
5881 tmp
= tcg_temp_new_i64();
5882 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5885 tcg_gen_add_i64(val
, val
, tmp
);
5886 tcg_temp_free_i64(tmp
);
5889 /* Set N and Z flags from a 64-bit value. */
5890 static void gen_logicq_cc(TCGv_i64 val
)
5892 TCGv tmp
= new_tmp();
5893 gen_helper_logicq_cc(tmp
, val
);
5898 /* Load/Store exclusive instructions are implemented by remembering
5899 the value/address loaded, and seeing if these are the same
5900 when the store is performed. This should be is sufficient to implement
5901 the architecturally mandated semantics, and avoids having to monitor
5904 In system emulation mode only one CPU will be running at once, so
5905 this sequence is effectively atomic. In user emulation mode we
5906 throw an exception and handle the atomic operation elsewhere. */
5907 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
5908 TCGv addr
, int size
)
5914 tmp
= gen_ld8u(addr
, IS_USER(s
));
5917 tmp
= gen_ld16u(addr
, IS_USER(s
));
5921 tmp
= gen_ld32(addr
, IS_USER(s
));
5926 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
5927 store_reg(s
, rt
, tmp
);
5929 tcg_gen_addi_i32(addr
, addr
, 4);
5930 tmp
= gen_ld32(addr
, IS_USER(s
));
5931 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
5932 store_reg(s
, rt2
, tmp
);
5934 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
5937 static void gen_clrex(DisasContext
*s
)
5939 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
5942 #ifdef CONFIG_USER_ONLY
5943 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5944 TCGv addr
, int size
)
5946 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
5947 tcg_gen_movi_i32(cpu_exclusive_info
,
5948 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
5949 gen_set_condexec(s
);
5950 gen_set_pc_im(s
->pc
- 4);
5951 gen_exception(EXCP_STREX
);
5952 s
->is_jmp
= DISAS_JUMP
;
5955 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5956 TCGv addr
, int size
)
5962 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5968 fail_label
= gen_new_label();
5969 done_label
= gen_new_label();
5970 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
5973 tmp
= gen_ld8u(addr
, IS_USER(s
));
5976 tmp
= gen_ld16u(addr
, IS_USER(s
));
5980 tmp
= gen_ld32(addr
, IS_USER(s
));
5985 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
5988 TCGv tmp2
= new_tmp();
5989 tcg_gen_addi_i32(tmp2
, addr
, 4);
5990 tmp
= gen_ld32(addr
, IS_USER(s
));
5992 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
5995 tmp
= load_reg(s
, rt
);
5998 gen_st8(tmp
, addr
, IS_USER(s
));
6001 gen_st16(tmp
, addr
, IS_USER(s
));
6005 gen_st32(tmp
, addr
, IS_USER(s
));
6011 tcg_gen_addi_i32(addr
, addr
, 4);
6012 tmp
= load_reg(s
, rt2
);
6013 gen_st32(tmp
, addr
, IS_USER(s
));
6015 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6016 tcg_gen_br(done_label
);
6017 gen_set_label(fail_label
);
6018 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6019 gen_set_label(done_label
);
6020 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6024 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
6026 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6033 insn
= ldl_code(s
->pc
);
6036 /* M variants do not implement ARM mode. */
6041 /* Unconditional instructions. */
6042 if (((insn
>> 25) & 7) == 1) {
6043 /* NEON Data processing. */
6044 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6047 if (disas_neon_data_insn(env
, s
, insn
))
6051 if ((insn
& 0x0f100000) == 0x04000000) {
6052 /* NEON load/store. */
6053 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6056 if (disas_neon_ls_insn(env
, s
, insn
))
6060 if ((insn
& 0x0d70f000) == 0x0550f000)
6062 else if ((insn
& 0x0ffffdff) == 0x01010000) {
6065 if (insn
& (1 << 9)) {
6066 /* BE8 mode not implemented. */
6070 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6071 switch ((insn
>> 4) & 0xf) {
6080 /* We don't emulate caches so these are a no-op. */
6085 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6091 op1
= (insn
& 0x1f);
6092 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6093 addr
= load_reg(s
, 13);
6096 tmp
= tcg_const_i32(op1
);
6097 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6098 tcg_temp_free_i32(tmp
);
6100 i
= (insn
>> 23) & 3;
6102 case 0: offset
= -4; break; /* DA */
6103 case 1: offset
= 0; break; /* IA */
6104 case 2: offset
= -8; break; /* DB */
6105 case 3: offset
= 4; break; /* IB */
6109 tcg_gen_addi_i32(addr
, addr
, offset
);
6110 tmp
= load_reg(s
, 14);
6111 gen_st32(tmp
, addr
, 0);
6112 tmp
= load_cpu_field(spsr
);
6113 tcg_gen_addi_i32(addr
, addr
, 4);
6114 gen_st32(tmp
, addr
, 0);
6115 if (insn
& (1 << 21)) {
6116 /* Base writeback. */
6118 case 0: offset
= -8; break;
6119 case 1: offset
= 4; break;
6120 case 2: offset
= -4; break;
6121 case 3: offset
= 0; break;
6125 tcg_gen_addi_i32(addr
, addr
, offset
);
6126 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
6127 store_reg(s
, 13, addr
);
6129 tmp
= tcg_const_i32(op1
);
6130 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6131 tcg_temp_free_i32(tmp
);
6138 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6144 rn
= (insn
>> 16) & 0xf;
6145 addr
= load_reg(s
, rn
);
6146 i
= (insn
>> 23) & 3;
6148 case 0: offset
= -4; break; /* DA */
6149 case 1: offset
= 0; break; /* IA */
6150 case 2: offset
= -8; break; /* DB */
6151 case 3: offset
= 4; break; /* IB */
6155 tcg_gen_addi_i32(addr
, addr
, offset
);
6156 /* Load PC into tmp and CPSR into tmp2. */
6157 tmp
= gen_ld32(addr
, 0);
6158 tcg_gen_addi_i32(addr
, addr
, 4);
6159 tmp2
= gen_ld32(addr
, 0);
6160 if (insn
& (1 << 21)) {
6161 /* Base writeback. */
6163 case 0: offset
= -8; break;
6164 case 1: offset
= 4; break;
6165 case 2: offset
= -4; break;
6166 case 3: offset
= 0; break;
6170 tcg_gen_addi_i32(addr
, addr
, offset
);
6171 store_reg(s
, rn
, addr
);
6175 gen_rfe(s
, tmp
, tmp2
);
6177 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6178 /* branch link and change to thumb (blx <offset>) */
6181 val
= (uint32_t)s
->pc
;
6183 tcg_gen_movi_i32(tmp
, val
);
6184 store_reg(s
, 14, tmp
);
6185 /* Sign-extend the 24-bit offset */
6186 offset
= (((int32_t)insn
) << 8) >> 8;
6187 /* offset * 4 + bit24 * 2 + (thumb bit) */
6188 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6189 /* pipeline offset */
6193 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6194 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6195 /* iWMMXt register transfer. */
6196 if (env
->cp15
.c15_cpar
& (1 << 1))
6197 if (!disas_iwmmxt_insn(env
, s
, insn
))
6200 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6201 /* Coprocessor double register transfer. */
6202 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6203 /* Additional coprocessor register transfer. */
6204 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6207 /* cps (privileged) */
6211 if (insn
& (1 << 19)) {
6212 if (insn
& (1 << 8))
6214 if (insn
& (1 << 7))
6216 if (insn
& (1 << 6))
6218 if (insn
& (1 << 18))
6221 if (insn
& (1 << 17)) {
6223 val
|= (insn
& 0x1f);
6226 gen_set_psr_im(s
, mask
, 0, val
);
6233 /* if not always execute, we generate a conditional jump to
6235 s
->condlabel
= gen_new_label();
6236 gen_test_cc(cond
^ 1, s
->condlabel
);
6239 if ((insn
& 0x0f900000) == 0x03000000) {
6240 if ((insn
& (1 << 21)) == 0) {
6242 rd
= (insn
>> 12) & 0xf;
6243 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6244 if ((insn
& (1 << 22)) == 0) {
6247 tcg_gen_movi_i32(tmp
, val
);
6250 tmp
= load_reg(s
, rd
);
6251 tcg_gen_ext16u_i32(tmp
, tmp
);
6252 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6254 store_reg(s
, rd
, tmp
);
6256 if (((insn
>> 12) & 0xf) != 0xf)
6258 if (((insn
>> 16) & 0xf) == 0) {
6259 gen_nop_hint(s
, insn
& 0xff);
6261 /* CPSR = immediate */
6263 shift
= ((insn
>> 8) & 0xf) * 2;
6265 val
= (val
>> shift
) | (val
<< (32 - shift
));
6266 i
= ((insn
& (1 << 22)) != 0);
6267 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6271 } else if ((insn
& 0x0f900000) == 0x01000000
6272 && (insn
& 0x00000090) != 0x00000090) {
6273 /* miscellaneous instructions */
6274 op1
= (insn
>> 21) & 3;
6275 sh
= (insn
>> 4) & 0xf;
6278 case 0x0: /* move program status register */
6281 tmp
= load_reg(s
, rm
);
6282 i
= ((op1
& 2) != 0);
6283 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6287 rd
= (insn
>> 12) & 0xf;
6291 tmp
= load_cpu_field(spsr
);
6294 gen_helper_cpsr_read(tmp
);
6296 store_reg(s
, rd
, tmp
);
6301 /* branch/exchange thumb (bx). */
6302 tmp
= load_reg(s
, rm
);
6304 } else if (op1
== 3) {
6306 rd
= (insn
>> 12) & 0xf;
6307 tmp
= load_reg(s
, rm
);
6308 gen_helper_clz(tmp
, tmp
);
6309 store_reg(s
, rd
, tmp
);
6317 /* Trivial implementation equivalent to bx. */
6318 tmp
= load_reg(s
, rm
);
6328 /* branch link/exchange thumb (blx) */
6329 tmp
= load_reg(s
, rm
);
6331 tcg_gen_movi_i32(tmp2
, s
->pc
);
6332 store_reg(s
, 14, tmp2
);
6335 case 0x5: /* saturating add/subtract */
6336 rd
= (insn
>> 12) & 0xf;
6337 rn
= (insn
>> 16) & 0xf;
6338 tmp
= load_reg(s
, rm
);
6339 tmp2
= load_reg(s
, rn
);
6341 gen_helper_double_saturate(tmp2
, tmp2
);
6343 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6345 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6347 store_reg(s
, rd
, tmp
);
6350 gen_set_condexec(s
);
6351 gen_set_pc_im(s
->pc
- 4);
6352 gen_exception(EXCP_BKPT
);
6353 s
->is_jmp
= DISAS_JUMP
;
6355 case 0x8: /* signed multiply */
6359 rs
= (insn
>> 8) & 0xf;
6360 rn
= (insn
>> 12) & 0xf;
6361 rd
= (insn
>> 16) & 0xf;
6363 /* (32 * 16) >> 16 */
6364 tmp
= load_reg(s
, rm
);
6365 tmp2
= load_reg(s
, rs
);
6367 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6370 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6371 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6373 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6374 tcg_temp_free_i64(tmp64
);
6375 if ((sh
& 2) == 0) {
6376 tmp2
= load_reg(s
, rn
);
6377 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6380 store_reg(s
, rd
, tmp
);
6383 tmp
= load_reg(s
, rm
);
6384 tmp2
= load_reg(s
, rs
);
6385 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6388 tmp64
= tcg_temp_new_i64();
6389 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6391 gen_addq(s
, tmp64
, rn
, rd
);
6392 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6393 tcg_temp_free_i64(tmp64
);
6396 tmp2
= load_reg(s
, rn
);
6397 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6400 store_reg(s
, rd
, tmp
);
6407 } else if (((insn
& 0x0e000000) == 0 &&
6408 (insn
& 0x00000090) != 0x90) ||
6409 ((insn
& 0x0e000000) == (1 << 25))) {
6410 int set_cc
, logic_cc
, shiftop
;
6412 op1
= (insn
>> 21) & 0xf;
6413 set_cc
= (insn
>> 20) & 1;
6414 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6416 /* data processing instruction */
6417 if (insn
& (1 << 25)) {
6418 /* immediate operand */
6420 shift
= ((insn
>> 8) & 0xf) * 2;
6422 val
= (val
>> shift
) | (val
<< (32 - shift
));
6425 tcg_gen_movi_i32(tmp2
, val
);
6426 if (logic_cc
&& shift
) {
6427 gen_set_CF_bit31(tmp2
);
6432 tmp2
= load_reg(s
, rm
);
6433 shiftop
= (insn
>> 5) & 3;
6434 if (!(insn
& (1 << 4))) {
6435 shift
= (insn
>> 7) & 0x1f;
6436 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6438 rs
= (insn
>> 8) & 0xf;
6439 tmp
= load_reg(s
, rs
);
6440 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6443 if (op1
!= 0x0f && op1
!= 0x0d) {
6444 rn
= (insn
>> 16) & 0xf;
6445 tmp
= load_reg(s
, rn
);
6449 rd
= (insn
>> 12) & 0xf;
6452 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6456 store_reg_bx(env
, s
, rd
, tmp
);
6459 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6463 store_reg_bx(env
, s
, rd
, tmp
);
6466 if (set_cc
&& rd
== 15) {
6467 /* SUBS r15, ... is used for exception return. */
6471 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6472 gen_exception_return(s
, tmp
);
6475 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6477 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6479 store_reg_bx(env
, s
, rd
, tmp
);
6484 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6486 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6488 store_reg_bx(env
, s
, rd
, tmp
);
6492 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6494 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6496 store_reg_bx(env
, s
, rd
, tmp
);
6500 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6502 gen_add_carry(tmp
, tmp
, tmp2
);
6504 store_reg_bx(env
, s
, rd
, tmp
);
6508 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6510 gen_sub_carry(tmp
, tmp
, tmp2
);
6512 store_reg_bx(env
, s
, rd
, tmp
);
6516 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6518 gen_sub_carry(tmp
, tmp2
, tmp
);
6520 store_reg_bx(env
, s
, rd
, tmp
);
6524 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6531 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6538 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6544 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6549 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6553 store_reg_bx(env
, s
, rd
, tmp
);
6556 if (logic_cc
&& rd
== 15) {
6557 /* MOVS r15, ... is used for exception return. */
6561 gen_exception_return(s
, tmp2
);
6566 store_reg_bx(env
, s
, rd
, tmp2
);
6570 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6574 store_reg_bx(env
, s
, rd
, tmp
);
6578 tcg_gen_not_i32(tmp2
, tmp2
);
6582 store_reg_bx(env
, s
, rd
, tmp2
);
6585 if (op1
!= 0x0f && op1
!= 0x0d) {
6589 /* other instructions */
6590 op1
= (insn
>> 24) & 0xf;
6594 /* multiplies, extra load/stores */
6595 sh
= (insn
>> 5) & 3;
6598 rd
= (insn
>> 16) & 0xf;
6599 rn
= (insn
>> 12) & 0xf;
6600 rs
= (insn
>> 8) & 0xf;
6602 op1
= (insn
>> 20) & 0xf;
6604 case 0: case 1: case 2: case 3: case 6:
6606 tmp
= load_reg(s
, rs
);
6607 tmp2
= load_reg(s
, rm
);
6608 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6610 if (insn
& (1 << 22)) {
6611 /* Subtract (mls) */
6613 tmp2
= load_reg(s
, rn
);
6614 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6616 } else if (insn
& (1 << 21)) {
6618 tmp2
= load_reg(s
, rn
);
6619 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6622 if (insn
& (1 << 20))
6624 store_reg(s
, rd
, tmp
);
6628 tmp
= load_reg(s
, rs
);
6629 tmp2
= load_reg(s
, rm
);
6630 if (insn
& (1 << 22))
6631 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6633 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6634 if (insn
& (1 << 21)) /* mult accumulate */
6635 gen_addq(s
, tmp64
, rn
, rd
);
6636 if (!(insn
& (1 << 23))) { /* double accumulate */
6638 gen_addq_lo(s
, tmp64
, rn
);
6639 gen_addq_lo(s
, tmp64
, rd
);
6641 if (insn
& (1 << 20))
6642 gen_logicq_cc(tmp64
);
6643 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6644 tcg_temp_free_i64(tmp64
);
6648 rn
= (insn
>> 16) & 0xf;
6649 rd
= (insn
>> 12) & 0xf;
6650 if (insn
& (1 << 23)) {
6651 /* load/store exclusive */
6652 op1
= (insn
>> 21) & 0x3;
6657 addr
= tcg_temp_local_new_i32();
6658 load_reg_var(s
, addr
, rn
);
6659 if (insn
& (1 << 20)) {
6662 gen_load_exclusive(s
, rd
, 15, addr
, 2);
6664 case 1: /* ldrexd */
6665 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
6667 case 2: /* ldrexb */
6668 gen_load_exclusive(s
, rd
, 15, addr
, 0);
6670 case 3: /* ldrexh */
6671 gen_load_exclusive(s
, rd
, 15, addr
, 1);
6680 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
6682 case 1: /* strexd */
6683 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
6685 case 2: /* strexb */
6686 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
6688 case 3: /* strexh */
6689 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
6695 tcg_temp_free(addr
);
6697 /* SWP instruction */
6700 /* ??? This is not really atomic. However we know
6701 we never have multiple CPUs running in parallel,
6702 so it is good enough. */
6703 addr
= load_reg(s
, rn
);
6704 tmp
= load_reg(s
, rm
);
6705 if (insn
& (1 << 22)) {
6706 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6707 gen_st8(tmp
, addr
, IS_USER(s
));
6709 tmp2
= gen_ld32(addr
, IS_USER(s
));
6710 gen_st32(tmp
, addr
, IS_USER(s
));
6713 store_reg(s
, rd
, tmp2
);
6719 /* Misc load/store */
6720 rn
= (insn
>> 16) & 0xf;
6721 rd
= (insn
>> 12) & 0xf;
6722 addr
= load_reg(s
, rn
);
6723 if (insn
& (1 << 24))
6724 gen_add_datah_offset(s
, insn
, 0, addr
);
6726 if (insn
& (1 << 20)) {
6730 tmp
= gen_ld16u(addr
, IS_USER(s
));
6733 tmp
= gen_ld8s(addr
, IS_USER(s
));
6737 tmp
= gen_ld16s(addr
, IS_USER(s
));
6741 } else if (sh
& 2) {
6745 tmp
= load_reg(s
, rd
);
6746 gen_st32(tmp
, addr
, IS_USER(s
));
6747 tcg_gen_addi_i32(addr
, addr
, 4);
6748 tmp
= load_reg(s
, rd
+ 1);
6749 gen_st32(tmp
, addr
, IS_USER(s
));
6753 tmp
= gen_ld32(addr
, IS_USER(s
));
6754 store_reg(s
, rd
, tmp
);
6755 tcg_gen_addi_i32(addr
, addr
, 4);
6756 tmp
= gen_ld32(addr
, IS_USER(s
));
6760 address_offset
= -4;
6763 tmp
= load_reg(s
, rd
);
6764 gen_st16(tmp
, addr
, IS_USER(s
));
6767 /* Perform base writeback before the loaded value to
6768 ensure correct behavior with overlapping index registers.
6769 ldrd with base writeback is is undefined if the
6770 destination and index registers overlap. */
6771 if (!(insn
& (1 << 24))) {
6772 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6773 store_reg(s
, rn
, addr
);
6774 } else if (insn
& (1 << 21)) {
6776 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6777 store_reg(s
, rn
, addr
);
6782 /* Complete the load. */
6783 store_reg(s
, rd
, tmp
);
6792 if (insn
& (1 << 4)) {
6794 /* Armv6 Media instructions. */
6796 rn
= (insn
>> 16) & 0xf;
6797 rd
= (insn
>> 12) & 0xf;
6798 rs
= (insn
>> 8) & 0xf;
6799 switch ((insn
>> 23) & 3) {
6800 case 0: /* Parallel add/subtract. */
6801 op1
= (insn
>> 20) & 7;
6802 tmp
= load_reg(s
, rn
);
6803 tmp2
= load_reg(s
, rm
);
6804 sh
= (insn
>> 5) & 7;
6805 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6807 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6809 store_reg(s
, rd
, tmp
);
6812 if ((insn
& 0x00700020) == 0) {
6813 /* Halfword pack. */
6814 tmp
= load_reg(s
, rn
);
6815 tmp2
= load_reg(s
, rm
);
6816 shift
= (insn
>> 7) & 0x1f;
6817 if (insn
& (1 << 6)) {
6821 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6822 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6823 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6827 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6828 tcg_gen_ext16u_i32(tmp
, tmp
);
6829 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6831 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6833 store_reg(s
, rd
, tmp
);
6834 } else if ((insn
& 0x00200020) == 0x00200000) {
6836 tmp
= load_reg(s
, rm
);
6837 shift
= (insn
>> 7) & 0x1f;
6838 if (insn
& (1 << 6)) {
6841 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6843 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6845 sh
= (insn
>> 16) & 0x1f;
6847 tmp2
= tcg_const_i32(sh
);
6848 if (insn
& (1 << 22))
6849 gen_helper_usat(tmp
, tmp
, tmp2
);
6851 gen_helper_ssat(tmp
, tmp
, tmp2
);
6852 tcg_temp_free_i32(tmp2
);
6854 store_reg(s
, rd
, tmp
);
6855 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6857 tmp
= load_reg(s
, rm
);
6858 sh
= (insn
>> 16) & 0x1f;
6860 tmp2
= tcg_const_i32(sh
);
6861 if (insn
& (1 << 22))
6862 gen_helper_usat16(tmp
, tmp
, tmp2
);
6864 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6865 tcg_temp_free_i32(tmp2
);
6867 store_reg(s
, rd
, tmp
);
6868 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6870 tmp
= load_reg(s
, rn
);
6871 tmp2
= load_reg(s
, rm
);
6873 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6874 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6877 store_reg(s
, rd
, tmp
);
6878 } else if ((insn
& 0x000003e0) == 0x00000060) {
6879 tmp
= load_reg(s
, rm
);
6880 shift
= (insn
>> 10) & 3;
6881 /* ??? In many cases it's not neccessary to do a
6882 rotate, a shift is sufficient. */
6884 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6885 op1
= (insn
>> 20) & 7;
6887 case 0: gen_sxtb16(tmp
); break;
6888 case 2: gen_sxtb(tmp
); break;
6889 case 3: gen_sxth(tmp
); break;
6890 case 4: gen_uxtb16(tmp
); break;
6891 case 6: gen_uxtb(tmp
); break;
6892 case 7: gen_uxth(tmp
); break;
6893 default: goto illegal_op
;
6896 tmp2
= load_reg(s
, rn
);
6897 if ((op1
& 3) == 0) {
6898 gen_add16(tmp
, tmp2
);
6900 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6904 store_reg(s
, rd
, tmp
);
6905 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6907 tmp
= load_reg(s
, rm
);
6908 if (insn
& (1 << 22)) {
6909 if (insn
& (1 << 7)) {
6913 gen_helper_rbit(tmp
, tmp
);
6916 if (insn
& (1 << 7))
6919 tcg_gen_bswap32_i32(tmp
, tmp
);
6921 store_reg(s
, rd
, tmp
);
6926 case 2: /* Multiplies (Type 3). */
6927 tmp
= load_reg(s
, rm
);
6928 tmp2
= load_reg(s
, rs
);
6929 if (insn
& (1 << 20)) {
6930 /* Signed multiply most significant [accumulate]. */
6931 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6932 if (insn
& (1 << 5))
6933 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6934 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6936 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6937 tcg_temp_free_i64(tmp64
);
6939 tmp2
= load_reg(s
, rd
);
6940 if (insn
& (1 << 6)) {
6941 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6943 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6947 store_reg(s
, rn
, tmp
);
6949 if (insn
& (1 << 5))
6950 gen_swap_half(tmp2
);
6951 gen_smul_dual(tmp
, tmp2
);
6952 /* This addition cannot overflow. */
6953 if (insn
& (1 << 6)) {
6954 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6956 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6959 if (insn
& (1 << 22)) {
6960 /* smlald, smlsld */
6961 tmp64
= tcg_temp_new_i64();
6962 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6964 gen_addq(s
, tmp64
, rd
, rn
);
6965 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6966 tcg_temp_free_i64(tmp64
);
6968 /* smuad, smusd, smlad, smlsd */
6971 tmp2
= load_reg(s
, rd
);
6972 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6975 store_reg(s
, rn
, tmp
);
6980 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6982 case 0: /* Unsigned sum of absolute differences. */
6984 tmp
= load_reg(s
, rm
);
6985 tmp2
= load_reg(s
, rs
);
6986 gen_helper_usad8(tmp
, tmp
, tmp2
);
6989 tmp2
= load_reg(s
, rd
);
6990 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6993 store_reg(s
, rn
, tmp
);
6995 case 0x20: case 0x24: case 0x28: case 0x2c:
6996 /* Bitfield insert/clear. */
6998 shift
= (insn
>> 7) & 0x1f;
6999 i
= (insn
>> 16) & 0x1f;
7003 tcg_gen_movi_i32(tmp
, 0);
7005 tmp
= load_reg(s
, rm
);
7008 tmp2
= load_reg(s
, rd
);
7009 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
7012 store_reg(s
, rd
, tmp
);
7014 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7015 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7017 tmp
= load_reg(s
, rm
);
7018 shift
= (insn
>> 7) & 0x1f;
7019 i
= ((insn
>> 16) & 0x1f) + 1;
7024 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7026 gen_sbfx(tmp
, shift
, i
);
7029 store_reg(s
, rd
, tmp
);
7039 /* Check for undefined extension instructions
7040 * per the ARM Bible IE:
7041 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7043 sh
= (0xf << 20) | (0xf << 4);
7044 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7048 /* load/store byte/word */
7049 rn
= (insn
>> 16) & 0xf;
7050 rd
= (insn
>> 12) & 0xf;
7051 tmp2
= load_reg(s
, rn
);
7052 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7053 if (insn
& (1 << 24))
7054 gen_add_data_offset(s
, insn
, tmp2
);
7055 if (insn
& (1 << 20)) {
7057 if (insn
& (1 << 22)) {
7058 tmp
= gen_ld8u(tmp2
, i
);
7060 tmp
= gen_ld32(tmp2
, i
);
7064 tmp
= load_reg(s
, rd
);
7065 if (insn
& (1 << 22))
7066 gen_st8(tmp
, tmp2
, i
);
7068 gen_st32(tmp
, tmp2
, i
);
7070 if (!(insn
& (1 << 24))) {
7071 gen_add_data_offset(s
, insn
, tmp2
);
7072 store_reg(s
, rn
, tmp2
);
7073 } else if (insn
& (1 << 21)) {
7074 store_reg(s
, rn
, tmp2
);
7078 if (insn
& (1 << 20)) {
7079 /* Complete the load. */
7083 store_reg(s
, rd
, tmp
);
7089 int j
, n
, user
, loaded_base
;
7091 /* load/store multiple words */
7092 /* XXX: store correct base if write back */
7094 if (insn
& (1 << 22)) {
7096 goto illegal_op
; /* only usable in supervisor mode */
7098 if ((insn
& (1 << 15)) == 0)
7101 rn
= (insn
>> 16) & 0xf;
7102 addr
= load_reg(s
, rn
);
7104 /* compute total size */
7106 TCGV_UNUSED(loaded_var
);
7109 if (insn
& (1 << i
))
7112 /* XXX: test invalid n == 0 case ? */
7113 if (insn
& (1 << 23)) {
7114 if (insn
& (1 << 24)) {
7116 tcg_gen_addi_i32(addr
, addr
, 4);
7118 /* post increment */
7121 if (insn
& (1 << 24)) {
7123 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7125 /* post decrement */
7127 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7132 if (insn
& (1 << i
)) {
7133 if (insn
& (1 << 20)) {
7135 tmp
= gen_ld32(addr
, IS_USER(s
));
7139 tmp2
= tcg_const_i32(i
);
7140 gen_helper_set_user_reg(tmp2
, tmp
);
7141 tcg_temp_free_i32(tmp2
);
7143 } else if (i
== rn
) {
7147 store_reg(s
, i
, tmp
);
7152 /* special case: r15 = PC + 8 */
7153 val
= (long)s
->pc
+ 4;
7155 tcg_gen_movi_i32(tmp
, val
);
7158 tmp2
= tcg_const_i32(i
);
7159 gen_helper_get_user_reg(tmp
, tmp2
);
7160 tcg_temp_free_i32(tmp2
);
7162 tmp
= load_reg(s
, i
);
7164 gen_st32(tmp
, addr
, IS_USER(s
));
7167 /* no need to add after the last transfer */
7169 tcg_gen_addi_i32(addr
, addr
, 4);
7172 if (insn
& (1 << 21)) {
7174 if (insn
& (1 << 23)) {
7175 if (insn
& (1 << 24)) {
7178 /* post increment */
7179 tcg_gen_addi_i32(addr
, addr
, 4);
7182 if (insn
& (1 << 24)) {
7185 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7187 /* post decrement */
7188 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7191 store_reg(s
, rn
, addr
);
7196 store_reg(s
, rn
, loaded_var
);
7198 if ((insn
& (1 << 22)) && !user
) {
7199 /* Restore CPSR from SPSR. */
7200 tmp
= load_cpu_field(spsr
);
7201 gen_set_cpsr(tmp
, 0xffffffff);
7203 s
->is_jmp
= DISAS_UPDATE
;
7212 /* branch (and link) */
7213 val
= (int32_t)s
->pc
;
7214 if (insn
& (1 << 24)) {
7216 tcg_gen_movi_i32(tmp
, val
);
7217 store_reg(s
, 14, tmp
);
7219 offset
= (((int32_t)insn
<< 8) >> 8);
7220 val
+= (offset
<< 2) + 4;
7228 if (disas_coproc_insn(env
, s
, insn
))
7233 gen_set_pc_im(s
->pc
);
7234 s
->is_jmp
= DISAS_SWI
;
7238 gen_set_condexec(s
);
7239 gen_set_pc_im(s
->pc
- 4);
7240 gen_exception(EXCP_UDEF
);
7241 s
->is_jmp
= DISAS_JUMP
;
7247 /* Return true if this is a Thumb-2 logical op. */
7249 thumb2_logic_op(int op
)
7254 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7255 then set condition code flags based on the result of the operation.
7256 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7257 to the high bit of T1.
7258 Returns zero if the opcode is valid. */
7261 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7268 tcg_gen_and_i32(t0
, t0
, t1
);
7272 tcg_gen_andc_i32(t0
, t0
, t1
);
7276 tcg_gen_or_i32(t0
, t0
, t1
);
7280 tcg_gen_not_i32(t1
, t1
);
7281 tcg_gen_or_i32(t0
, t0
, t1
);
7285 tcg_gen_xor_i32(t0
, t0
, t1
);
7290 gen_helper_add_cc(t0
, t0
, t1
);
7292 tcg_gen_add_i32(t0
, t0
, t1
);
7296 gen_helper_adc_cc(t0
, t0
, t1
);
7302 gen_helper_sbc_cc(t0
, t0
, t1
);
7304 gen_sub_carry(t0
, t0
, t1
);
7308 gen_helper_sub_cc(t0
, t0
, t1
);
7310 tcg_gen_sub_i32(t0
, t0
, t1
);
7314 gen_helper_sub_cc(t0
, t1
, t0
);
7316 tcg_gen_sub_i32(t0
, t1
, t0
);
7318 default: /* 5, 6, 7, 9, 12, 15. */
7324 gen_set_CF_bit31(t1
);
7329 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7331 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7333 uint32_t insn
, imm
, shift
, offset
;
7334 uint32_t rd
, rn
, rm
, rs
;
7345 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7346 || arm_feature (env
, ARM_FEATURE_M
))) {
7347 /* Thumb-1 cores may need to treat bl and blx as a pair of
7348 16-bit instructions to get correct prefetch abort behavior. */
7350 if ((insn
& (1 << 12)) == 0) {
7351 /* Second half of blx. */
7352 offset
= ((insn
& 0x7ff) << 1);
7353 tmp
= load_reg(s
, 14);
7354 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7355 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7358 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7359 store_reg(s
, 14, tmp2
);
7363 if (insn
& (1 << 11)) {
7364 /* Second half of bl. */
7365 offset
= ((insn
& 0x7ff) << 1) | 1;
7366 tmp
= load_reg(s
, 14);
7367 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7370 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7371 store_reg(s
, 14, tmp2
);
7375 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7376 /* Instruction spans a page boundary. Implement it as two
7377 16-bit instructions in case the second half causes an
7379 offset
= ((int32_t)insn
<< 21) >> 9;
7380 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7383 /* Fall through to 32-bit decode. */
7386 insn
= lduw_code(s
->pc
);
7388 insn
|= (uint32_t)insn_hw1
<< 16;
7390 if ((insn
& 0xf800e800) != 0xf000e800) {
7394 rn
= (insn
>> 16) & 0xf;
7395 rs
= (insn
>> 12) & 0xf;
7396 rd
= (insn
>> 8) & 0xf;
7398 switch ((insn
>> 25) & 0xf) {
7399 case 0: case 1: case 2: case 3:
7400 /* 16-bit instructions. Should never happen. */
7403 if (insn
& (1 << 22)) {
7404 /* Other load/store, table branch. */
7405 if (insn
& 0x01200000) {
7406 /* Load/store doubleword. */
7409 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7411 addr
= load_reg(s
, rn
);
7413 offset
= (insn
& 0xff) * 4;
7414 if ((insn
& (1 << 23)) == 0)
7416 if (insn
& (1 << 24)) {
7417 tcg_gen_addi_i32(addr
, addr
, offset
);
7420 if (insn
& (1 << 20)) {
7422 tmp
= gen_ld32(addr
, IS_USER(s
));
7423 store_reg(s
, rs
, tmp
);
7424 tcg_gen_addi_i32(addr
, addr
, 4);
7425 tmp
= gen_ld32(addr
, IS_USER(s
));
7426 store_reg(s
, rd
, tmp
);
7429 tmp
= load_reg(s
, rs
);
7430 gen_st32(tmp
, addr
, IS_USER(s
));
7431 tcg_gen_addi_i32(addr
, addr
, 4);
7432 tmp
= load_reg(s
, rd
);
7433 gen_st32(tmp
, addr
, IS_USER(s
));
7435 if (insn
& (1 << 21)) {
7436 /* Base writeback. */
7439 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7440 store_reg(s
, rn
, addr
);
7444 } else if ((insn
& (1 << 23)) == 0) {
7445 /* Load/store exclusive word. */
7446 addr
= tcg_temp_local_new();
7447 load_reg_var(s
, addr
, rn
);
7448 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
7449 if (insn
& (1 << 20)) {
7450 gen_load_exclusive(s
, rs
, 15, addr
, 2);
7452 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
7454 tcg_temp_free(addr
);
7455 } else if ((insn
& (1 << 6)) == 0) {
7459 tcg_gen_movi_i32(addr
, s
->pc
);
7461 addr
= load_reg(s
, rn
);
7463 tmp
= load_reg(s
, rm
);
7464 tcg_gen_add_i32(addr
, addr
, tmp
);
7465 if (insn
& (1 << 4)) {
7467 tcg_gen_add_i32(addr
, addr
, tmp
);
7469 tmp
= gen_ld16u(addr
, IS_USER(s
));
7472 tmp
= gen_ld8u(addr
, IS_USER(s
));
7475 tcg_gen_shli_i32(tmp
, tmp
, 1);
7476 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7477 store_reg(s
, 15, tmp
);
7479 /* Load/store exclusive byte/halfword/doubleword. */
7481 op
= (insn
>> 4) & 0x3;
7485 addr
= tcg_temp_local_new();
7486 load_reg_var(s
, addr
, rn
);
7487 if (insn
& (1 << 20)) {
7488 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
7490 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
7492 tcg_temp_free(addr
);
7495 /* Load/store multiple, RFE, SRS. */
7496 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7497 /* Not available in user mode. */
7500 if (insn
& (1 << 20)) {
7502 addr
= load_reg(s
, rn
);
7503 if ((insn
& (1 << 24)) == 0)
7504 tcg_gen_addi_i32(addr
, addr
, -8);
7505 /* Load PC into tmp and CPSR into tmp2. */
7506 tmp
= gen_ld32(addr
, 0);
7507 tcg_gen_addi_i32(addr
, addr
, 4);
7508 tmp2
= gen_ld32(addr
, 0);
7509 if (insn
& (1 << 21)) {
7510 /* Base writeback. */
7511 if (insn
& (1 << 24)) {
7512 tcg_gen_addi_i32(addr
, addr
, 4);
7514 tcg_gen_addi_i32(addr
, addr
, -4);
7516 store_reg(s
, rn
, addr
);
7520 gen_rfe(s
, tmp
, tmp2
);
7524 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7525 addr
= load_reg(s
, 13);
7528 tmp
= tcg_const_i32(op
);
7529 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7530 tcg_temp_free_i32(tmp
);
7532 if ((insn
& (1 << 24)) == 0) {
7533 tcg_gen_addi_i32(addr
, addr
, -8);
7535 tmp
= load_reg(s
, 14);
7536 gen_st32(tmp
, addr
, 0);
7537 tcg_gen_addi_i32(addr
, addr
, 4);
7539 gen_helper_cpsr_read(tmp
);
7540 gen_st32(tmp
, addr
, 0);
7541 if (insn
& (1 << 21)) {
7542 if ((insn
& (1 << 24)) == 0) {
7543 tcg_gen_addi_i32(addr
, addr
, -4);
7545 tcg_gen_addi_i32(addr
, addr
, 4);
7547 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7548 store_reg(s
, 13, addr
);
7550 tmp
= tcg_const_i32(op
);
7551 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7552 tcg_temp_free_i32(tmp
);
7560 /* Load/store multiple. */
7561 addr
= load_reg(s
, rn
);
7563 for (i
= 0; i
< 16; i
++) {
7564 if (insn
& (1 << i
))
7567 if (insn
& (1 << 24)) {
7568 tcg_gen_addi_i32(addr
, addr
, -offset
);
7571 for (i
= 0; i
< 16; i
++) {
7572 if ((insn
& (1 << i
)) == 0)
7574 if (insn
& (1 << 20)) {
7576 tmp
= gen_ld32(addr
, IS_USER(s
));
7580 store_reg(s
, i
, tmp
);
7584 tmp
= load_reg(s
, i
);
7585 gen_st32(tmp
, addr
, IS_USER(s
));
7587 tcg_gen_addi_i32(addr
, addr
, 4);
7589 if (insn
& (1 << 21)) {
7590 /* Base register writeback. */
7591 if (insn
& (1 << 24)) {
7592 tcg_gen_addi_i32(addr
, addr
, -offset
);
7594 /* Fault if writeback register is in register list. */
7595 if (insn
& (1 << rn
))
7597 store_reg(s
, rn
, addr
);
7604 case 5: /* Data processing register constant shift. */
7607 tcg_gen_movi_i32(tmp
, 0);
7609 tmp
= load_reg(s
, rn
);
7611 tmp2
= load_reg(s
, rm
);
7612 op
= (insn
>> 21) & 0xf;
7613 shiftop
= (insn
>> 4) & 3;
7614 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7615 conds
= (insn
& (1 << 20)) != 0;
7616 logic_cc
= (conds
&& thumb2_logic_op(op
));
7617 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7618 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7622 store_reg(s
, rd
, tmp
);
7627 case 13: /* Misc data processing. */
7628 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7629 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7632 case 0: /* Register controlled shift. */
7633 tmp
= load_reg(s
, rn
);
7634 tmp2
= load_reg(s
, rm
);
7635 if ((insn
& 0x70) != 0)
7637 op
= (insn
>> 21) & 3;
7638 logic_cc
= (insn
& (1 << 20)) != 0;
7639 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7642 store_reg_bx(env
, s
, rd
, tmp
);
7644 case 1: /* Sign/zero extend. */
7645 tmp
= load_reg(s
, rm
);
7646 shift
= (insn
>> 4) & 3;
7647 /* ??? In many cases it's not neccessary to do a
7648 rotate, a shift is sufficient. */
7650 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7651 op
= (insn
>> 20) & 7;
7653 case 0: gen_sxth(tmp
); break;
7654 case 1: gen_uxth(tmp
); break;
7655 case 2: gen_sxtb16(tmp
); break;
7656 case 3: gen_uxtb16(tmp
); break;
7657 case 4: gen_sxtb(tmp
); break;
7658 case 5: gen_uxtb(tmp
); break;
7659 default: goto illegal_op
;
7662 tmp2
= load_reg(s
, rn
);
7663 if ((op
>> 1) == 1) {
7664 gen_add16(tmp
, tmp2
);
7666 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7670 store_reg(s
, rd
, tmp
);
7672 case 2: /* SIMD add/subtract. */
7673 op
= (insn
>> 20) & 7;
7674 shift
= (insn
>> 4) & 7;
7675 if ((op
& 3) == 3 || (shift
& 3) == 3)
7677 tmp
= load_reg(s
, rn
);
7678 tmp2
= load_reg(s
, rm
);
7679 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7681 store_reg(s
, rd
, tmp
);
7683 case 3: /* Other data processing. */
7684 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7686 /* Saturating add/subtract. */
7687 tmp
= load_reg(s
, rn
);
7688 tmp2
= load_reg(s
, rm
);
7690 gen_helper_double_saturate(tmp
, tmp
);
7692 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7694 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7697 tmp
= load_reg(s
, rn
);
7699 case 0x0a: /* rbit */
7700 gen_helper_rbit(tmp
, tmp
);
7702 case 0x08: /* rev */
7703 tcg_gen_bswap32_i32(tmp
, tmp
);
7705 case 0x09: /* rev16 */
7708 case 0x0b: /* revsh */
7711 case 0x10: /* sel */
7712 tmp2
= load_reg(s
, rm
);
7714 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7715 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7719 case 0x18: /* clz */
7720 gen_helper_clz(tmp
, tmp
);
7726 store_reg(s
, rd
, tmp
);
7728 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7729 op
= (insn
>> 4) & 0xf;
7730 tmp
= load_reg(s
, rn
);
7731 tmp2
= load_reg(s
, rm
);
7732 switch ((insn
>> 20) & 7) {
7733 case 0: /* 32 x 32 -> 32 */
7734 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7737 tmp2
= load_reg(s
, rs
);
7739 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7741 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7745 case 1: /* 16 x 16 -> 32 */
7746 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7749 tmp2
= load_reg(s
, rs
);
7750 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7754 case 2: /* Dual multiply add. */
7755 case 4: /* Dual multiply subtract. */
7757 gen_swap_half(tmp2
);
7758 gen_smul_dual(tmp
, tmp2
);
7759 /* This addition cannot overflow. */
7760 if (insn
& (1 << 22)) {
7761 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7763 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7768 tmp2
= load_reg(s
, rs
);
7769 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7773 case 3: /* 32 * 16 -> 32msb */
7775 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7778 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7779 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7781 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7782 tcg_temp_free_i64(tmp64
);
7785 tmp2
= load_reg(s
, rs
);
7786 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7790 case 5: case 6: /* 32 * 32 -> 32msb */
7791 gen_imull(tmp
, tmp2
);
7792 if (insn
& (1 << 5)) {
7793 gen_roundqd(tmp
, tmp2
);
7800 tmp2
= load_reg(s
, rs
);
7801 if (insn
& (1 << 21)) {
7802 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7804 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7809 case 7: /* Unsigned sum of absolute differences. */
7810 gen_helper_usad8(tmp
, tmp
, tmp2
);
7813 tmp2
= load_reg(s
, rs
);
7814 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7819 store_reg(s
, rd
, tmp
);
7821 case 6: case 7: /* 64-bit multiply, Divide. */
7822 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7823 tmp
= load_reg(s
, rn
);
7824 tmp2
= load_reg(s
, rm
);
7825 if ((op
& 0x50) == 0x10) {
7827 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7830 gen_helper_udiv(tmp
, tmp
, tmp2
);
7832 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7834 store_reg(s
, rd
, tmp
);
7835 } else if ((op
& 0xe) == 0xc) {
7836 /* Dual multiply accumulate long. */
7838 gen_swap_half(tmp2
);
7839 gen_smul_dual(tmp
, tmp2
);
7841 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7843 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7847 tmp64
= tcg_temp_new_i64();
7848 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7850 gen_addq(s
, tmp64
, rs
, rd
);
7851 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7852 tcg_temp_free_i64(tmp64
);
7855 /* Unsigned 64-bit multiply */
7856 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7860 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7862 tmp64
= tcg_temp_new_i64();
7863 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7866 /* Signed 64-bit multiply */
7867 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7872 gen_addq_lo(s
, tmp64
, rs
);
7873 gen_addq_lo(s
, tmp64
, rd
);
7874 } else if (op
& 0x40) {
7875 /* 64-bit accumulate. */
7876 gen_addq(s
, tmp64
, rs
, rd
);
7878 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7879 tcg_temp_free_i64(tmp64
);
7884 case 6: case 7: case 14: case 15:
7886 if (((insn
>> 24) & 3) == 3) {
7887 /* Translate into the equivalent ARM encoding. */
7888 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7889 if (disas_neon_data_insn(env
, s
, insn
))
7892 if (insn
& (1 << 28))
7894 if (disas_coproc_insn (env
, s
, insn
))
7898 case 8: case 9: case 10: case 11:
7899 if (insn
& (1 << 15)) {
7900 /* Branches, misc control. */
7901 if (insn
& 0x5000) {
7902 /* Unconditional branch. */
7903 /* signextend(hw1[10:0]) -> offset[:12]. */
7904 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7905 /* hw1[10:0] -> offset[11:1]. */
7906 offset
|= (insn
& 0x7ff) << 1;
7907 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7908 offset[24:22] already have the same value because of the
7909 sign extension above. */
7910 offset
^= ((~insn
) & (1 << 13)) << 10;
7911 offset
^= ((~insn
) & (1 << 11)) << 11;
7913 if (insn
& (1 << 14)) {
7914 /* Branch and link. */
7915 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7919 if (insn
& (1 << 12)) {
7924 offset
&= ~(uint32_t)2;
7925 gen_bx_im(s
, offset
);
7927 } else if (((insn
>> 23) & 7) == 7) {
7929 if (insn
& (1 << 13))
7932 if (insn
& (1 << 26)) {
7933 /* Secure monitor call (v6Z) */
7934 goto illegal_op
; /* not implemented. */
7936 op
= (insn
>> 20) & 7;
7938 case 0: /* msr cpsr. */
7940 tmp
= load_reg(s
, rn
);
7941 addr
= tcg_const_i32(insn
& 0xff);
7942 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7943 tcg_temp_free_i32(addr
);
7949 case 1: /* msr spsr. */
7952 tmp
= load_reg(s
, rn
);
7954 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7958 case 2: /* cps, nop-hint. */
7959 if (((insn
>> 8) & 7) == 0) {
7960 gen_nop_hint(s
, insn
& 0xff);
7962 /* Implemented as NOP in user mode. */
7967 if (insn
& (1 << 10)) {
7968 if (insn
& (1 << 7))
7970 if (insn
& (1 << 6))
7972 if (insn
& (1 << 5))
7974 if (insn
& (1 << 9))
7975 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7977 if (insn
& (1 << 8)) {
7979 imm
|= (insn
& 0x1f);
7982 gen_set_psr_im(s
, offset
, 0, imm
);
7985 case 3: /* Special control operations. */
7987 op
= (insn
>> 4) & 0xf;
7995 /* These execute as NOPs. */
8002 /* Trivial implementation equivalent to bx. */
8003 tmp
= load_reg(s
, rn
);
8006 case 5: /* Exception return. */
8010 if (rn
!= 14 || rd
!= 15) {
8013 tmp
= load_reg(s
, rn
);
8014 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8015 gen_exception_return(s
, tmp
);
8017 case 6: /* mrs cpsr. */
8020 addr
= tcg_const_i32(insn
& 0xff);
8021 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8022 tcg_temp_free_i32(addr
);
8024 gen_helper_cpsr_read(tmp
);
8026 store_reg(s
, rd
, tmp
);
8028 case 7: /* mrs spsr. */
8029 /* Not accessible in user mode. */
8030 if (IS_USER(s
) || IS_M(env
))
8032 tmp
= load_cpu_field(spsr
);
8033 store_reg(s
, rd
, tmp
);
8038 /* Conditional branch. */
8039 op
= (insn
>> 22) & 0xf;
8040 /* Generate a conditional jump to next instruction. */
8041 s
->condlabel
= gen_new_label();
8042 gen_test_cc(op
^ 1, s
->condlabel
);
8045 /* offset[11:1] = insn[10:0] */
8046 offset
= (insn
& 0x7ff) << 1;
8047 /* offset[17:12] = insn[21:16]. */
8048 offset
|= (insn
& 0x003f0000) >> 4;
8049 /* offset[31:20] = insn[26]. */
8050 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8051 /* offset[18] = insn[13]. */
8052 offset
|= (insn
& (1 << 13)) << 5;
8053 /* offset[19] = insn[11]. */
8054 offset
|= (insn
& (1 << 11)) << 8;
8056 /* jump to the offset */
8057 gen_jmp(s
, s
->pc
+ offset
);
8060 /* Data processing immediate. */
8061 if (insn
& (1 << 25)) {
8062 if (insn
& (1 << 24)) {
8063 if (insn
& (1 << 20))
8065 /* Bitfield/Saturate. */
8066 op
= (insn
>> 21) & 7;
8068 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8071 tcg_gen_movi_i32(tmp
, 0);
8073 tmp
= load_reg(s
, rn
);
8076 case 2: /* Signed bitfield extract. */
8078 if (shift
+ imm
> 32)
8081 gen_sbfx(tmp
, shift
, imm
);
8083 case 6: /* Unsigned bitfield extract. */
8085 if (shift
+ imm
> 32)
8088 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8090 case 3: /* Bitfield insert/clear. */
8093 imm
= imm
+ 1 - shift
;
8095 tmp2
= load_reg(s
, rd
);
8096 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
8102 default: /* Saturate. */
8105 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8107 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8109 tmp2
= tcg_const_i32(imm
);
8112 if ((op
& 1) && shift
== 0)
8113 gen_helper_usat16(tmp
, tmp
, tmp2
);
8115 gen_helper_usat(tmp
, tmp
, tmp2
);
8118 if ((op
& 1) && shift
== 0)
8119 gen_helper_ssat16(tmp
, tmp
, tmp2
);
8121 gen_helper_ssat(tmp
, tmp
, tmp2
);
8123 tcg_temp_free_i32(tmp2
);
8126 store_reg(s
, rd
, tmp
);
8128 imm
= ((insn
& 0x04000000) >> 15)
8129 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8130 if (insn
& (1 << 22)) {
8131 /* 16-bit immediate. */
8132 imm
|= (insn
>> 4) & 0xf000;
8133 if (insn
& (1 << 23)) {
8135 tmp
= load_reg(s
, rd
);
8136 tcg_gen_ext16u_i32(tmp
, tmp
);
8137 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8141 tcg_gen_movi_i32(tmp
, imm
);
8144 /* Add/sub 12-bit immediate. */
8146 offset
= s
->pc
& ~(uint32_t)3;
8147 if (insn
& (1 << 23))
8152 tcg_gen_movi_i32(tmp
, offset
);
8154 tmp
= load_reg(s
, rn
);
8155 if (insn
& (1 << 23))
8156 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8158 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8161 store_reg(s
, rd
, tmp
);
8164 int shifter_out
= 0;
8165 /* modified 12-bit immediate. */
8166 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8167 imm
= (insn
& 0xff);
8170 /* Nothing to do. */
8172 case 1: /* 00XY00XY */
8175 case 2: /* XY00XY00 */
8179 case 3: /* XYXYXYXY */
8183 default: /* Rotated constant. */
8184 shift
= (shift
<< 1) | (imm
>> 7);
8186 imm
= imm
<< (32 - shift
);
8191 tcg_gen_movi_i32(tmp2
, imm
);
8192 rn
= (insn
>> 16) & 0xf;
8195 tcg_gen_movi_i32(tmp
, 0);
8197 tmp
= load_reg(s
, rn
);
8199 op
= (insn
>> 21) & 0xf;
8200 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8201 shifter_out
, tmp
, tmp2
))
8204 rd
= (insn
>> 8) & 0xf;
8206 store_reg(s
, rd
, tmp
);
8213 case 12: /* Load/store single data item. */
8218 if ((insn
& 0x01100000) == 0x01000000) {
8219 if (disas_neon_ls_insn(env
, s
, insn
))
8227 /* s->pc has already been incremented by 4. */
8228 imm
= s
->pc
& 0xfffffffc;
8229 if (insn
& (1 << 23))
8230 imm
+= insn
& 0xfff;
8232 imm
-= insn
& 0xfff;
8233 tcg_gen_movi_i32(addr
, imm
);
8235 addr
= load_reg(s
, rn
);
8236 if (insn
& (1 << 23)) {
8237 /* Positive offset. */
8239 tcg_gen_addi_i32(addr
, addr
, imm
);
8241 op
= (insn
>> 8) & 7;
8244 case 0: case 8: /* Shifted Register. */
8245 shift
= (insn
>> 4) & 0xf;
8248 tmp
= load_reg(s
, rm
);
8250 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8251 tcg_gen_add_i32(addr
, addr
, tmp
);
8254 case 4: /* Negative offset. */
8255 tcg_gen_addi_i32(addr
, addr
, -imm
);
8257 case 6: /* User privilege. */
8258 tcg_gen_addi_i32(addr
, addr
, imm
);
8261 case 1: /* Post-decrement. */
8264 case 3: /* Post-increment. */
8268 case 5: /* Pre-decrement. */
8271 case 7: /* Pre-increment. */
8272 tcg_gen_addi_i32(addr
, addr
, imm
);
8280 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8281 if (insn
& (1 << 20)) {
8283 if (rs
== 15 && op
!= 2) {
8286 /* Memory hint. Implemented as NOP. */
8289 case 0: tmp
= gen_ld8u(addr
, user
); break;
8290 case 4: tmp
= gen_ld8s(addr
, user
); break;
8291 case 1: tmp
= gen_ld16u(addr
, user
); break;
8292 case 5: tmp
= gen_ld16s(addr
, user
); break;
8293 case 2: tmp
= gen_ld32(addr
, user
); break;
8294 default: goto illegal_op
;
8299 store_reg(s
, rs
, tmp
);
8306 tmp
= load_reg(s
, rs
);
8308 case 0: gen_st8(tmp
, addr
, user
); break;
8309 case 1: gen_st16(tmp
, addr
, user
); break;
8310 case 2: gen_st32(tmp
, addr
, user
); break;
8311 default: goto illegal_op
;
8315 tcg_gen_addi_i32(addr
, addr
, imm
);
8317 store_reg(s
, rn
, addr
);
8331 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8333 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8340 if (s
->condexec_mask
) {
8341 cond
= s
->condexec_cond
;
8342 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
8343 s
->condlabel
= gen_new_label();
8344 gen_test_cc(cond
^ 1, s
->condlabel
);
8349 insn
= lduw_code(s
->pc
);
8352 switch (insn
>> 12) {
8356 op
= (insn
>> 11) & 3;
8359 rn
= (insn
>> 3) & 7;
8360 tmp
= load_reg(s
, rn
);
8361 if (insn
& (1 << 10)) {
8364 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8367 rm
= (insn
>> 6) & 7;
8368 tmp2
= load_reg(s
, rm
);
8370 if (insn
& (1 << 9)) {
8371 if (s
->condexec_mask
)
8372 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8374 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8376 if (s
->condexec_mask
)
8377 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8379 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8382 store_reg(s
, rd
, tmp
);
8384 /* shift immediate */
8385 rm
= (insn
>> 3) & 7;
8386 shift
= (insn
>> 6) & 0x1f;
8387 tmp
= load_reg(s
, rm
);
8388 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8389 if (!s
->condexec_mask
)
8391 store_reg(s
, rd
, tmp
);
8395 /* arithmetic large immediate */
8396 op
= (insn
>> 11) & 3;
8397 rd
= (insn
>> 8) & 0x7;
8398 if (op
== 0) { /* mov */
8400 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8401 if (!s
->condexec_mask
)
8403 store_reg(s
, rd
, tmp
);
8405 tmp
= load_reg(s
, rd
);
8407 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8410 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8415 if (s
->condexec_mask
)
8416 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8418 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8420 store_reg(s
, rd
, tmp
);
8423 if (s
->condexec_mask
)
8424 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8426 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8428 store_reg(s
, rd
, tmp
);
8434 if (insn
& (1 << 11)) {
8435 rd
= (insn
>> 8) & 7;
8436 /* load pc-relative. Bit 1 of PC is ignored. */
8437 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8438 val
&= ~(uint32_t)2;
8440 tcg_gen_movi_i32(addr
, val
);
8441 tmp
= gen_ld32(addr
, IS_USER(s
));
8443 store_reg(s
, rd
, tmp
);
8446 if (insn
& (1 << 10)) {
8447 /* data processing extended or blx */
8448 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8449 rm
= (insn
>> 3) & 0xf;
8450 op
= (insn
>> 8) & 3;
8453 tmp
= load_reg(s
, rd
);
8454 tmp2
= load_reg(s
, rm
);
8455 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8457 store_reg(s
, rd
, tmp
);
8460 tmp
= load_reg(s
, rd
);
8461 tmp2
= load_reg(s
, rm
);
8462 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8466 case 2: /* mov/cpy */
8467 tmp
= load_reg(s
, rm
);
8468 store_reg(s
, rd
, tmp
);
8470 case 3:/* branch [and link] exchange thumb register */
8471 tmp
= load_reg(s
, rm
);
8472 if (insn
& (1 << 7)) {
8473 val
= (uint32_t)s
->pc
| 1;
8475 tcg_gen_movi_i32(tmp2
, val
);
8476 store_reg(s
, 14, tmp2
);
8484 /* data processing register */
8486 rm
= (insn
>> 3) & 7;
8487 op
= (insn
>> 6) & 0xf;
8488 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8489 /* the shift/rotate ops want the operands backwards */
8498 if (op
== 9) { /* neg */
8500 tcg_gen_movi_i32(tmp
, 0);
8501 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8502 tmp
= load_reg(s
, rd
);
8507 tmp2
= load_reg(s
, rm
);
8510 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8511 if (!s
->condexec_mask
)
8515 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8516 if (!s
->condexec_mask
)
8520 if (s
->condexec_mask
) {
8521 gen_helper_shl(tmp2
, tmp2
, tmp
);
8523 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8528 if (s
->condexec_mask
) {
8529 gen_helper_shr(tmp2
, tmp2
, tmp
);
8531 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8536 if (s
->condexec_mask
) {
8537 gen_helper_sar(tmp2
, tmp2
, tmp
);
8539 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8544 if (s
->condexec_mask
)
8547 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8550 if (s
->condexec_mask
)
8551 gen_sub_carry(tmp
, tmp
, tmp2
);
8553 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8556 if (s
->condexec_mask
) {
8557 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8558 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8560 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8565 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8570 if (s
->condexec_mask
)
8571 tcg_gen_neg_i32(tmp
, tmp2
);
8573 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8576 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8580 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8584 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8585 if (!s
->condexec_mask
)
8589 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8590 if (!s
->condexec_mask
)
8594 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8595 if (!s
->condexec_mask
)
8599 tcg_gen_not_i32(tmp2
, tmp2
);
8600 if (!s
->condexec_mask
)
8608 store_reg(s
, rm
, tmp2
);
8612 store_reg(s
, rd
, tmp
);
8622 /* load/store register offset. */
8624 rn
= (insn
>> 3) & 7;
8625 rm
= (insn
>> 6) & 7;
8626 op
= (insn
>> 9) & 7;
8627 addr
= load_reg(s
, rn
);
8628 tmp
= load_reg(s
, rm
);
8629 tcg_gen_add_i32(addr
, addr
, tmp
);
8632 if (op
< 3) /* store */
8633 tmp
= load_reg(s
, rd
);
8637 gen_st32(tmp
, addr
, IS_USER(s
));
8640 gen_st16(tmp
, addr
, IS_USER(s
));
8643 gen_st8(tmp
, addr
, IS_USER(s
));
8646 tmp
= gen_ld8s(addr
, IS_USER(s
));
8649 tmp
= gen_ld32(addr
, IS_USER(s
));
8652 tmp
= gen_ld16u(addr
, IS_USER(s
));
8655 tmp
= gen_ld8u(addr
, IS_USER(s
));
8658 tmp
= gen_ld16s(addr
, IS_USER(s
));
8661 if (op
>= 3) /* load */
8662 store_reg(s
, rd
, tmp
);
8667 /* load/store word immediate offset */
8669 rn
= (insn
>> 3) & 7;
8670 addr
= load_reg(s
, rn
);
8671 val
= (insn
>> 4) & 0x7c;
8672 tcg_gen_addi_i32(addr
, addr
, val
);
8674 if (insn
& (1 << 11)) {
8676 tmp
= gen_ld32(addr
, IS_USER(s
));
8677 store_reg(s
, rd
, tmp
);
8680 tmp
= load_reg(s
, rd
);
8681 gen_st32(tmp
, addr
, IS_USER(s
));
8687 /* load/store byte immediate offset */
8689 rn
= (insn
>> 3) & 7;
8690 addr
= load_reg(s
, rn
);
8691 val
= (insn
>> 6) & 0x1f;
8692 tcg_gen_addi_i32(addr
, addr
, val
);
8694 if (insn
& (1 << 11)) {
8696 tmp
= gen_ld8u(addr
, IS_USER(s
));
8697 store_reg(s
, rd
, tmp
);
8700 tmp
= load_reg(s
, rd
);
8701 gen_st8(tmp
, addr
, IS_USER(s
));
8707 /* load/store halfword immediate offset */
8709 rn
= (insn
>> 3) & 7;
8710 addr
= load_reg(s
, rn
);
8711 val
= (insn
>> 5) & 0x3e;
8712 tcg_gen_addi_i32(addr
, addr
, val
);
8714 if (insn
& (1 << 11)) {
8716 tmp
= gen_ld16u(addr
, IS_USER(s
));
8717 store_reg(s
, rd
, tmp
);
8720 tmp
= load_reg(s
, rd
);
8721 gen_st16(tmp
, addr
, IS_USER(s
));
8727 /* load/store from stack */
8728 rd
= (insn
>> 8) & 7;
8729 addr
= load_reg(s
, 13);
8730 val
= (insn
& 0xff) * 4;
8731 tcg_gen_addi_i32(addr
, addr
, val
);
8733 if (insn
& (1 << 11)) {
8735 tmp
= gen_ld32(addr
, IS_USER(s
));
8736 store_reg(s
, rd
, tmp
);
8739 tmp
= load_reg(s
, rd
);
8740 gen_st32(tmp
, addr
, IS_USER(s
));
8746 /* add to high reg */
8747 rd
= (insn
>> 8) & 7;
8748 if (insn
& (1 << 11)) {
8750 tmp
= load_reg(s
, 13);
8752 /* PC. bit 1 is ignored. */
8754 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8756 val
= (insn
& 0xff) * 4;
8757 tcg_gen_addi_i32(tmp
, tmp
, val
);
8758 store_reg(s
, rd
, tmp
);
8763 op
= (insn
>> 8) & 0xf;
8766 /* adjust stack pointer */
8767 tmp
= load_reg(s
, 13);
8768 val
= (insn
& 0x7f) * 4;
8769 if (insn
& (1 << 7))
8770 val
= -(int32_t)val
;
8771 tcg_gen_addi_i32(tmp
, tmp
, val
);
8772 store_reg(s
, 13, tmp
);
8775 case 2: /* sign/zero extend. */
8778 rm
= (insn
>> 3) & 7;
8779 tmp
= load_reg(s
, rm
);
8780 switch ((insn
>> 6) & 3) {
8781 case 0: gen_sxth(tmp
); break;
8782 case 1: gen_sxtb(tmp
); break;
8783 case 2: gen_uxth(tmp
); break;
8784 case 3: gen_uxtb(tmp
); break;
8786 store_reg(s
, rd
, tmp
);
8788 case 4: case 5: case 0xc: case 0xd:
8790 addr
= load_reg(s
, 13);
8791 if (insn
& (1 << 8))
8795 for (i
= 0; i
< 8; i
++) {
8796 if (insn
& (1 << i
))
8799 if ((insn
& (1 << 11)) == 0) {
8800 tcg_gen_addi_i32(addr
, addr
, -offset
);
8802 for (i
= 0; i
< 8; i
++) {
8803 if (insn
& (1 << i
)) {
8804 if (insn
& (1 << 11)) {
8806 tmp
= gen_ld32(addr
, IS_USER(s
));
8807 store_reg(s
, i
, tmp
);
8810 tmp
= load_reg(s
, i
);
8811 gen_st32(tmp
, addr
, IS_USER(s
));
8813 /* advance to the next address. */
8814 tcg_gen_addi_i32(addr
, addr
, 4);
8818 if (insn
& (1 << 8)) {
8819 if (insn
& (1 << 11)) {
8821 tmp
= gen_ld32(addr
, IS_USER(s
));
8822 /* don't set the pc until the rest of the instruction
8826 tmp
= load_reg(s
, 14);
8827 gen_st32(tmp
, addr
, IS_USER(s
));
8829 tcg_gen_addi_i32(addr
, addr
, 4);
8831 if ((insn
& (1 << 11)) == 0) {
8832 tcg_gen_addi_i32(addr
, addr
, -offset
);
8834 /* write back the new stack pointer */
8835 store_reg(s
, 13, addr
);
8836 /* set the new PC value */
8837 if ((insn
& 0x0900) == 0x0900)
8841 case 1: case 3: case 9: case 11: /* czb */
8843 tmp
= load_reg(s
, rm
);
8844 s
->condlabel
= gen_new_label();
8846 if (insn
& (1 << 11))
8847 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8849 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8851 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8852 val
= (uint32_t)s
->pc
+ 2;
8857 case 15: /* IT, nop-hint. */
8858 if ((insn
& 0xf) == 0) {
8859 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8863 s
->condexec_cond
= (insn
>> 4) & 0xe;
8864 s
->condexec_mask
= insn
& 0x1f;
8865 /* No actual code generated for this insn, just setup state. */
8868 case 0xe: /* bkpt */
8869 gen_set_condexec(s
);
8870 gen_set_pc_im(s
->pc
- 2);
8871 gen_exception(EXCP_BKPT
);
8872 s
->is_jmp
= DISAS_JUMP
;
8877 rn
= (insn
>> 3) & 0x7;
8879 tmp
= load_reg(s
, rn
);
8880 switch ((insn
>> 6) & 3) {
8881 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8882 case 1: gen_rev16(tmp
); break;
8883 case 3: gen_revsh(tmp
); break;
8884 default: goto illegal_op
;
8886 store_reg(s
, rd
, tmp
);
8894 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8897 addr
= tcg_const_i32(16);
8898 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8899 tcg_temp_free_i32(addr
);
8903 addr
= tcg_const_i32(17);
8904 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8905 tcg_temp_free_i32(addr
);
8907 tcg_temp_free_i32(tmp
);
8910 if (insn
& (1 << 4))
8911 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8914 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
8924 /* load/store multiple */
8925 rn
= (insn
>> 8) & 0x7;
8926 addr
= load_reg(s
, rn
);
8927 for (i
= 0; i
< 8; i
++) {
8928 if (insn
& (1 << i
)) {
8929 if (insn
& (1 << 11)) {
8931 tmp
= gen_ld32(addr
, IS_USER(s
));
8932 store_reg(s
, i
, tmp
);
8935 tmp
= load_reg(s
, i
);
8936 gen_st32(tmp
, addr
, IS_USER(s
));
8938 /* advance to the next address */
8939 tcg_gen_addi_i32(addr
, addr
, 4);
8942 /* Base register writeback. */
8943 if ((insn
& (1 << rn
)) == 0) {
8944 store_reg(s
, rn
, addr
);
8951 /* conditional branch or swi */
8952 cond
= (insn
>> 8) & 0xf;
8958 gen_set_condexec(s
);
8959 gen_set_pc_im(s
->pc
);
8960 s
->is_jmp
= DISAS_SWI
;
8963 /* generate a conditional jump to next instruction */
8964 s
->condlabel
= gen_new_label();
8965 gen_test_cc(cond
^ 1, s
->condlabel
);
8968 /* jump to the offset */
8969 val
= (uint32_t)s
->pc
+ 2;
8970 offset
= ((int32_t)insn
<< 24) >> 24;
8976 if (insn
& (1 << 11)) {
8977 if (disas_thumb2_insn(env
, s
, insn
))
8981 /* unconditional branch */
8982 val
= (uint32_t)s
->pc
;
8983 offset
= ((int32_t)insn
<< 21) >> 21;
8984 val
+= (offset
<< 1) + 2;
8989 if (disas_thumb2_insn(env
, s
, insn
))
8995 gen_set_condexec(s
);
8996 gen_set_pc_im(s
->pc
- 4);
8997 gen_exception(EXCP_UDEF
);
8998 s
->is_jmp
= DISAS_JUMP
;
9002 gen_set_condexec(s
);
9003 gen_set_pc_im(s
->pc
- 2);
9004 gen_exception(EXCP_UDEF
);
9005 s
->is_jmp
= DISAS_JUMP
;
9008 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9009 basic block 'tb'. If search_pc is TRUE, also generate PC
9010 information for each intermediate instruction. */
9011 static inline void gen_intermediate_code_internal(CPUState
*env
,
9012 TranslationBlock
*tb
,
9015 DisasContext dc1
, *dc
= &dc1
;
9017 uint16_t *gen_opc_end
;
9019 target_ulong pc_start
;
9020 uint32_t next_page_start
;
9024 /* generate intermediate code */
9031 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
9033 dc
->is_jmp
= DISAS_NEXT
;
9035 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9037 dc
->thumb
= env
->thumb
;
9038 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
9039 dc
->condexec_cond
= env
->condexec_bits
>> 4;
9040 #if !defined(CONFIG_USER_ONLY)
9042 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
9044 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
9047 cpu_F0s
= tcg_temp_new_i32();
9048 cpu_F1s
= tcg_temp_new_i32();
9049 cpu_F0d
= tcg_temp_new_i64();
9050 cpu_F1d
= tcg_temp_new_i64();
9053 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9054 cpu_M0
= tcg_temp_new_i64();
9055 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9058 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9060 max_insns
= CF_COUNT_MASK
;
9063 /* Reset the conditional execution bits immediately. This avoids
9064 complications trying to do it at the end of the block. */
9065 if (env
->condexec_bits
)
9067 TCGv tmp
= new_tmp();
9068 tcg_gen_movi_i32(tmp
, 0);
9069 store_cpu_field(tmp
, condexec_bits
);
9072 #ifdef CONFIG_USER_ONLY
9073 /* Intercept jump to the magic kernel page. */
9074 if (dc
->pc
>= 0xffff0000) {
9075 /* We always get here via a jump, so know we are not in a
9076 conditional execution block. */
9077 gen_exception(EXCP_KERNEL_TRAP
);
9078 dc
->is_jmp
= DISAS_UPDATE
;
9082 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9083 /* We always get here via a jump, so know we are not in a
9084 conditional execution block. */
9085 gen_exception(EXCP_EXCEPTION_EXIT
);
9086 dc
->is_jmp
= DISAS_UPDATE
;
9091 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9092 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9093 if (bp
->pc
== dc
->pc
) {
9094 gen_set_condexec(dc
);
9095 gen_set_pc_im(dc
->pc
);
9096 gen_exception(EXCP_DEBUG
);
9097 dc
->is_jmp
= DISAS_JUMP
;
9098 /* Advance PC so that clearing the breakpoint will
9099 invalidate this TB. */
9101 goto done_generating
;
9107 j
= gen_opc_ptr
- gen_opc_buf
;
9111 gen_opc_instr_start
[lj
++] = 0;
9113 gen_opc_pc
[lj
] = dc
->pc
;
9114 gen_opc_instr_start
[lj
] = 1;
9115 gen_opc_icount
[lj
] = num_insns
;
9118 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9122 disas_thumb_insn(env
, dc
);
9123 if (dc
->condexec_mask
) {
9124 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9125 | ((dc
->condexec_mask
>> 4) & 1);
9126 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9127 if (dc
->condexec_mask
== 0) {
9128 dc
->condexec_cond
= 0;
9132 disas_arm_insn(env
, dc
);
9135 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
9139 if (dc
->condjmp
&& !dc
->is_jmp
) {
9140 gen_set_label(dc
->condlabel
);
9143 /* Translation stops when a conditional branch is encountered.
9144 * Otherwise the subsequent code could get translated several times.
9145 * Also stop translation when a page boundary is reached. This
9146 * ensures prefetch aborts occur at the right place. */
9148 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9149 !env
->singlestep_enabled
&&
9151 dc
->pc
< next_page_start
&&
9152 num_insns
< max_insns
);
9154 if (tb
->cflags
& CF_LAST_IO
) {
9156 /* FIXME: This can theoretically happen with self-modifying
9158 cpu_abort(env
, "IO on conditional branch instruction");
9163 /* At this stage dc->condjmp will only be set when the skipped
9164 instruction was a conditional branch or trap, and the PC has
9165 already been written. */
9166 if (unlikely(env
->singlestep_enabled
)) {
9167 /* Make sure the pc is updated, and raise a debug exception. */
9169 gen_set_condexec(dc
);
9170 if (dc
->is_jmp
== DISAS_SWI
) {
9171 gen_exception(EXCP_SWI
);
9173 gen_exception(EXCP_DEBUG
);
9175 gen_set_label(dc
->condlabel
);
9177 if (dc
->condjmp
|| !dc
->is_jmp
) {
9178 gen_set_pc_im(dc
->pc
);
9181 gen_set_condexec(dc
);
9182 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9183 gen_exception(EXCP_SWI
);
9185 /* FIXME: Single stepping a WFI insn will not halt
9187 gen_exception(EXCP_DEBUG
);
9190 /* While branches must always occur at the end of an IT block,
9191 there are a few other things that can cause us to terminate
9192 the TB in the middel of an IT block:
9193 - Exception generating instructions (bkpt, swi, undefined).
9195 - Hardware watchpoints.
9196 Hardware breakpoints have already been handled and skip this code.
9198 gen_set_condexec(dc
);
9199 switch(dc
->is_jmp
) {
9201 gen_goto_tb(dc
, 1, dc
->pc
);
9206 /* indicate that the hash table must be used to find the next TB */
9210 /* nothing more to generate */
9216 gen_exception(EXCP_SWI
);
9220 gen_set_label(dc
->condlabel
);
9221 gen_set_condexec(dc
);
9222 gen_goto_tb(dc
, 1, dc
->pc
);
9228 gen_icount_end(tb
, num_insns
);
9229 *gen_opc_ptr
= INDEX_op_end
;
9232 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9233 qemu_log("----------------\n");
9234 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9235 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9240 j
= gen_opc_ptr
- gen_opc_buf
;
9243 gen_opc_instr_start
[lj
++] = 0;
9245 tb
->size
= dc
->pc
- pc_start
;
9246 tb
->icount
= num_insns
;
9250 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9252 gen_intermediate_code_internal(env
, tb
, 0);
9255 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9257 gen_intermediate_code_internal(env
, tb
, 1);
9260 static const char *cpu_mode_names
[16] = {
9261 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9262 "???", "???", "???", "und", "???", "???", "???", "sys"
9265 void cpu_dump_state(CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
9275 /* ??? This assumes float64 and double have the same layout.
9276 Oh well, it's only debug dumps. */
9285 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9287 cpu_fprintf(f
, "\n");
9289 cpu_fprintf(f
, " ");
9291 psr
= cpsr_read(env
);
9292 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9294 psr
& (1 << 31) ? 'N' : '-',
9295 psr
& (1 << 30) ? 'Z' : '-',
9296 psr
& (1 << 29) ? 'C' : '-',
9297 psr
& (1 << 28) ? 'V' : '-',
9298 psr
& CPSR_T
? 'T' : 'A',
9299 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9302 for (i
= 0; i
< 16; i
++) {
9303 d
.d
= env
->vfp
.regs
[i
];
9307 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9308 i
* 2, (int)s0
.i
, s0
.s
,
9309 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9310 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9313 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9317 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9318 unsigned long searched_pc
, int pc_pos
, void *puc
)
9320 env
->regs
[15] = gen_opc_pc
[pc_pos
];