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)
67 #if defined(CONFIG_USER_ONLY)
70 #define IS_USER(s) (s->user)
73 /* These instructions trap after executing, so defer them until after the
74 conditional executions state has been updated. */
78 static TCGv_ptr cpu_env
;
79 /* We reuse the same 64-bit temporaries for efficiency. */
80 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
81 static TCGv_i32 cpu_R
[16];
82 static TCGv_i32 cpu_exclusive_addr
;
83 static TCGv_i32 cpu_exclusive_val
;
84 static TCGv_i32 cpu_exclusive_high
;
85 #ifdef CONFIG_USER_ONLY
86 static TCGv_i32 cpu_exclusive_test
;
87 static TCGv_i32 cpu_exclusive_info
;
90 /* FIXME: These should be removed. */
91 static TCGv cpu_F0s
, cpu_F1s
;
92 static TCGv_i64 cpu_F0d
, cpu_F1d
;
94 #include "gen-icount.h"
96 static const char *regnames
[] =
97 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
98 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
100 /* initialize TCG globals. */
101 void arm_translate_init(void)
105 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
107 for (i
= 0; i
< 16; i
++) {
108 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
109 offsetof(CPUState
, regs
[i
]),
112 cpu_exclusive_addr
= tcg_global_mem_new_i32(TCG_AREG0
,
113 offsetof(CPUState
, exclusive_addr
), "exclusive_addr");
114 cpu_exclusive_val
= tcg_global_mem_new_i32(TCG_AREG0
,
115 offsetof(CPUState
, exclusive_val
), "exclusive_val");
116 cpu_exclusive_high
= tcg_global_mem_new_i32(TCG_AREG0
,
117 offsetof(CPUState
, exclusive_high
), "exclusive_high");
118 #ifdef CONFIG_USER_ONLY
119 cpu_exclusive_test
= tcg_global_mem_new_i32(TCG_AREG0
,
120 offsetof(CPUState
, exclusive_test
), "exclusive_test");
121 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
122 offsetof(CPUState
, exclusive_info
), "exclusive_info");
129 static int num_temps
;
131 /* Allocate a temporary variable. */
132 static TCGv_i32
new_tmp(void)
135 return tcg_temp_new_i32();
138 /* Release a temporary variable. */
139 static void dead_tmp(TCGv tmp
)
145 static inline TCGv
load_cpu_offset(int offset
)
147 TCGv tmp
= new_tmp();
148 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
152 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
154 static inline void store_cpu_offset(TCGv var
, int offset
)
156 tcg_gen_st_i32(var
, cpu_env
, offset
);
160 #define store_cpu_field(var, name) \
161 store_cpu_offset(var, offsetof(CPUState, name))
163 /* Set a variable to the value of a CPU register. */
164 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
168 /* normaly, since we updated PC, we need only to add one insn */
170 addr
= (long)s
->pc
+ 2;
172 addr
= (long)s
->pc
+ 4;
173 tcg_gen_movi_i32(var
, addr
);
175 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
179 /* Create a new temporary and set it to the value of a CPU register. */
180 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
182 TCGv tmp
= new_tmp();
183 load_reg_var(s
, tmp
, reg
);
187 /* Set a CPU register. The source must be a temporary and will be
189 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
192 tcg_gen_andi_i32(var
, var
, ~1);
193 s
->is_jmp
= DISAS_JUMP
;
195 tcg_gen_mov_i32(cpu_R
[reg
], var
);
199 /* Value extensions. */
200 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
201 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
202 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
203 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
205 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
209 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
211 TCGv tmp_mask
= tcg_const_i32(mask
);
212 gen_helper_cpsr_write(var
, tmp_mask
);
213 tcg_temp_free_i32(tmp_mask
);
215 /* Set NZCV flags from the high 4 bits of var. */
216 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
218 static void gen_exception(int excp
)
220 TCGv tmp
= new_tmp();
221 tcg_gen_movi_i32(tmp
, excp
);
222 gen_helper_exception(tmp
);
226 static void gen_smul_dual(TCGv a
, TCGv b
)
228 TCGv tmp1
= new_tmp();
229 TCGv tmp2
= new_tmp();
230 tcg_gen_ext16s_i32(tmp1
, a
);
231 tcg_gen_ext16s_i32(tmp2
, b
);
232 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
234 tcg_gen_sari_i32(a
, a
, 16);
235 tcg_gen_sari_i32(b
, b
, 16);
236 tcg_gen_mul_i32(b
, b
, a
);
237 tcg_gen_mov_i32(a
, tmp1
);
241 /* Byteswap each halfword. */
242 static void gen_rev16(TCGv var
)
244 TCGv tmp
= new_tmp();
245 tcg_gen_shri_i32(tmp
, var
, 8);
246 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
247 tcg_gen_shli_i32(var
, var
, 8);
248 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
249 tcg_gen_or_i32(var
, var
, tmp
);
253 /* Byteswap low halfword and sign extend. */
254 static void gen_revsh(TCGv var
)
256 tcg_gen_ext16u_i32(var
, var
);
257 tcg_gen_bswap16_i32(var
, var
);
258 tcg_gen_ext16s_i32(var
, var
);
261 /* Unsigned bitfield extract. */
262 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
265 tcg_gen_shri_i32(var
, var
, shift
);
266 tcg_gen_andi_i32(var
, var
, mask
);
269 /* Signed bitfield extract. */
270 static void gen_sbfx(TCGv var
, int shift
, int width
)
275 tcg_gen_sari_i32(var
, var
, shift
);
276 if (shift
+ width
< 32) {
277 signbit
= 1u << (width
- 1);
278 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
279 tcg_gen_xori_i32(var
, var
, signbit
);
280 tcg_gen_subi_i32(var
, var
, signbit
);
284 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
285 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
287 tcg_gen_andi_i32(val
, val
, mask
);
288 tcg_gen_shli_i32(val
, val
, shift
);
289 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
290 tcg_gen_or_i32(dest
, base
, val
);
293 /* Return (b << 32) + a. Mark inputs as dead */
294 static TCGv_i64
gen_addq_msw(TCGv_i64 a
, TCGv b
)
296 TCGv_i64 tmp64
= tcg_temp_new_i64();
298 tcg_gen_extu_i32_i64(tmp64
, b
);
300 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
301 tcg_gen_add_i64(a
, tmp64
, a
);
303 tcg_temp_free_i64(tmp64
);
307 /* Return (b << 32) - a. Mark inputs as dead. */
308 static TCGv_i64
gen_subq_msw(TCGv_i64 a
, TCGv b
)
310 TCGv_i64 tmp64
= tcg_temp_new_i64();
312 tcg_gen_extu_i32_i64(tmp64
, b
);
314 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
315 tcg_gen_sub_i64(a
, tmp64
, a
);
317 tcg_temp_free_i64(tmp64
);
321 /* FIXME: Most targets have native widening multiplication.
322 It would be good to use that instead of a full wide multiply. */
323 /* 32x32->64 multiply. Marks inputs as dead. */
324 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
326 TCGv_i64 tmp1
= tcg_temp_new_i64();
327 TCGv_i64 tmp2
= tcg_temp_new_i64();
329 tcg_gen_extu_i32_i64(tmp1
, a
);
331 tcg_gen_extu_i32_i64(tmp2
, b
);
333 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
334 tcg_temp_free_i64(tmp2
);
338 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
340 TCGv_i64 tmp1
= tcg_temp_new_i64();
341 TCGv_i64 tmp2
= tcg_temp_new_i64();
343 tcg_gen_ext_i32_i64(tmp1
, a
);
345 tcg_gen_ext_i32_i64(tmp2
, b
);
347 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
348 tcg_temp_free_i64(tmp2
);
352 /* Swap low and high halfwords. */
353 static void gen_swap_half(TCGv var
)
355 TCGv tmp
= new_tmp();
356 tcg_gen_shri_i32(tmp
, var
, 16);
357 tcg_gen_shli_i32(var
, var
, 16);
358 tcg_gen_or_i32(var
, var
, tmp
);
362 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
363 tmp = (t0 ^ t1) & 0x8000;
366 t0 = (t0 + t1) ^ tmp;
369 static void gen_add16(TCGv t0
, TCGv t1
)
371 TCGv tmp
= new_tmp();
372 tcg_gen_xor_i32(tmp
, t0
, t1
);
373 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
374 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
375 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
376 tcg_gen_add_i32(t0
, t0
, t1
);
377 tcg_gen_xor_i32(t0
, t0
, tmp
);
382 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
384 /* Set CF to the top bit of var. */
385 static void gen_set_CF_bit31(TCGv var
)
387 TCGv tmp
= new_tmp();
388 tcg_gen_shri_i32(tmp
, var
, 31);
393 /* Set N and Z flags from var. */
394 static inline void gen_logic_CC(TCGv var
)
396 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
397 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
401 static void gen_adc(TCGv t0
, TCGv t1
)
404 tcg_gen_add_i32(t0
, t0
, t1
);
405 tmp
= load_cpu_field(CF
);
406 tcg_gen_add_i32(t0
, t0
, tmp
);
410 /* dest = T0 + T1 + CF. */
411 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
414 tcg_gen_add_i32(dest
, t0
, t1
);
415 tmp
= load_cpu_field(CF
);
416 tcg_gen_add_i32(dest
, dest
, tmp
);
420 /* dest = T0 - T1 + CF - 1. */
421 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
424 tcg_gen_sub_i32(dest
, t0
, t1
);
425 tmp
= load_cpu_field(CF
);
426 tcg_gen_add_i32(dest
, dest
, tmp
);
427 tcg_gen_subi_i32(dest
, dest
, 1);
431 /* FIXME: Implement this natively. */
432 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
434 static void shifter_out_im(TCGv var
, int shift
)
436 TCGv tmp
= new_tmp();
438 tcg_gen_andi_i32(tmp
, var
, 1);
440 tcg_gen_shri_i32(tmp
, var
, shift
);
442 tcg_gen_andi_i32(tmp
, tmp
, 1);
448 /* Shift by immediate. Includes special handling for shift == 0. */
449 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
455 shifter_out_im(var
, 32 - shift
);
456 tcg_gen_shli_i32(var
, var
, shift
);
462 tcg_gen_shri_i32(var
, var
, 31);
465 tcg_gen_movi_i32(var
, 0);
468 shifter_out_im(var
, shift
- 1);
469 tcg_gen_shri_i32(var
, var
, shift
);
476 shifter_out_im(var
, shift
- 1);
479 tcg_gen_sari_i32(var
, var
, shift
);
481 case 3: /* ROR/RRX */
484 shifter_out_im(var
, shift
- 1);
485 tcg_gen_rotri_i32(var
, var
, shift
); break;
487 TCGv tmp
= load_cpu_field(CF
);
489 shifter_out_im(var
, 0);
490 tcg_gen_shri_i32(var
, var
, 1);
491 tcg_gen_shli_i32(tmp
, tmp
, 31);
492 tcg_gen_or_i32(var
, var
, tmp
);
498 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
499 TCGv shift
, int flags
)
503 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
504 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
505 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
506 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
510 case 0: gen_helper_shl(var
, var
, shift
); break;
511 case 1: gen_helper_shr(var
, var
, shift
); break;
512 case 2: gen_helper_sar(var
, var
, shift
); break;
513 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
514 tcg_gen_rotr_i32(var
, var
, shift
); break;
520 #define PAS_OP(pfx) \
522 case 0: gen_pas_helper(glue(pfx,add16)); break; \
523 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
524 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
525 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
526 case 4: gen_pas_helper(glue(pfx,add8)); break; \
527 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
529 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
534 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
536 tmp
= tcg_temp_new_ptr();
537 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
539 tcg_temp_free_ptr(tmp
);
542 tmp
= tcg_temp_new_ptr();
543 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
545 tcg_temp_free_ptr(tmp
);
547 #undef gen_pas_helper
548 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
561 #undef gen_pas_helper
566 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
567 #define PAS_OP(pfx) \
569 case 0: gen_pas_helper(glue(pfx,add8)); break; \
570 case 1: gen_pas_helper(glue(pfx,add16)); break; \
571 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
572 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
573 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
574 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
576 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
581 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
583 tmp
= tcg_temp_new_ptr();
584 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
586 tcg_temp_free_ptr(tmp
);
589 tmp
= tcg_temp_new_ptr();
590 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
592 tcg_temp_free_ptr(tmp
);
594 #undef gen_pas_helper
595 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
608 #undef gen_pas_helper
613 static void gen_test_cc(int cc
, int label
)
621 tmp
= load_cpu_field(ZF
);
622 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
625 tmp
= load_cpu_field(ZF
);
626 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
629 tmp
= load_cpu_field(CF
);
630 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
633 tmp
= load_cpu_field(CF
);
634 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
637 tmp
= load_cpu_field(NF
);
638 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
641 tmp
= load_cpu_field(NF
);
642 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
645 tmp
= load_cpu_field(VF
);
646 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
649 tmp
= load_cpu_field(VF
);
650 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
652 case 8: /* hi: C && !Z */
653 inv
= gen_new_label();
654 tmp
= load_cpu_field(CF
);
655 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
657 tmp
= load_cpu_field(ZF
);
658 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
661 case 9: /* ls: !C || Z */
662 tmp
= load_cpu_field(CF
);
663 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
665 tmp
= load_cpu_field(ZF
);
666 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
668 case 10: /* ge: N == V -> N ^ V == 0 */
669 tmp
= load_cpu_field(VF
);
670 tmp2
= load_cpu_field(NF
);
671 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
673 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
675 case 11: /* lt: N != V -> N ^ V != 0 */
676 tmp
= load_cpu_field(VF
);
677 tmp2
= load_cpu_field(NF
);
678 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
680 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
682 case 12: /* gt: !Z && N == V */
683 inv
= gen_new_label();
684 tmp
= load_cpu_field(ZF
);
685 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
687 tmp
= load_cpu_field(VF
);
688 tmp2
= load_cpu_field(NF
);
689 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
691 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
694 case 13: /* le: Z || N != V */
695 tmp
= load_cpu_field(ZF
);
696 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
698 tmp
= load_cpu_field(VF
);
699 tmp2
= load_cpu_field(NF
);
700 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
702 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
705 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
711 static const uint8_t table_logic_cc
[16] = {
730 /* Set PC and Thumb state from an immediate address. */
731 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
735 s
->is_jmp
= DISAS_UPDATE
;
736 if (s
->thumb
!= (addr
& 1)) {
738 tcg_gen_movi_i32(tmp
, addr
& 1);
739 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
742 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
745 /* Set PC and Thumb state from var. var is marked as dead. */
746 static inline void gen_bx(DisasContext
*s
, TCGv var
)
748 s
->is_jmp
= DISAS_UPDATE
;
749 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
750 tcg_gen_andi_i32(var
, var
, 1);
751 store_cpu_field(var
, thumb
);
754 /* Variant of store_reg which uses branch&exchange logic when storing
755 to r15 in ARM architecture v7 and above. The source must be a temporary
756 and will be marked as dead. */
757 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
760 if (reg
== 15 && ENABLE_ARCH_7
) {
763 store_reg(s
, reg
, var
);
767 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
769 TCGv tmp
= new_tmp();
770 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
773 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
775 TCGv tmp
= new_tmp();
776 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
779 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
781 TCGv tmp
= new_tmp();
782 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
785 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
787 TCGv tmp
= new_tmp();
788 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
791 static inline TCGv
gen_ld32(TCGv addr
, int index
)
793 TCGv tmp
= new_tmp();
794 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
797 static inline TCGv_i64
gen_ld64(TCGv addr
, int index
)
799 TCGv_i64 tmp
= tcg_temp_new_i64();
800 tcg_gen_qemu_ld64(tmp
, addr
, index
);
803 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
805 tcg_gen_qemu_st8(val
, addr
, index
);
808 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
810 tcg_gen_qemu_st16(val
, addr
, index
);
813 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
815 tcg_gen_qemu_st32(val
, addr
, index
);
818 static inline void gen_st64(TCGv_i64 val
, TCGv addr
, int index
)
820 tcg_gen_qemu_st64(val
, addr
, index
);
821 tcg_temp_free_i64(val
);
824 static inline void gen_set_pc_im(uint32_t val
)
826 tcg_gen_movi_i32(cpu_R
[15], val
);
829 /* Force a TB lookup after an instruction that changes the CPU state. */
830 static inline void gen_lookup_tb(DisasContext
*s
)
832 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
833 s
->is_jmp
= DISAS_UPDATE
;
836 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
839 int val
, rm
, shift
, shiftop
;
842 if (!(insn
& (1 << 25))) {
845 if (!(insn
& (1 << 23)))
848 tcg_gen_addi_i32(var
, var
, val
);
852 shift
= (insn
>> 7) & 0x1f;
853 shiftop
= (insn
>> 5) & 3;
854 offset
= load_reg(s
, rm
);
855 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
856 if (!(insn
& (1 << 23)))
857 tcg_gen_sub_i32(var
, var
, offset
);
859 tcg_gen_add_i32(var
, var
, offset
);
864 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
870 if (insn
& (1 << 22)) {
872 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
873 if (!(insn
& (1 << 23)))
877 tcg_gen_addi_i32(var
, var
, val
);
881 tcg_gen_addi_i32(var
, var
, extra
);
883 offset
= load_reg(s
, rm
);
884 if (!(insn
& (1 << 23)))
885 tcg_gen_sub_i32(var
, var
, offset
);
887 tcg_gen_add_i32(var
, var
, offset
);
892 #define VFP_OP2(name) \
893 static inline void gen_vfp_##name(int dp) \
896 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
898 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
908 static inline void gen_vfp_abs(int dp
)
911 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
913 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
916 static inline void gen_vfp_neg(int dp
)
919 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
921 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
924 static inline void gen_vfp_sqrt(int dp
)
927 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
929 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
932 static inline void gen_vfp_cmp(int dp
)
935 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
937 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
940 static inline void gen_vfp_cmpe(int dp
)
943 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
945 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
948 static inline void gen_vfp_F1_ld0(int dp
)
951 tcg_gen_movi_i64(cpu_F1d
, 0);
953 tcg_gen_movi_i32(cpu_F1s
, 0);
956 static inline void gen_vfp_uito(int dp
)
959 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
961 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
964 static inline void gen_vfp_sito(int dp
)
967 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
969 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
972 static inline void gen_vfp_toui(int dp
)
975 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
977 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
980 static inline void gen_vfp_touiz(int dp
)
983 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
985 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
988 static inline void gen_vfp_tosi(int dp
)
991 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
993 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
996 static inline void gen_vfp_tosiz(int dp
)
999 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1001 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1004 #define VFP_GEN_FIX(name) \
1005 static inline void gen_vfp_##name(int dp, int shift) \
1007 TCGv tmp_shift = tcg_const_i32(shift); \
1009 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1011 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1012 tcg_temp_free_i32(tmp_shift); \
1024 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1027 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1029 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1032 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1035 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1037 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1041 vfp_reg_offset (int dp
, int reg
)
1044 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1046 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1047 + offsetof(CPU_DoubleU
, l
.upper
);
1049 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1050 + offsetof(CPU_DoubleU
, l
.lower
);
1054 /* Return the offset of a 32-bit piece of a NEON register.
1055 zero is the least significant end of the register. */
1057 neon_reg_offset (int reg
, int n
)
1061 return vfp_reg_offset(0, sreg
);
1064 static TCGv
neon_load_reg(int reg
, int pass
)
1066 TCGv tmp
= new_tmp();
1067 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1071 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1073 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1077 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1079 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1082 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1084 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1087 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1088 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1089 #define tcg_gen_st_f32 tcg_gen_st_i32
1090 #define tcg_gen_st_f64 tcg_gen_st_i64
1092 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1095 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1097 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1100 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1103 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1105 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1108 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1111 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1113 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1116 #define ARM_CP_RW_BIT (1 << 20)
1118 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1120 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1123 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1125 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1128 static inline TCGv
iwmmxt_load_creg(int reg
)
1130 TCGv var
= new_tmp();
1131 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1135 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1137 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1141 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1143 iwmmxt_store_reg(cpu_M0
, rn
);
1146 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1148 iwmmxt_load_reg(cpu_M0
, rn
);
1151 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1153 iwmmxt_load_reg(cpu_V1
, rn
);
1154 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1157 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1159 iwmmxt_load_reg(cpu_V1
, rn
);
1160 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1163 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1165 iwmmxt_load_reg(cpu_V1
, rn
);
1166 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1169 #define IWMMXT_OP(name) \
1170 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1172 iwmmxt_load_reg(cpu_V1, rn); \
1173 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1176 #define IWMMXT_OP_ENV(name) \
1177 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1179 iwmmxt_load_reg(cpu_V1, rn); \
1180 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1183 #define IWMMXT_OP_ENV_SIZE(name) \
1184 IWMMXT_OP_ENV(name##b) \
1185 IWMMXT_OP_ENV(name##w) \
1186 IWMMXT_OP_ENV(name##l)
1188 #define IWMMXT_OP_ENV1(name) \
1189 static inline void gen_op_iwmmxt_##name##_M0(void) \
1191 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1205 IWMMXT_OP_ENV_SIZE(unpackl
)
1206 IWMMXT_OP_ENV_SIZE(unpackh
)
1208 IWMMXT_OP_ENV1(unpacklub
)
1209 IWMMXT_OP_ENV1(unpackluw
)
1210 IWMMXT_OP_ENV1(unpacklul
)
1211 IWMMXT_OP_ENV1(unpackhub
)
1212 IWMMXT_OP_ENV1(unpackhuw
)
1213 IWMMXT_OP_ENV1(unpackhul
)
1214 IWMMXT_OP_ENV1(unpacklsb
)
1215 IWMMXT_OP_ENV1(unpacklsw
)
1216 IWMMXT_OP_ENV1(unpacklsl
)
1217 IWMMXT_OP_ENV1(unpackhsb
)
1218 IWMMXT_OP_ENV1(unpackhsw
)
1219 IWMMXT_OP_ENV1(unpackhsl
)
1221 IWMMXT_OP_ENV_SIZE(cmpeq
)
1222 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1223 IWMMXT_OP_ENV_SIZE(cmpgts
)
1225 IWMMXT_OP_ENV_SIZE(mins
)
1226 IWMMXT_OP_ENV_SIZE(minu
)
1227 IWMMXT_OP_ENV_SIZE(maxs
)
1228 IWMMXT_OP_ENV_SIZE(maxu
)
1230 IWMMXT_OP_ENV_SIZE(subn
)
1231 IWMMXT_OP_ENV_SIZE(addn
)
1232 IWMMXT_OP_ENV_SIZE(subu
)
1233 IWMMXT_OP_ENV_SIZE(addu
)
1234 IWMMXT_OP_ENV_SIZE(subs
)
1235 IWMMXT_OP_ENV_SIZE(adds
)
1237 IWMMXT_OP_ENV(avgb0
)
1238 IWMMXT_OP_ENV(avgb1
)
1239 IWMMXT_OP_ENV(avgw0
)
1240 IWMMXT_OP_ENV(avgw1
)
1244 IWMMXT_OP_ENV(packuw
)
1245 IWMMXT_OP_ENV(packul
)
1246 IWMMXT_OP_ENV(packuq
)
1247 IWMMXT_OP_ENV(packsw
)
1248 IWMMXT_OP_ENV(packsl
)
1249 IWMMXT_OP_ENV(packsq
)
1251 static void gen_op_iwmmxt_set_mup(void)
1254 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1255 tcg_gen_ori_i32(tmp
, tmp
, 2);
1256 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1259 static void gen_op_iwmmxt_set_cup(void)
1262 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1263 tcg_gen_ori_i32(tmp
, tmp
, 1);
1264 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1267 static void gen_op_iwmmxt_setpsr_nz(void)
1269 TCGv tmp
= new_tmp();
1270 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1271 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1274 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1276 iwmmxt_load_reg(cpu_V1
, rn
);
1277 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1278 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1281 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1287 rd
= (insn
>> 16) & 0xf;
1288 tmp
= load_reg(s
, rd
);
1290 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1291 if (insn
& (1 << 24)) {
1293 if (insn
& (1 << 23))
1294 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1296 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1297 tcg_gen_mov_i32(dest
, tmp
);
1298 if (insn
& (1 << 21))
1299 store_reg(s
, rd
, tmp
);
1302 } else if (insn
& (1 << 21)) {
1304 tcg_gen_mov_i32(dest
, tmp
);
1305 if (insn
& (1 << 23))
1306 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1308 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1309 store_reg(s
, rd
, tmp
);
1310 } else if (!(insn
& (1 << 23)))
1315 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1317 int rd
= (insn
>> 0) & 0xf;
1320 if (insn
& (1 << 8)) {
1321 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1324 tmp
= iwmmxt_load_creg(rd
);
1328 iwmmxt_load_reg(cpu_V0
, rd
);
1329 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1331 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1332 tcg_gen_mov_i32(dest
, tmp
);
1337 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1338 (ie. an undefined instruction). */
1339 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1342 int rdhi
, rdlo
, rd0
, rd1
, i
;
1344 TCGv tmp
, tmp2
, tmp3
;
1346 if ((insn
& 0x0e000e00) == 0x0c000000) {
1347 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1349 rdlo
= (insn
>> 12) & 0xf;
1350 rdhi
= (insn
>> 16) & 0xf;
1351 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1352 iwmmxt_load_reg(cpu_V0
, wrd
);
1353 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1354 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1355 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1356 } else { /* TMCRR */
1357 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1358 iwmmxt_store_reg(cpu_V0
, wrd
);
1359 gen_op_iwmmxt_set_mup();
1364 wrd
= (insn
>> 12) & 0xf;
1366 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1370 if (insn
& ARM_CP_RW_BIT
) {
1371 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1373 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1374 iwmmxt_store_creg(wrd
, tmp
);
1377 if (insn
& (1 << 8)) {
1378 if (insn
& (1 << 22)) { /* WLDRD */
1379 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1381 } else { /* WLDRW wRd */
1382 tmp
= gen_ld32(addr
, IS_USER(s
));
1385 if (insn
& (1 << 22)) { /* WLDRH */
1386 tmp
= gen_ld16u(addr
, IS_USER(s
));
1387 } else { /* WLDRB */
1388 tmp
= gen_ld8u(addr
, IS_USER(s
));
1392 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1395 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1398 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1399 tmp
= iwmmxt_load_creg(wrd
);
1400 gen_st32(tmp
, addr
, IS_USER(s
));
1402 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1404 if (insn
& (1 << 8)) {
1405 if (insn
& (1 << 22)) { /* WSTRD */
1407 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1408 } else { /* WSTRW wRd */
1409 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1410 gen_st32(tmp
, addr
, IS_USER(s
));
1413 if (insn
& (1 << 22)) { /* WSTRH */
1414 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1415 gen_st16(tmp
, addr
, IS_USER(s
));
1416 } else { /* WSTRB */
1417 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1418 gen_st8(tmp
, addr
, IS_USER(s
));
1427 if ((insn
& 0x0f000000) != 0x0e000000)
1430 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1431 case 0x000: /* WOR */
1432 wrd
= (insn
>> 12) & 0xf;
1433 rd0
= (insn
>> 0) & 0xf;
1434 rd1
= (insn
>> 16) & 0xf;
1435 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1436 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1437 gen_op_iwmmxt_setpsr_nz();
1438 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1439 gen_op_iwmmxt_set_mup();
1440 gen_op_iwmmxt_set_cup();
1442 case 0x011: /* TMCR */
1445 rd
= (insn
>> 12) & 0xf;
1446 wrd
= (insn
>> 16) & 0xf;
1448 case ARM_IWMMXT_wCID
:
1449 case ARM_IWMMXT_wCASF
:
1451 case ARM_IWMMXT_wCon
:
1452 gen_op_iwmmxt_set_cup();
1454 case ARM_IWMMXT_wCSSF
:
1455 tmp
= iwmmxt_load_creg(wrd
);
1456 tmp2
= load_reg(s
, rd
);
1457 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1459 iwmmxt_store_creg(wrd
, tmp
);
1461 case ARM_IWMMXT_wCGR0
:
1462 case ARM_IWMMXT_wCGR1
:
1463 case ARM_IWMMXT_wCGR2
:
1464 case ARM_IWMMXT_wCGR3
:
1465 gen_op_iwmmxt_set_cup();
1466 tmp
= load_reg(s
, rd
);
1467 iwmmxt_store_creg(wrd
, tmp
);
1473 case 0x100: /* WXOR */
1474 wrd
= (insn
>> 12) & 0xf;
1475 rd0
= (insn
>> 0) & 0xf;
1476 rd1
= (insn
>> 16) & 0xf;
1477 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1478 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1479 gen_op_iwmmxt_setpsr_nz();
1480 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1481 gen_op_iwmmxt_set_mup();
1482 gen_op_iwmmxt_set_cup();
1484 case 0x111: /* TMRC */
1487 rd
= (insn
>> 12) & 0xf;
1488 wrd
= (insn
>> 16) & 0xf;
1489 tmp
= iwmmxt_load_creg(wrd
);
1490 store_reg(s
, rd
, tmp
);
1492 case 0x300: /* WANDN */
1493 wrd
= (insn
>> 12) & 0xf;
1494 rd0
= (insn
>> 0) & 0xf;
1495 rd1
= (insn
>> 16) & 0xf;
1496 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1497 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1498 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1499 gen_op_iwmmxt_setpsr_nz();
1500 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1501 gen_op_iwmmxt_set_mup();
1502 gen_op_iwmmxt_set_cup();
1504 case 0x200: /* WAND */
1505 wrd
= (insn
>> 12) & 0xf;
1506 rd0
= (insn
>> 0) & 0xf;
1507 rd1
= (insn
>> 16) & 0xf;
1508 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1509 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1510 gen_op_iwmmxt_setpsr_nz();
1511 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1512 gen_op_iwmmxt_set_mup();
1513 gen_op_iwmmxt_set_cup();
1515 case 0x810: case 0xa10: /* WMADD */
1516 wrd
= (insn
>> 12) & 0xf;
1517 rd0
= (insn
>> 0) & 0xf;
1518 rd1
= (insn
>> 16) & 0xf;
1519 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1520 if (insn
& (1 << 21))
1521 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1523 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1524 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1525 gen_op_iwmmxt_set_mup();
1527 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1528 wrd
= (insn
>> 12) & 0xf;
1529 rd0
= (insn
>> 16) & 0xf;
1530 rd1
= (insn
>> 0) & 0xf;
1531 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1532 switch ((insn
>> 22) & 3) {
1534 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1537 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1540 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1545 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1546 gen_op_iwmmxt_set_mup();
1547 gen_op_iwmmxt_set_cup();
1549 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1550 wrd
= (insn
>> 12) & 0xf;
1551 rd0
= (insn
>> 16) & 0xf;
1552 rd1
= (insn
>> 0) & 0xf;
1553 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1554 switch ((insn
>> 22) & 3) {
1556 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1559 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1562 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1567 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1568 gen_op_iwmmxt_set_mup();
1569 gen_op_iwmmxt_set_cup();
1571 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1572 wrd
= (insn
>> 12) & 0xf;
1573 rd0
= (insn
>> 16) & 0xf;
1574 rd1
= (insn
>> 0) & 0xf;
1575 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1576 if (insn
& (1 << 22))
1577 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1579 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1580 if (!(insn
& (1 << 20)))
1581 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1582 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1583 gen_op_iwmmxt_set_mup();
1585 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1586 wrd
= (insn
>> 12) & 0xf;
1587 rd0
= (insn
>> 16) & 0xf;
1588 rd1
= (insn
>> 0) & 0xf;
1589 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1590 if (insn
& (1 << 21)) {
1591 if (insn
& (1 << 20))
1592 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1594 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1596 if (insn
& (1 << 20))
1597 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1599 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1601 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1602 gen_op_iwmmxt_set_mup();
1604 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1605 wrd
= (insn
>> 12) & 0xf;
1606 rd0
= (insn
>> 16) & 0xf;
1607 rd1
= (insn
>> 0) & 0xf;
1608 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1609 if (insn
& (1 << 21))
1610 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1612 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1613 if (!(insn
& (1 << 20))) {
1614 iwmmxt_load_reg(cpu_V1
, wrd
);
1615 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1617 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1618 gen_op_iwmmxt_set_mup();
1620 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1621 wrd
= (insn
>> 12) & 0xf;
1622 rd0
= (insn
>> 16) & 0xf;
1623 rd1
= (insn
>> 0) & 0xf;
1624 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1625 switch ((insn
>> 22) & 3) {
1627 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1630 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1633 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1638 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1639 gen_op_iwmmxt_set_mup();
1640 gen_op_iwmmxt_set_cup();
1642 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1643 wrd
= (insn
>> 12) & 0xf;
1644 rd0
= (insn
>> 16) & 0xf;
1645 rd1
= (insn
>> 0) & 0xf;
1646 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1647 if (insn
& (1 << 22)) {
1648 if (insn
& (1 << 20))
1649 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1651 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1653 if (insn
& (1 << 20))
1654 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1656 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1658 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1659 gen_op_iwmmxt_set_mup();
1660 gen_op_iwmmxt_set_cup();
1662 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1663 wrd
= (insn
>> 12) & 0xf;
1664 rd0
= (insn
>> 16) & 0xf;
1665 rd1
= (insn
>> 0) & 0xf;
1666 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1667 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1668 tcg_gen_andi_i32(tmp
, tmp
, 7);
1669 iwmmxt_load_reg(cpu_V1
, rd1
);
1670 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1672 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1673 gen_op_iwmmxt_set_mup();
1675 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1676 if (((insn
>> 6) & 3) == 3)
1678 rd
= (insn
>> 12) & 0xf;
1679 wrd
= (insn
>> 16) & 0xf;
1680 tmp
= load_reg(s
, rd
);
1681 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1682 switch ((insn
>> 6) & 3) {
1684 tmp2
= tcg_const_i32(0xff);
1685 tmp3
= tcg_const_i32((insn
& 7) << 3);
1688 tmp2
= tcg_const_i32(0xffff);
1689 tmp3
= tcg_const_i32((insn
& 3) << 4);
1692 tmp2
= tcg_const_i32(0xffffffff);
1693 tmp3
= tcg_const_i32((insn
& 1) << 5);
1699 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1700 tcg_temp_free(tmp3
);
1701 tcg_temp_free(tmp2
);
1703 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1704 gen_op_iwmmxt_set_mup();
1706 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1707 rd
= (insn
>> 12) & 0xf;
1708 wrd
= (insn
>> 16) & 0xf;
1709 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1711 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1713 switch ((insn
>> 22) & 3) {
1715 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1716 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1718 tcg_gen_ext8s_i32(tmp
, tmp
);
1720 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1724 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1725 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1727 tcg_gen_ext16s_i32(tmp
, tmp
);
1729 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1733 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1734 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1737 store_reg(s
, rd
, tmp
);
1739 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1740 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1742 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1743 switch ((insn
>> 22) & 3) {
1745 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1748 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1751 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1754 tcg_gen_shli_i32(tmp
, tmp
, 28);
1758 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1759 if (((insn
>> 6) & 3) == 3)
1761 rd
= (insn
>> 12) & 0xf;
1762 wrd
= (insn
>> 16) & 0xf;
1763 tmp
= load_reg(s
, rd
);
1764 switch ((insn
>> 6) & 3) {
1766 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1769 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1772 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1776 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1777 gen_op_iwmmxt_set_mup();
1779 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1780 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1782 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1784 tcg_gen_mov_i32(tmp2
, tmp
);
1785 switch ((insn
>> 22) & 3) {
1787 for (i
= 0; i
< 7; i
++) {
1788 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1789 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1793 for (i
= 0; i
< 3; i
++) {
1794 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1795 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1799 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1800 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1807 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1808 wrd
= (insn
>> 12) & 0xf;
1809 rd0
= (insn
>> 16) & 0xf;
1810 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1811 switch ((insn
>> 22) & 3) {
1813 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1816 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1819 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1824 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1825 gen_op_iwmmxt_set_mup();
1827 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1828 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1830 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1832 tcg_gen_mov_i32(tmp2
, tmp
);
1833 switch ((insn
>> 22) & 3) {
1835 for (i
= 0; i
< 7; i
++) {
1836 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1837 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1841 for (i
= 0; i
< 3; i
++) {
1842 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1843 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1847 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1848 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1855 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1856 rd
= (insn
>> 12) & 0xf;
1857 rd0
= (insn
>> 16) & 0xf;
1858 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1860 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1862 switch ((insn
>> 22) & 3) {
1864 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1867 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1870 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1873 store_reg(s
, rd
, tmp
);
1875 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1876 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1877 wrd
= (insn
>> 12) & 0xf;
1878 rd0
= (insn
>> 16) & 0xf;
1879 rd1
= (insn
>> 0) & 0xf;
1880 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1881 switch ((insn
>> 22) & 3) {
1883 if (insn
& (1 << 21))
1884 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1886 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1889 if (insn
& (1 << 21))
1890 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1892 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1895 if (insn
& (1 << 21))
1896 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1898 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1903 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1904 gen_op_iwmmxt_set_mup();
1905 gen_op_iwmmxt_set_cup();
1907 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1908 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1909 wrd
= (insn
>> 12) & 0xf;
1910 rd0
= (insn
>> 16) & 0xf;
1911 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1912 switch ((insn
>> 22) & 3) {
1914 if (insn
& (1 << 21))
1915 gen_op_iwmmxt_unpacklsb_M0();
1917 gen_op_iwmmxt_unpacklub_M0();
1920 if (insn
& (1 << 21))
1921 gen_op_iwmmxt_unpacklsw_M0();
1923 gen_op_iwmmxt_unpackluw_M0();
1926 if (insn
& (1 << 21))
1927 gen_op_iwmmxt_unpacklsl_M0();
1929 gen_op_iwmmxt_unpacklul_M0();
1934 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1935 gen_op_iwmmxt_set_mup();
1936 gen_op_iwmmxt_set_cup();
1938 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1939 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1940 wrd
= (insn
>> 12) & 0xf;
1941 rd0
= (insn
>> 16) & 0xf;
1942 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1943 switch ((insn
>> 22) & 3) {
1945 if (insn
& (1 << 21))
1946 gen_op_iwmmxt_unpackhsb_M0();
1948 gen_op_iwmmxt_unpackhub_M0();
1951 if (insn
& (1 << 21))
1952 gen_op_iwmmxt_unpackhsw_M0();
1954 gen_op_iwmmxt_unpackhuw_M0();
1957 if (insn
& (1 << 21))
1958 gen_op_iwmmxt_unpackhsl_M0();
1960 gen_op_iwmmxt_unpackhul_M0();
1965 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1966 gen_op_iwmmxt_set_mup();
1967 gen_op_iwmmxt_set_cup();
1969 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1970 case 0x214: case 0x614: case 0xa14: case 0xe14:
1971 if (((insn
>> 22) & 3) == 0)
1973 wrd
= (insn
>> 12) & 0xf;
1974 rd0
= (insn
>> 16) & 0xf;
1975 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1977 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1981 switch ((insn
>> 22) & 3) {
1983 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1986 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1989 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1993 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1994 gen_op_iwmmxt_set_mup();
1995 gen_op_iwmmxt_set_cup();
1997 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1998 case 0x014: case 0x414: case 0x814: case 0xc14:
1999 if (((insn
>> 22) & 3) == 0)
2001 wrd
= (insn
>> 12) & 0xf;
2002 rd0
= (insn
>> 16) & 0xf;
2003 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2005 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2009 switch ((insn
>> 22) & 3) {
2011 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2014 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2017 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2021 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2022 gen_op_iwmmxt_set_mup();
2023 gen_op_iwmmxt_set_cup();
2025 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2026 case 0x114: case 0x514: case 0x914: case 0xd14:
2027 if (((insn
>> 22) & 3) == 0)
2029 wrd
= (insn
>> 12) & 0xf;
2030 rd0
= (insn
>> 16) & 0xf;
2031 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2033 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2037 switch ((insn
>> 22) & 3) {
2039 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2042 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2045 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2049 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2050 gen_op_iwmmxt_set_mup();
2051 gen_op_iwmmxt_set_cup();
2053 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2054 case 0x314: case 0x714: case 0xb14: case 0xf14:
2055 if (((insn
>> 22) & 3) == 0)
2057 wrd
= (insn
>> 12) & 0xf;
2058 rd0
= (insn
>> 16) & 0xf;
2059 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2061 switch ((insn
>> 22) & 3) {
2063 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2067 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2070 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2074 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2077 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2081 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2085 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2086 gen_op_iwmmxt_set_mup();
2087 gen_op_iwmmxt_set_cup();
2089 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2090 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2091 wrd
= (insn
>> 12) & 0xf;
2092 rd0
= (insn
>> 16) & 0xf;
2093 rd1
= (insn
>> 0) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2095 switch ((insn
>> 22) & 3) {
2097 if (insn
& (1 << 21))
2098 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2100 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2103 if (insn
& (1 << 21))
2104 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2106 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2109 if (insn
& (1 << 21))
2110 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2112 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2117 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2118 gen_op_iwmmxt_set_mup();
2120 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2121 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2122 wrd
= (insn
>> 12) & 0xf;
2123 rd0
= (insn
>> 16) & 0xf;
2124 rd1
= (insn
>> 0) & 0xf;
2125 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2126 switch ((insn
>> 22) & 3) {
2128 if (insn
& (1 << 21))
2129 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2131 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2134 if (insn
& (1 << 21))
2135 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2137 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2140 if (insn
& (1 << 21))
2141 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2143 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2148 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2149 gen_op_iwmmxt_set_mup();
2151 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2152 case 0x402: case 0x502: case 0x602: case 0x702:
2153 wrd
= (insn
>> 12) & 0xf;
2154 rd0
= (insn
>> 16) & 0xf;
2155 rd1
= (insn
>> 0) & 0xf;
2156 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2157 tmp
= tcg_const_i32((insn
>> 20) & 3);
2158 iwmmxt_load_reg(cpu_V1
, rd1
);
2159 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2161 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2162 gen_op_iwmmxt_set_mup();
2164 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2165 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2166 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2167 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2168 wrd
= (insn
>> 12) & 0xf;
2169 rd0
= (insn
>> 16) & 0xf;
2170 rd1
= (insn
>> 0) & 0xf;
2171 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2172 switch ((insn
>> 20) & 0xf) {
2174 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2177 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2180 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2183 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2186 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2189 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2192 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2195 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2198 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2203 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2204 gen_op_iwmmxt_set_mup();
2205 gen_op_iwmmxt_set_cup();
2207 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2208 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2209 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2210 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2211 wrd
= (insn
>> 12) & 0xf;
2212 rd0
= (insn
>> 16) & 0xf;
2213 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2214 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2215 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2217 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2218 gen_op_iwmmxt_set_mup();
2219 gen_op_iwmmxt_set_cup();
2221 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2222 case 0x418: case 0x518: case 0x618: case 0x718:
2223 case 0x818: case 0x918: case 0xa18: case 0xb18:
2224 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2225 wrd
= (insn
>> 12) & 0xf;
2226 rd0
= (insn
>> 16) & 0xf;
2227 rd1
= (insn
>> 0) & 0xf;
2228 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2229 switch ((insn
>> 20) & 0xf) {
2231 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2234 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2237 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2240 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2243 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2246 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2249 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2252 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2255 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2260 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2261 gen_op_iwmmxt_set_mup();
2262 gen_op_iwmmxt_set_cup();
2264 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2265 case 0x408: case 0x508: case 0x608: case 0x708:
2266 case 0x808: case 0x908: case 0xa08: case 0xb08:
2267 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2268 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2270 wrd
= (insn
>> 12) & 0xf;
2271 rd0
= (insn
>> 16) & 0xf;
2272 rd1
= (insn
>> 0) & 0xf;
2273 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2274 switch ((insn
>> 22) & 3) {
2276 if (insn
& (1 << 21))
2277 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2279 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2282 if (insn
& (1 << 21))
2283 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2285 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2288 if (insn
& (1 << 21))
2289 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2291 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2294 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2295 gen_op_iwmmxt_set_mup();
2296 gen_op_iwmmxt_set_cup();
2298 case 0x201: case 0x203: case 0x205: case 0x207:
2299 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2300 case 0x211: case 0x213: case 0x215: case 0x217:
2301 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2302 wrd
= (insn
>> 5) & 0xf;
2303 rd0
= (insn
>> 12) & 0xf;
2304 rd1
= (insn
>> 0) & 0xf;
2305 if (rd0
== 0xf || rd1
== 0xf)
2307 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2308 tmp
= load_reg(s
, rd0
);
2309 tmp2
= load_reg(s
, rd1
);
2310 switch ((insn
>> 16) & 0xf) {
2311 case 0x0: /* TMIA */
2312 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2314 case 0x8: /* TMIAPH */
2315 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2317 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2318 if (insn
& (1 << 16))
2319 tcg_gen_shri_i32(tmp
, tmp
, 16);
2320 if (insn
& (1 << 17))
2321 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2322 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2331 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2332 gen_op_iwmmxt_set_mup();
2341 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2342 (ie. an undefined instruction). */
2343 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2345 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2348 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2349 /* Multiply with Internal Accumulate Format */
2350 rd0
= (insn
>> 12) & 0xf;
2352 acc
= (insn
>> 5) & 7;
2357 tmp
= load_reg(s
, rd0
);
2358 tmp2
= load_reg(s
, rd1
);
2359 switch ((insn
>> 16) & 0xf) {
2361 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2363 case 0x8: /* MIAPH */
2364 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2366 case 0xc: /* MIABB */
2367 case 0xd: /* MIABT */
2368 case 0xe: /* MIATB */
2369 case 0xf: /* MIATT */
2370 if (insn
& (1 << 16))
2371 tcg_gen_shri_i32(tmp
, tmp
, 16);
2372 if (insn
& (1 << 17))
2373 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2374 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2382 gen_op_iwmmxt_movq_wRn_M0(acc
);
2386 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2387 /* Internal Accumulator Access Format */
2388 rdhi
= (insn
>> 16) & 0xf;
2389 rdlo
= (insn
>> 12) & 0xf;
2395 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2396 iwmmxt_load_reg(cpu_V0
, acc
);
2397 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2398 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2399 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2400 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2402 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2403 iwmmxt_store_reg(cpu_V0
, acc
);
2411 /* Disassemble system coprocessor instruction. Return nonzero if
2412 instruction is not defined. */
2413 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2416 uint32_t rd
= (insn
>> 12) & 0xf;
2417 uint32_t cp
= (insn
>> 8) & 0xf;
2422 if (insn
& ARM_CP_RW_BIT
) {
2423 if (!env
->cp
[cp
].cp_read
)
2425 gen_set_pc_im(s
->pc
);
2427 tmp2
= tcg_const_i32(insn
);
2428 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2429 tcg_temp_free(tmp2
);
2430 store_reg(s
, rd
, tmp
);
2432 if (!env
->cp
[cp
].cp_write
)
2434 gen_set_pc_im(s
->pc
);
2435 tmp
= load_reg(s
, rd
);
2436 tmp2
= tcg_const_i32(insn
);
2437 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2438 tcg_temp_free(tmp2
);
2444 static int cp15_user_ok(uint32_t insn
)
2446 int cpn
= (insn
>> 16) & 0xf;
2447 int cpm
= insn
& 0xf;
2448 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2450 if (cpn
== 13 && cpm
== 0) {
2452 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2456 /* ISB, DSB, DMB. */
2457 if ((cpm
== 5 && op
== 4)
2458 || (cpm
== 10 && (op
== 4 || op
== 5)))
2464 static int cp15_tls_load_store(CPUState
*env
, DisasContext
*s
, uint32_t insn
, uint32_t rd
)
2467 int cpn
= (insn
>> 16) & 0xf;
2468 int cpm
= insn
& 0xf;
2469 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2471 if (!arm_feature(env
, ARM_FEATURE_V6K
))
2474 if (!(cpn
== 13 && cpm
== 0))
2477 if (insn
& ARM_CP_RW_BIT
) {
2480 tmp
= load_cpu_field(cp15
.c13_tls1
);
2483 tmp
= load_cpu_field(cp15
.c13_tls2
);
2486 tmp
= load_cpu_field(cp15
.c13_tls3
);
2491 store_reg(s
, rd
, tmp
);
2494 tmp
= load_reg(s
, rd
);
2497 store_cpu_field(tmp
, cp15
.c13_tls1
);
2500 store_cpu_field(tmp
, cp15
.c13_tls2
);
2503 store_cpu_field(tmp
, cp15
.c13_tls3
);
2513 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2514 instruction is not defined. */
2515 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2520 /* M profile cores use memory mapped registers instead of cp15. */
2521 if (arm_feature(env
, ARM_FEATURE_M
))
2524 if ((insn
& (1 << 25)) == 0) {
2525 if (insn
& (1 << 20)) {
2529 /* mcrr. Used for block cache operations, so implement as no-op. */
2532 if ((insn
& (1 << 4)) == 0) {
2536 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2539 if ((insn
& 0x0fff0fff) == 0x0e070f90
2540 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2541 /* Wait for interrupt. */
2542 gen_set_pc_im(s
->pc
);
2543 s
->is_jmp
= DISAS_WFI
;
2546 rd
= (insn
>> 12) & 0xf;
2548 if (cp15_tls_load_store(env
, s
, insn
, rd
))
2551 tmp2
= tcg_const_i32(insn
);
2552 if (insn
& ARM_CP_RW_BIT
) {
2554 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2555 /* If the destination register is r15 then sets condition codes. */
2557 store_reg(s
, rd
, tmp
);
2561 tmp
= load_reg(s
, rd
);
2562 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2564 /* Normally we would always end the TB here, but Linux
2565 * arch/arm/mach-pxa/sleep.S expects two instructions following
2566 * an MMU enable to execute from cache. Imitate this behaviour. */
2567 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2568 (insn
& 0x0fff0fff) != 0x0e010f10)
2571 tcg_temp_free_i32(tmp2
);
2575 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2576 #define VFP_SREG(insn, bigbit, smallbit) \
2577 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2578 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2579 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2580 reg = (((insn) >> (bigbit)) & 0x0f) \
2581 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2583 if (insn & (1 << (smallbit))) \
2585 reg = ((insn) >> (bigbit)) & 0x0f; \
2588 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2589 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2590 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2591 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2592 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2593 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2595 /* Move between integer and VFP cores. */
2596 static TCGv
gen_vfp_mrs(void)
2598 TCGv tmp
= new_tmp();
2599 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2603 static void gen_vfp_msr(TCGv tmp
)
2605 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2609 static void gen_neon_dup_u8(TCGv var
, int shift
)
2611 TCGv tmp
= new_tmp();
2613 tcg_gen_shri_i32(var
, var
, shift
);
2614 tcg_gen_ext8u_i32(var
, var
);
2615 tcg_gen_shli_i32(tmp
, var
, 8);
2616 tcg_gen_or_i32(var
, var
, tmp
);
2617 tcg_gen_shli_i32(tmp
, var
, 16);
2618 tcg_gen_or_i32(var
, var
, tmp
);
2622 static void gen_neon_dup_low16(TCGv var
)
2624 TCGv tmp
= new_tmp();
2625 tcg_gen_ext16u_i32(var
, var
);
2626 tcg_gen_shli_i32(tmp
, var
, 16);
2627 tcg_gen_or_i32(var
, var
, tmp
);
2631 static void gen_neon_dup_high16(TCGv var
)
2633 TCGv tmp
= new_tmp();
2634 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2635 tcg_gen_shri_i32(tmp
, var
, 16);
2636 tcg_gen_or_i32(var
, var
, tmp
);
2640 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2641 (ie. an undefined instruction). */
2642 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2644 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2650 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2653 if (!s
->vfp_enabled
) {
2654 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2655 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2657 rn
= (insn
>> 16) & 0xf;
2658 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2659 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2662 dp
= ((insn
& 0xf00) == 0xb00);
2663 switch ((insn
>> 24) & 0xf) {
2665 if (insn
& (1 << 4)) {
2666 /* single register transfer */
2667 rd
= (insn
>> 12) & 0xf;
2672 VFP_DREG_N(rn
, insn
);
2675 if (insn
& 0x00c00060
2676 && !arm_feature(env
, ARM_FEATURE_NEON
))
2679 pass
= (insn
>> 21) & 1;
2680 if (insn
& (1 << 22)) {
2682 offset
= ((insn
>> 5) & 3) * 8;
2683 } else if (insn
& (1 << 5)) {
2685 offset
= (insn
& (1 << 6)) ? 16 : 0;
2690 if (insn
& ARM_CP_RW_BIT
) {
2692 tmp
= neon_load_reg(rn
, pass
);
2696 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2697 if (insn
& (1 << 23))
2703 if (insn
& (1 << 23)) {
2705 tcg_gen_shri_i32(tmp
, tmp
, 16);
2711 tcg_gen_sari_i32(tmp
, tmp
, 16);
2720 store_reg(s
, rd
, tmp
);
2723 tmp
= load_reg(s
, rd
);
2724 if (insn
& (1 << 23)) {
2727 gen_neon_dup_u8(tmp
, 0);
2728 } else if (size
== 1) {
2729 gen_neon_dup_low16(tmp
);
2731 for (n
= 0; n
<= pass
* 2; n
++) {
2733 tcg_gen_mov_i32(tmp2
, tmp
);
2734 neon_store_reg(rn
, n
, tmp2
);
2736 neon_store_reg(rn
, n
, tmp
);
2741 tmp2
= neon_load_reg(rn
, pass
);
2742 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2746 tmp2
= neon_load_reg(rn
, pass
);
2747 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2753 neon_store_reg(rn
, pass
, tmp
);
2757 if ((insn
& 0x6f) != 0x00)
2759 rn
= VFP_SREG_N(insn
);
2760 if (insn
& ARM_CP_RW_BIT
) {
2762 if (insn
& (1 << 21)) {
2763 /* system register */
2768 /* VFP2 allows access to FSID from userspace.
2769 VFP3 restricts all id registers to privileged
2772 && arm_feature(env
, ARM_FEATURE_VFP3
))
2774 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2779 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2781 case ARM_VFP_FPINST
:
2782 case ARM_VFP_FPINST2
:
2783 /* Not present in VFP3. */
2785 || arm_feature(env
, ARM_FEATURE_VFP3
))
2787 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2791 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2792 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2795 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2801 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2803 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2809 gen_mov_F0_vreg(0, rn
);
2810 tmp
= gen_vfp_mrs();
2813 /* Set the 4 flag bits in the CPSR. */
2817 store_reg(s
, rd
, tmp
);
2821 tmp
= load_reg(s
, rd
);
2822 if (insn
& (1 << 21)) {
2824 /* system register */
2829 /* Writes are ignored. */
2832 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2839 /* TODO: VFP subarchitecture support.
2840 * For now, keep the EN bit only */
2841 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2842 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2845 case ARM_VFP_FPINST
:
2846 case ARM_VFP_FPINST2
:
2847 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2854 gen_mov_vreg_F0(0, rn
);
2859 /* data processing */
2860 /* The opcode is in bits 23, 21, 20 and 6. */
2861 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2865 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2867 /* rn is register number */
2868 VFP_DREG_N(rn
, insn
);
2871 if (op
== 15 && (rn
== 15 || ((rn
& 0x1c) == 0x18))) {
2872 /* Integer or single precision destination. */
2873 rd
= VFP_SREG_D(insn
);
2875 VFP_DREG_D(rd
, insn
);
2878 (((rn
& 0x1c) == 0x10) || ((rn
& 0x14) == 0x14))) {
2879 /* VCVT from int is always from S reg regardless of dp bit.
2880 * VCVT with immediate frac_bits has same format as SREG_M
2882 rm
= VFP_SREG_M(insn
);
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 /* NB that we implicitly rely on the encoding for the frac_bits
2895 * in VCVT of fixed to float being the same as that of an SREG_M
2897 rm
= VFP_SREG_M(insn
);
2900 veclen
= s
->vec_len
;
2901 if (op
== 15 && rn
> 3)
2904 /* Shut up compiler warnings. */
2915 /* Figure out what type of vector operation this is. */
2916 if ((rd
& bank_mask
) == 0) {
2921 delta_d
= (s
->vec_stride
>> 1) + 1;
2923 delta_d
= s
->vec_stride
+ 1;
2925 if ((rm
& bank_mask
) == 0) {
2926 /* mixed scalar/vector */
2935 /* Load the initial operands. */
2940 /* Integer source */
2941 gen_mov_F0_vreg(0, rm
);
2946 gen_mov_F0_vreg(dp
, rd
);
2947 gen_mov_F1_vreg(dp
, rm
);
2951 /* Compare with zero */
2952 gen_mov_F0_vreg(dp
, rd
);
2963 /* Source and destination the same. */
2964 gen_mov_F0_vreg(dp
, rd
);
2967 /* One source operand. */
2968 gen_mov_F0_vreg(dp
, rm
);
2972 /* Two source operands. */
2973 gen_mov_F0_vreg(dp
, rn
);
2974 gen_mov_F1_vreg(dp
, rm
);
2978 /* Perform the calculation. */
2980 case 0: /* mac: fd + (fn * fm) */
2982 gen_mov_F1_vreg(dp
, rd
);
2985 case 1: /* nmac: fd - (fn * fm) */
2988 gen_mov_F1_vreg(dp
, rd
);
2991 case 2: /* msc: -fd + (fn * fm) */
2993 gen_mov_F1_vreg(dp
, rd
);
2996 case 3: /* nmsc: -fd - (fn * fm) */
2999 gen_mov_F1_vreg(dp
, rd
);
3002 case 4: /* mul: fn * fm */
3005 case 5: /* nmul: -(fn * fm) */
3009 case 6: /* add: fn + fm */
3012 case 7: /* sub: fn - fm */
3015 case 8: /* div: fn / fm */
3018 case 14: /* fconst */
3019 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3022 n
= (insn
<< 12) & 0x80000000;
3023 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3030 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3037 tcg_gen_movi_i32(cpu_F0s
, n
);
3040 case 15: /* extension space */
3054 case 4: /* vcvtb.f32.f16 */
3055 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3057 tmp
= gen_vfp_mrs();
3058 tcg_gen_ext16u_i32(tmp
, tmp
);
3059 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3062 case 5: /* vcvtt.f32.f16 */
3063 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3065 tmp
= gen_vfp_mrs();
3066 tcg_gen_shri_i32(tmp
, tmp
, 16);
3067 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3070 case 6: /* vcvtb.f16.f32 */
3071 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3074 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3075 gen_mov_F0_vreg(0, rd
);
3076 tmp2
= gen_vfp_mrs();
3077 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3078 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3082 case 7: /* vcvtt.f16.f32 */
3083 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
3086 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3087 tcg_gen_shli_i32(tmp
, tmp
, 16);
3088 gen_mov_F0_vreg(0, rd
);
3089 tmp2
= gen_vfp_mrs();
3090 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3091 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3104 case 11: /* cmpez */
3108 case 15: /* single<->double conversion */
3110 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3112 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3114 case 16: /* fuito */
3117 case 17: /* fsito */
3120 case 20: /* fshto */
3121 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3123 gen_vfp_shto(dp
, 16 - rm
);
3125 case 21: /* fslto */
3126 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3128 gen_vfp_slto(dp
, 32 - rm
);
3130 case 22: /* fuhto */
3131 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3133 gen_vfp_uhto(dp
, 16 - rm
);
3135 case 23: /* fulto */
3136 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3138 gen_vfp_ulto(dp
, 32 - rm
);
3140 case 24: /* ftoui */
3143 case 25: /* ftouiz */
3146 case 26: /* ftosi */
3149 case 27: /* ftosiz */
3152 case 28: /* ftosh */
3153 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3155 gen_vfp_tosh(dp
, 16 - rm
);
3157 case 29: /* ftosl */
3158 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3160 gen_vfp_tosl(dp
, 32 - rm
);
3162 case 30: /* ftouh */
3163 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3165 gen_vfp_touh(dp
, 16 - rm
);
3167 case 31: /* ftoul */
3168 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3170 gen_vfp_toul(dp
, 32 - rm
);
3172 default: /* undefined */
3173 printf ("rn:%d\n", rn
);
3177 default: /* undefined */
3178 printf ("op:%d\n", op
);
3182 /* Write back the result. */
3183 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3184 ; /* Comparison, do nothing. */
3185 else if (op
== 15 && dp
&& ((rn
& 0x1c) == 0x18))
3186 /* VCVT double to int: always integer result. */
3187 gen_mov_vreg_F0(0, rd
);
3188 else if (op
== 15 && rn
== 15)
3190 gen_mov_vreg_F0(!dp
, rd
);
3192 gen_mov_vreg_F0(dp
, rd
);
3194 /* break out of the loop if we have finished */
3198 if (op
== 15 && delta_m
== 0) {
3199 /* single source one-many */
3201 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3203 gen_mov_vreg_F0(dp
, rd
);
3207 /* Setup the next operands. */
3209 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3213 /* One source operand. */
3214 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3216 gen_mov_F0_vreg(dp
, rm
);
3218 /* Two source operands. */
3219 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3221 gen_mov_F0_vreg(dp
, rn
);
3223 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3225 gen_mov_F1_vreg(dp
, rm
);
3233 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3234 /* two-register transfer */
3235 rn
= (insn
>> 16) & 0xf;
3236 rd
= (insn
>> 12) & 0xf;
3238 VFP_DREG_M(rm
, insn
);
3240 rm
= VFP_SREG_M(insn
);
3243 if (insn
& ARM_CP_RW_BIT
) {
3246 gen_mov_F0_vreg(0, rm
* 2);
3247 tmp
= gen_vfp_mrs();
3248 store_reg(s
, rd
, tmp
);
3249 gen_mov_F0_vreg(0, rm
* 2 + 1);
3250 tmp
= gen_vfp_mrs();
3251 store_reg(s
, rn
, tmp
);
3253 gen_mov_F0_vreg(0, rm
);
3254 tmp
= gen_vfp_mrs();
3255 store_reg(s
, rn
, tmp
);
3256 gen_mov_F0_vreg(0, rm
+ 1);
3257 tmp
= gen_vfp_mrs();
3258 store_reg(s
, rd
, tmp
);
3263 tmp
= load_reg(s
, rd
);
3265 gen_mov_vreg_F0(0, rm
* 2);
3266 tmp
= load_reg(s
, rn
);
3268 gen_mov_vreg_F0(0, rm
* 2 + 1);
3270 tmp
= load_reg(s
, rn
);
3272 gen_mov_vreg_F0(0, rm
);
3273 tmp
= load_reg(s
, rd
);
3275 gen_mov_vreg_F0(0, rm
+ 1);
3280 rn
= (insn
>> 16) & 0xf;
3282 VFP_DREG_D(rd
, insn
);
3284 rd
= VFP_SREG_D(insn
);
3285 if (s
->thumb
&& rn
== 15) {
3287 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3289 addr
= load_reg(s
, rn
);
3291 if ((insn
& 0x01200000) == 0x01000000) {
3292 /* Single load/store */
3293 offset
= (insn
& 0xff) << 2;
3294 if ((insn
& (1 << 23)) == 0)
3296 tcg_gen_addi_i32(addr
, addr
, offset
);
3297 if (insn
& (1 << 20)) {
3298 gen_vfp_ld(s
, dp
, addr
);
3299 gen_mov_vreg_F0(dp
, rd
);
3301 gen_mov_F0_vreg(dp
, rd
);
3302 gen_vfp_st(s
, dp
, addr
);
3306 /* load/store multiple */
3308 n
= (insn
>> 1) & 0x7f;
3312 if (insn
& (1 << 24)) /* pre-decrement */
3313 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3319 for (i
= 0; i
< n
; i
++) {
3320 if (insn
& ARM_CP_RW_BIT
) {
3322 gen_vfp_ld(s
, dp
, addr
);
3323 gen_mov_vreg_F0(dp
, rd
+ i
);
3326 gen_mov_F0_vreg(dp
, rd
+ i
);
3327 gen_vfp_st(s
, dp
, addr
);
3329 tcg_gen_addi_i32(addr
, addr
, offset
);
3331 if (insn
& (1 << 21)) {
3333 if (insn
& (1 << 24))
3334 offset
= -offset
* n
;
3335 else if (dp
&& (insn
& 1))
3341 tcg_gen_addi_i32(addr
, addr
, offset
);
3342 store_reg(s
, rn
, addr
);
3350 /* Should never happen. */
3356 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3358 TranslationBlock
*tb
;
3361 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3363 gen_set_pc_im(dest
);
3364 tcg_gen_exit_tb((long)tb
+ n
);
3366 gen_set_pc_im(dest
);
3371 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3373 if (unlikely(s
->singlestep_enabled
)) {
3374 /* An indirect jump so that we still trigger the debug exception. */
3379 gen_goto_tb(s
, 0, dest
);
3380 s
->is_jmp
= DISAS_TB_JUMP
;
3384 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3387 tcg_gen_sari_i32(t0
, t0
, 16);
3391 tcg_gen_sari_i32(t1
, t1
, 16);
3394 tcg_gen_mul_i32(t0
, t0
, t1
);
3397 /* Return the mask of PSR bits set by a MSR instruction. */
3398 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3402 if (flags
& (1 << 0))
3404 if (flags
& (1 << 1))
3406 if (flags
& (1 << 2))
3408 if (flags
& (1 << 3))
3411 /* Mask out undefined bits. */
3412 mask
&= ~CPSR_RESERVED
;
3413 if (!arm_feature(env
, ARM_FEATURE_V6
))
3414 mask
&= ~(CPSR_E
| CPSR_GE
);
3415 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3417 /* Mask out execution state bits. */
3420 /* Mask out privileged bits. */
3426 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3427 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3431 /* ??? This is also undefined in system mode. */
3435 tmp
= load_cpu_field(spsr
);
3436 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3437 tcg_gen_andi_i32(t0
, t0
, mask
);
3438 tcg_gen_or_i32(tmp
, tmp
, t0
);
3439 store_cpu_field(tmp
, spsr
);
3441 gen_set_cpsr(t0
, mask
);
3448 /* Returns nonzero if access to the PSR is not permitted. */
3449 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3453 tcg_gen_movi_i32(tmp
, val
);
3454 return gen_set_psr(s
, mask
, spsr
, tmp
);
3457 /* Generate an old-style exception return. Marks pc as dead. */
3458 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3461 store_reg(s
, 15, pc
);
3462 tmp
= load_cpu_field(spsr
);
3463 gen_set_cpsr(tmp
, 0xffffffff);
3465 s
->is_jmp
= DISAS_UPDATE
;
3468 /* Generate a v6 exception return. Marks both values as dead. */
3469 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3471 gen_set_cpsr(cpsr
, 0xffffffff);
3473 store_reg(s
, 15, pc
);
3474 s
->is_jmp
= DISAS_UPDATE
;
3478 gen_set_condexec (DisasContext
*s
)
3480 if (s
->condexec_mask
) {
3481 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3482 TCGv tmp
= new_tmp();
3483 tcg_gen_movi_i32(tmp
, val
);
3484 store_cpu_field(tmp
, condexec_bits
);
3488 static void gen_nop_hint(DisasContext
*s
, int val
)
3492 gen_set_pc_im(s
->pc
);
3493 s
->is_jmp
= DISAS_WFI
;
3497 /* TODO: Implement SEV and WFE. May help SMP performance. */
3503 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3505 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3508 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3509 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3510 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3516 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3519 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3520 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3521 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3526 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3527 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3528 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3529 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3530 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3532 /* FIXME: This is wrong. They set the wrong overflow bit. */
3533 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3534 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3535 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3536 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3538 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3539 switch ((size << 1) | u) { \
3541 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3544 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3547 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3550 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3553 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3556 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3558 default: return 1; \
3561 #define GEN_NEON_INTEGER_OP(name) do { \
3562 switch ((size << 1) | u) { \
3564 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3567 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3570 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3573 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3576 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3579 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3581 default: return 1; \
3584 static TCGv
neon_load_scratch(int scratch
)
3586 TCGv tmp
= new_tmp();
3587 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3591 static void neon_store_scratch(int scratch
, TCGv var
)
3593 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3597 static inline TCGv
neon_get_scalar(int size
, int reg
)
3601 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3603 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3605 gen_neon_dup_low16(tmp
);
3607 gen_neon_dup_high16(tmp
);
3613 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3621 tcg_gen_andi_i32(rd
, t0
, 0xff);
3622 tcg_gen_shri_i32(tmp
, t0
, 8);
3623 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3624 tcg_gen_or_i32(rd
, rd
, tmp
);
3625 tcg_gen_shli_i32(tmp
, t1
, 16);
3626 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3627 tcg_gen_or_i32(rd
, rd
, tmp
);
3628 tcg_gen_shli_i32(tmp
, t1
, 8);
3629 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3630 tcg_gen_or_i32(rd
, rd
, tmp
);
3632 tcg_gen_shri_i32(rm
, t0
, 8);
3633 tcg_gen_andi_i32(rm
, rm
, 0xff);
3634 tcg_gen_shri_i32(tmp
, t0
, 16);
3635 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3636 tcg_gen_or_i32(rm
, rm
, tmp
);
3637 tcg_gen_shli_i32(tmp
, t1
, 8);
3638 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3639 tcg_gen_or_i32(rm
, rm
, tmp
);
3640 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3641 tcg_gen_or_i32(t1
, rm
, tmp
);
3642 tcg_gen_mov_i32(t0
, rd
);
3649 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3657 tcg_gen_andi_i32(rd
, t0
, 0xff);
3658 tcg_gen_shli_i32(tmp
, t1
, 8);
3659 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3660 tcg_gen_or_i32(rd
, rd
, tmp
);
3661 tcg_gen_shli_i32(tmp
, t0
, 16);
3662 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3663 tcg_gen_or_i32(rd
, rd
, tmp
);
3664 tcg_gen_shli_i32(tmp
, t1
, 24);
3665 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3666 tcg_gen_or_i32(rd
, rd
, tmp
);
3668 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3669 tcg_gen_shri_i32(tmp
, t0
, 8);
3670 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3671 tcg_gen_or_i32(rm
, rm
, tmp
);
3672 tcg_gen_shri_i32(tmp
, t1
, 8);
3673 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3674 tcg_gen_or_i32(rm
, rm
, tmp
);
3675 tcg_gen_shri_i32(tmp
, t0
, 16);
3676 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3677 tcg_gen_or_i32(t1
, rm
, tmp
);
3678 tcg_gen_mov_i32(t0
, rd
);
3685 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3692 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3693 tcg_gen_shli_i32(tmp2
, t1
, 16);
3694 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3695 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3696 tcg_gen_shri_i32(tmp2
, t0
, 16);
3697 tcg_gen_or_i32(t1
, t1
, tmp2
);
3698 tcg_gen_mov_i32(t0
, tmp
);
3704 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3709 for (n
= 0; n
< q
+ 1; n
+= 2) {
3710 t0
= neon_load_reg(reg
, n
);
3711 t1
= neon_load_reg(reg
, n
+ 1);
3713 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3714 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3715 case 2: /* no-op */; break;
3718 neon_store_scratch(tmp
+ n
, t0
);
3719 neon_store_scratch(tmp
+ n
+ 1, t1
);
3723 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3730 tcg_gen_shli_i32(rd
, t0
, 8);
3731 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3732 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3733 tcg_gen_or_i32(rd
, rd
, tmp
);
3735 tcg_gen_shri_i32(t1
, t1
, 8);
3736 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3737 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3738 tcg_gen_or_i32(t1
, t1
, tmp
);
3739 tcg_gen_mov_i32(t0
, rd
);
3745 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3752 tcg_gen_shli_i32(rd
, t0
, 16);
3753 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3754 tcg_gen_or_i32(rd
, rd
, tmp
);
3755 tcg_gen_shri_i32(t1
, t1
, 16);
3756 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3757 tcg_gen_or_i32(t1
, t1
, tmp
);
3758 tcg_gen_mov_i32(t0
, rd
);
3769 } neon_ls_element_type
[11] = {
3783 /* Translate a NEON load/store element instruction. Return nonzero if the
3784 instruction is invalid. */
3785 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3804 if (!s
->vfp_enabled
)
3806 VFP_DREG_D(rd
, insn
);
3807 rn
= (insn
>> 16) & 0xf;
3809 load
= (insn
& (1 << 21)) != 0;
3811 if ((insn
& (1 << 23)) == 0) {
3812 /* Load store all elements. */
3813 op
= (insn
>> 8) & 0xf;
3814 size
= (insn
>> 6) & 3;
3817 nregs
= neon_ls_element_type
[op
].nregs
;
3818 interleave
= neon_ls_element_type
[op
].interleave
;
3819 spacing
= neon_ls_element_type
[op
].spacing
;
3820 if (size
== 3 && (interleave
| spacing
) != 1)
3822 load_reg_var(s
, addr
, rn
);
3823 stride
= (1 << size
) * interleave
;
3824 for (reg
= 0; reg
< nregs
; reg
++) {
3825 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3826 load_reg_var(s
, addr
, rn
);
3827 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3828 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3829 load_reg_var(s
, addr
, rn
);
3830 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3834 tmp64
= gen_ld64(addr
, IS_USER(s
));
3835 neon_store_reg64(tmp64
, rd
);
3836 tcg_temp_free_i64(tmp64
);
3838 tmp64
= tcg_temp_new_i64();
3839 neon_load_reg64(tmp64
, rd
);
3840 gen_st64(tmp64
, addr
, IS_USER(s
));
3842 tcg_gen_addi_i32(addr
, addr
, stride
);
3844 for (pass
= 0; pass
< 2; pass
++) {
3847 tmp
= gen_ld32(addr
, IS_USER(s
));
3848 neon_store_reg(rd
, pass
, tmp
);
3850 tmp
= neon_load_reg(rd
, pass
);
3851 gen_st32(tmp
, addr
, IS_USER(s
));
3853 tcg_gen_addi_i32(addr
, addr
, stride
);
3854 } else if (size
== 1) {
3856 tmp
= gen_ld16u(addr
, IS_USER(s
));
3857 tcg_gen_addi_i32(addr
, addr
, stride
);
3858 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3859 tcg_gen_addi_i32(addr
, addr
, stride
);
3860 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3861 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3863 neon_store_reg(rd
, pass
, tmp
);
3865 tmp
= neon_load_reg(rd
, pass
);
3867 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3868 gen_st16(tmp
, addr
, IS_USER(s
));
3869 tcg_gen_addi_i32(addr
, addr
, stride
);
3870 gen_st16(tmp2
, addr
, IS_USER(s
));
3871 tcg_gen_addi_i32(addr
, addr
, stride
);
3873 } else /* size == 0 */ {
3876 for (n
= 0; n
< 4; n
++) {
3877 tmp
= gen_ld8u(addr
, IS_USER(s
));
3878 tcg_gen_addi_i32(addr
, addr
, stride
);
3882 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3883 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3887 neon_store_reg(rd
, pass
, tmp2
);
3889 tmp2
= neon_load_reg(rd
, pass
);
3890 for (n
= 0; n
< 4; n
++) {
3893 tcg_gen_mov_i32(tmp
, tmp2
);
3895 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3897 gen_st8(tmp
, addr
, IS_USER(s
));
3898 tcg_gen_addi_i32(addr
, addr
, stride
);
3909 size
= (insn
>> 10) & 3;
3911 /* Load single element to all lanes. */
3914 size
= (insn
>> 6) & 3;
3915 nregs
= ((insn
>> 8) & 3) + 1;
3916 stride
= (insn
& (1 << 5)) ? 2 : 1;
3917 load_reg_var(s
, addr
, rn
);
3918 for (reg
= 0; reg
< nregs
; reg
++) {
3921 tmp
= gen_ld8u(addr
, IS_USER(s
));
3922 gen_neon_dup_u8(tmp
, 0);
3925 tmp
= gen_ld16u(addr
, IS_USER(s
));
3926 gen_neon_dup_low16(tmp
);
3929 tmp
= gen_ld32(addr
, IS_USER(s
));
3933 default: /* Avoid compiler warnings. */
3936 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3938 tcg_gen_mov_i32(tmp2
, tmp
);
3939 neon_store_reg(rd
, 0, tmp2
);
3940 neon_store_reg(rd
, 1, tmp
);
3943 stride
= (1 << size
) * nregs
;
3945 /* Single element. */
3946 pass
= (insn
>> 7) & 1;
3949 shift
= ((insn
>> 5) & 3) * 8;
3953 shift
= ((insn
>> 6) & 1) * 16;
3954 stride
= (insn
& (1 << 5)) ? 2 : 1;
3958 stride
= (insn
& (1 << 6)) ? 2 : 1;
3963 nregs
= ((insn
>> 8) & 3) + 1;
3964 load_reg_var(s
, addr
, rn
);
3965 for (reg
= 0; reg
< nregs
; reg
++) {
3969 tmp
= gen_ld8u(addr
, IS_USER(s
));
3972 tmp
= gen_ld16u(addr
, IS_USER(s
));
3975 tmp
= gen_ld32(addr
, IS_USER(s
));
3977 default: /* Avoid compiler warnings. */
3981 tmp2
= neon_load_reg(rd
, pass
);
3982 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3985 neon_store_reg(rd
, pass
, tmp
);
3986 } else { /* Store */
3987 tmp
= neon_load_reg(rd
, pass
);
3989 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3992 gen_st8(tmp
, addr
, IS_USER(s
));
3995 gen_st16(tmp
, addr
, IS_USER(s
));
3998 gen_st32(tmp
, addr
, IS_USER(s
));
4003 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4005 stride
= nregs
* (1 << size
);
4012 base
= load_reg(s
, rn
);
4014 tcg_gen_addi_i32(base
, base
, stride
);
4017 index
= load_reg(s
, rm
);
4018 tcg_gen_add_i32(base
, base
, index
);
4021 store_reg(s
, rn
, base
);
4026 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4027 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4029 tcg_gen_and_i32(t
, t
, c
);
4030 tcg_gen_andc_i32(f
, f
, c
);
4031 tcg_gen_or_i32(dest
, t
, f
);
4034 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4037 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4038 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4039 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4044 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4047 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4048 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4049 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4054 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4057 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4058 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4059 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4064 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4070 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4071 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4076 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4077 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4084 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4085 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4090 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4091 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4098 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4102 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4103 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4104 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4109 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4110 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4111 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4118 static inline void gen_neon_addl(int size
)
4121 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4122 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4123 case 2: tcg_gen_add_i64(CPU_V001
); break;
4128 static inline void gen_neon_subl(int size
)
4131 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4132 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4133 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4138 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4141 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4142 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4143 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4148 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4151 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4152 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4157 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4161 switch ((size
<< 1) | u
) {
4162 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4163 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4164 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4165 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4167 tmp
= gen_muls_i64_i32(a
, b
);
4168 tcg_gen_mov_i64(dest
, tmp
);
4171 tmp
= gen_mulu_i64_i32(a
, b
);
4172 tcg_gen_mov_i64(dest
, tmp
);
4178 /* Translate a NEON data processing instruction. Return nonzero if the
4179 instruction is invalid.
4180 We process data in a mixture of 32-bit and 64-bit chunks.
4181 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4183 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4196 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4199 if (!s
->vfp_enabled
)
4201 q
= (insn
& (1 << 6)) != 0;
4202 u
= (insn
>> 24) & 1;
4203 VFP_DREG_D(rd
, insn
);
4204 VFP_DREG_N(rn
, insn
);
4205 VFP_DREG_M(rm
, insn
);
4206 size
= (insn
>> 20) & 3;
4207 if ((insn
& (1 << 23)) == 0) {
4208 /* Three register same length. */
4209 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4210 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4211 || op
== 10 || op
== 11 || op
== 16)) {
4212 /* 64-bit element instructions. */
4213 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4214 neon_load_reg64(cpu_V0
, rn
+ pass
);
4215 neon_load_reg64(cpu_V1
, rm
+ pass
);
4219 gen_helper_neon_add_saturate_u64(CPU_V001
);
4221 gen_helper_neon_add_saturate_s64(CPU_V001
);
4226 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4228 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4233 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4235 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4240 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4243 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4247 case 10: /* VRSHL */
4249 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4251 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4254 case 11: /* VQRSHL */
4256 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4259 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4265 tcg_gen_sub_i64(CPU_V001
);
4267 tcg_gen_add_i64(CPU_V001
);
4273 neon_store_reg64(cpu_V0
, rd
+ pass
);
4280 case 10: /* VRSHL */
4281 case 11: /* VQRSHL */
4284 /* Shift instruction operands are reversed. */
4291 case 20: /* VPMAX */
4292 case 21: /* VPMIN */
4293 case 23: /* VPADD */
4296 case 26: /* VPADD (float) */
4297 pairwise
= (u
&& size
< 2);
4299 case 30: /* VPMIN/VPMAX (float) */
4307 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4316 tmp
= neon_load_reg(rn
, n
);
4317 tmp2
= neon_load_reg(rn
, n
+ 1);
4319 tmp
= neon_load_reg(rm
, n
);
4320 tmp2
= neon_load_reg(rm
, n
+ 1);
4324 tmp
= neon_load_reg(rn
, pass
);
4325 tmp2
= neon_load_reg(rm
, pass
);
4329 GEN_NEON_INTEGER_OP(hadd
);
4332 GEN_NEON_INTEGER_OP_ENV(qadd
);
4334 case 2: /* VRHADD */
4335 GEN_NEON_INTEGER_OP(rhadd
);
4337 case 3: /* Logic ops. */
4338 switch ((u
<< 2) | size
) {
4340 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4343 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4346 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4349 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4352 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4355 tmp3
= neon_load_reg(rd
, pass
);
4356 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4360 tmp3
= neon_load_reg(rd
, pass
);
4361 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4365 tmp3
= neon_load_reg(rd
, pass
);
4366 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4372 GEN_NEON_INTEGER_OP(hsub
);
4375 GEN_NEON_INTEGER_OP_ENV(qsub
);
4378 GEN_NEON_INTEGER_OP(cgt
);
4381 GEN_NEON_INTEGER_OP(cge
);
4384 GEN_NEON_INTEGER_OP(shl
);
4387 GEN_NEON_INTEGER_OP_ENV(qshl
);
4389 case 10: /* VRSHL */
4390 GEN_NEON_INTEGER_OP(rshl
);
4392 case 11: /* VQRSHL */
4393 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4396 GEN_NEON_INTEGER_OP(max
);
4399 GEN_NEON_INTEGER_OP(min
);
4402 GEN_NEON_INTEGER_OP(abd
);
4405 GEN_NEON_INTEGER_OP(abd
);
4407 tmp2
= neon_load_reg(rd
, pass
);
4408 gen_neon_add(size
, tmp
, tmp2
);
4411 if (!u
) { /* VADD */
4412 if (gen_neon_add(size
, tmp
, tmp2
))
4416 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4417 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4418 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4424 if (!u
) { /* VTST */
4426 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4427 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4428 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4433 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4434 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4435 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4440 case 18: /* Multiply. */
4442 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4443 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4444 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4448 tmp2
= neon_load_reg(rd
, pass
);
4450 gen_neon_rsb(size
, tmp
, tmp2
);
4452 gen_neon_add(size
, tmp
, tmp2
);
4456 if (u
) { /* polynomial */
4457 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4458 } else { /* Integer */
4460 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4461 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4462 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4467 case 20: /* VPMAX */
4468 GEN_NEON_INTEGER_OP(pmax
);
4470 case 21: /* VPMIN */
4471 GEN_NEON_INTEGER_OP(pmin
);
4473 case 22: /* Hultiply high. */
4474 if (!u
) { /* VQDMULH */
4476 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4477 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4480 } else { /* VQRDHMUL */
4482 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4483 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4488 case 23: /* VPADD */
4492 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4493 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4494 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4498 case 26: /* Floating point arithnetic. */
4499 switch ((u
<< 2) | size
) {
4501 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4504 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4507 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4510 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4516 case 27: /* Float multiply. */
4517 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4520 tmp2
= neon_load_reg(rd
, pass
);
4522 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4524 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4528 case 28: /* Float compare. */
4530 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4533 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4535 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4538 case 29: /* Float compare absolute. */
4542 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4544 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4546 case 30: /* Float min/max. */
4548 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4550 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4554 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4556 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4563 /* Save the result. For elementwise operations we can put it
4564 straight into the destination register. For pairwise operations
4565 we have to be careful to avoid clobbering the source operands. */
4566 if (pairwise
&& rd
== rm
) {
4567 neon_store_scratch(pass
, tmp
);
4569 neon_store_reg(rd
, pass
, tmp
);
4573 if (pairwise
&& rd
== rm
) {
4574 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4575 tmp
= neon_load_scratch(pass
);
4576 neon_store_reg(rd
, pass
, tmp
);
4579 /* End of 3 register same size operations. */
4580 } else if (insn
& (1 << 4)) {
4581 if ((insn
& 0x00380080) != 0) {
4582 /* Two registers and shift. */
4583 op
= (insn
>> 8) & 0xf;
4584 if (insn
& (1 << 7)) {
4589 while ((insn
& (1 << (size
+ 19))) == 0)
4592 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4593 /* To avoid excessive dumplication of ops we implement shift
4594 by immediate using the variable shift operations. */
4596 /* Shift by immediate:
4597 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4598 /* Right shifts are encoded as N - shift, where N is the
4599 element size in bits. */
4601 shift
= shift
- (1 << (size
+ 3));
4609 imm
= (uint8_t) shift
;
4614 imm
= (uint16_t) shift
;
4625 for (pass
= 0; pass
< count
; pass
++) {
4627 neon_load_reg64(cpu_V0
, rm
+ pass
);
4628 tcg_gen_movi_i64(cpu_V1
, imm
);
4633 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4635 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4640 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4642 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4647 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4649 case 5: /* VSHL, VSLI */
4650 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4652 case 6: /* VQSHLU */
4654 gen_helper_neon_qshlu_s64(cpu_V0
, cpu_env
,
4662 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4665 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4670 if (op
== 1 || op
== 3) {
4672 neon_load_reg64(cpu_V0
, rd
+ pass
);
4673 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4674 } else if (op
== 4 || (op
== 5 && u
)) {
4676 cpu_abort(env
, "VS[LR]I.64 not implemented");
4678 neon_store_reg64(cpu_V0
, rd
+ pass
);
4679 } else { /* size < 3 */
4680 /* Operands in T0 and T1. */
4681 tmp
= neon_load_reg(rm
, pass
);
4683 tcg_gen_movi_i32(tmp2
, imm
);
4687 GEN_NEON_INTEGER_OP(shl
);
4691 GEN_NEON_INTEGER_OP(rshl
);
4696 GEN_NEON_INTEGER_OP(shl
);
4698 case 5: /* VSHL, VSLI */
4700 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4701 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4702 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4706 case 6: /* VQSHLU */
4712 gen_helper_neon_qshlu_s8(tmp
, cpu_env
,
4716 gen_helper_neon_qshlu_s16(tmp
, cpu_env
,
4720 gen_helper_neon_qshlu_s32(tmp
, cpu_env
,
4728 GEN_NEON_INTEGER_OP_ENV(qshl
);
4733 if (op
== 1 || op
== 3) {
4735 tmp2
= neon_load_reg(rd
, pass
);
4736 gen_neon_add(size
, tmp2
, tmp
);
4738 } else if (op
== 4 || (op
== 5 && u
)) {
4743 mask
= 0xff >> -shift
;
4745 mask
= (uint8_t)(0xff << shift
);
4751 mask
= 0xffff >> -shift
;
4753 mask
= (uint16_t)(0xffff << shift
);
4757 if (shift
< -31 || shift
> 31) {
4761 mask
= 0xffffffffu
>> -shift
;
4763 mask
= 0xffffffffu
<< shift
;
4769 tmp2
= neon_load_reg(rd
, pass
);
4770 tcg_gen_andi_i32(tmp
, tmp
, mask
);
4771 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
4772 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4775 neon_store_reg(rd
, pass
, tmp
);
4778 } else if (op
< 10) {
4779 /* Shift by immediate and narrow:
4780 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4781 shift
= shift
- (1 << (size
+ 3));
4785 imm
= (uint16_t)shift
;
4787 tmp2
= tcg_const_i32(imm
);
4788 TCGV_UNUSED_I64(tmp64
);
4791 imm
= (uint32_t)shift
;
4792 tmp2
= tcg_const_i32(imm
);
4793 TCGV_UNUSED_I64(tmp64
);
4796 tmp64
= tcg_const_i64(shift
);
4803 for (pass
= 0; pass
< 2; pass
++) {
4805 neon_load_reg64(cpu_V0
, rm
+ pass
);
4808 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4810 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4813 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4815 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4818 tmp
= neon_load_reg(rm
+ pass
, 0);
4819 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4820 tmp3
= neon_load_reg(rm
+ pass
, 1);
4821 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4822 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4827 if (op
== 8 && !u
) {
4828 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4831 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4833 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4835 neon_store_reg(rd
, pass
, tmp
);
4838 tcg_temp_free_i64(tmp64
);
4842 } else if (op
== 10) {
4846 tmp
= neon_load_reg(rm
, 0);
4847 tmp2
= neon_load_reg(rm
, 1);
4848 for (pass
= 0; pass
< 2; pass
++) {
4852 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4855 /* The shift is less than the width of the source
4856 type, so we can just shift the whole register. */
4857 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4858 if (size
< 2 || !u
) {
4861 imm
= (0xffu
>> (8 - shift
));
4864 imm
= 0xffff >> (16 - shift
);
4866 imm64
= imm
| (((uint64_t)imm
) << 32);
4867 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4870 neon_store_reg64(cpu_V0
, rd
+ pass
);
4872 } else if (op
>= 14) {
4873 /* VCVT fixed-point. */
4874 /* We have already masked out the must-be-1 top bit of imm6,
4875 * hence this 32-shift where the ARM ARM has 64-imm6.
4878 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4879 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4882 gen_vfp_ulto(0, shift
);
4884 gen_vfp_slto(0, shift
);
4887 gen_vfp_toul(0, shift
);
4889 gen_vfp_tosl(0, shift
);
4891 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4896 } else { /* (insn & 0x00380080) == 0 */
4899 op
= (insn
>> 8) & 0xf;
4900 /* One register and immediate. */
4901 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4902 invert
= (insn
& (1 << 5)) != 0;
4920 imm
= (imm
<< 8) | (imm
<< 24);
4923 imm
= (imm
<< 8) | 0xff;
4926 imm
= (imm
<< 16) | 0xffff;
4929 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4934 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4935 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4941 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4942 if (op
& 1 && op
< 12) {
4943 tmp
= neon_load_reg(rd
, pass
);
4945 /* The immediate value has already been inverted, so
4947 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4949 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4954 if (op
== 14 && invert
) {
4957 for (n
= 0; n
< 4; n
++) {
4958 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4959 val
|= 0xff << (n
* 8);
4961 tcg_gen_movi_i32(tmp
, val
);
4963 tcg_gen_movi_i32(tmp
, imm
);
4966 neon_store_reg(rd
, pass
, tmp
);
4969 } else { /* (insn & 0x00800010 == 0x00800000) */
4971 op
= (insn
>> 8) & 0xf;
4972 if ((insn
& (1 << 6)) == 0) {
4973 /* Three registers of different lengths. */
4977 /* prewiden, src1_wide, src2_wide */
4978 static const int neon_3reg_wide
[16][3] = {
4979 {1, 0, 0}, /* VADDL */
4980 {1, 1, 0}, /* VADDW */
4981 {1, 0, 0}, /* VSUBL */
4982 {1, 1, 0}, /* VSUBW */
4983 {0, 1, 1}, /* VADDHN */
4984 {0, 0, 0}, /* VABAL */
4985 {0, 1, 1}, /* VSUBHN */
4986 {0, 0, 0}, /* VABDL */
4987 {0, 0, 0}, /* VMLAL */
4988 {0, 0, 0}, /* VQDMLAL */
4989 {0, 0, 0}, /* VMLSL */
4990 {0, 0, 0}, /* VQDMLSL */
4991 {0, 0, 0}, /* Integer VMULL */
4992 {0, 0, 0}, /* VQDMULL */
4993 {0, 0, 0} /* Polynomial VMULL */
4996 prewiden
= neon_3reg_wide
[op
][0];
4997 src1_wide
= neon_3reg_wide
[op
][1];
4998 src2_wide
= neon_3reg_wide
[op
][2];
5000 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
5003 /* Avoid overlapping operands. Wide source operands are
5004 always aligned so will never overlap with wide
5005 destinations in problematic ways. */
5006 if (rd
== rm
&& !src2_wide
) {
5007 tmp
= neon_load_reg(rm
, 1);
5008 neon_store_scratch(2, tmp
);
5009 } else if (rd
== rn
&& !src1_wide
) {
5010 tmp
= neon_load_reg(rn
, 1);
5011 neon_store_scratch(2, tmp
);
5014 for (pass
= 0; pass
< 2; pass
++) {
5016 neon_load_reg64(cpu_V0
, rn
+ pass
);
5019 if (pass
== 1 && rd
== rn
) {
5020 tmp
= neon_load_scratch(2);
5022 tmp
= neon_load_reg(rn
, pass
);
5025 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5029 neon_load_reg64(cpu_V1
, rm
+ pass
);
5032 if (pass
== 1 && rd
== rm
) {
5033 tmp2
= neon_load_scratch(2);
5035 tmp2
= neon_load_reg(rm
, pass
);
5038 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5042 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5043 gen_neon_addl(size
);
5045 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5046 gen_neon_subl(size
);
5048 case 5: case 7: /* VABAL, VABDL */
5049 switch ((size
<< 1) | u
) {
5051 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5054 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5057 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5060 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5063 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5066 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5073 case 8: case 9: case 10: case 11: case 12: case 13:
5074 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5075 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5079 case 14: /* Polynomial VMULL */
5080 cpu_abort(env
, "Polynomial VMULL not implemented");
5082 default: /* 15 is RESERVED. */
5085 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5087 if (op
== 10 || op
== 11) {
5088 gen_neon_negl(cpu_V0
, size
);
5092 neon_load_reg64(cpu_V1
, rd
+ pass
);
5096 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5097 gen_neon_addl(size
);
5099 case 9: case 11: /* VQDMLAL, VQDMLSL */
5100 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5101 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5104 case 13: /* VQDMULL */
5105 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5110 neon_store_reg64(cpu_V0
, rd
+ pass
);
5111 } else if (op
== 4 || op
== 6) {
5112 /* Narrowing operation. */
5117 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5120 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5123 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5124 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5131 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5134 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5137 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5138 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5139 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5147 neon_store_reg(rd
, 0, tmp3
);
5148 neon_store_reg(rd
, 1, tmp
);
5151 /* Write back the result. */
5152 neon_store_reg64(cpu_V0
, rd
+ pass
);
5156 /* Two registers and a scalar. */
5158 case 0: /* Integer VMLA scalar */
5159 case 1: /* Float VMLA scalar */
5160 case 4: /* Integer VMLS scalar */
5161 case 5: /* Floating point VMLS scalar */
5162 case 8: /* Integer VMUL scalar */
5163 case 9: /* Floating point VMUL scalar */
5164 case 12: /* VQDMULH scalar */
5165 case 13: /* VQRDMULH scalar */
5166 tmp
= neon_get_scalar(size
, rm
);
5167 neon_store_scratch(0, tmp
);
5168 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5169 tmp
= neon_load_scratch(0);
5170 tmp2
= neon_load_reg(rn
, pass
);
5173 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5175 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5177 } else if (op
== 13) {
5179 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5181 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5183 } else if (op
& 1) {
5184 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5187 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5188 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5189 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5196 tmp2
= neon_load_reg(rd
, pass
);
5199 gen_neon_add(size
, tmp
, tmp2
);
5202 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5205 gen_neon_rsb(size
, tmp
, tmp2
);
5208 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5215 neon_store_reg(rd
, pass
, tmp
);
5218 case 2: /* VMLAL sclar */
5219 case 3: /* VQDMLAL scalar */
5220 case 6: /* VMLSL scalar */
5221 case 7: /* VQDMLSL scalar */
5222 case 10: /* VMULL scalar */
5223 case 11: /* VQDMULL scalar */
5224 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5227 tmp2
= neon_get_scalar(size
, rm
);
5228 tmp3
= neon_load_reg(rn
, 1);
5230 for (pass
= 0; pass
< 2; pass
++) {
5232 tmp
= neon_load_reg(rn
, 0);
5236 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5238 if (op
== 6 || op
== 7) {
5239 gen_neon_negl(cpu_V0
, size
);
5242 neon_load_reg64(cpu_V1
, rd
+ pass
);
5246 gen_neon_addl(size
);
5249 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5250 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5256 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5261 neon_store_reg64(cpu_V0
, rd
+ pass
);
5267 default: /* 14 and 15 are RESERVED */
5271 } else { /* size == 3 */
5274 imm
= (insn
>> 8) & 0xf;
5280 neon_load_reg64(cpu_V0
, rn
);
5282 neon_load_reg64(cpu_V1
, rn
+ 1);
5284 } else if (imm
== 8) {
5285 neon_load_reg64(cpu_V0
, rn
+ 1);
5287 neon_load_reg64(cpu_V1
, rm
);
5290 tmp64
= tcg_temp_new_i64();
5292 neon_load_reg64(cpu_V0
, rn
);
5293 neon_load_reg64(tmp64
, rn
+ 1);
5295 neon_load_reg64(cpu_V0
, rn
+ 1);
5296 neon_load_reg64(tmp64
, rm
);
5298 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5299 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5300 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5302 neon_load_reg64(cpu_V1
, rm
);
5304 neon_load_reg64(cpu_V1
, rm
+ 1);
5307 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5308 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5309 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5310 tcg_temp_free_i64(tmp64
);
5313 neon_load_reg64(cpu_V0
, rn
);
5314 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5315 neon_load_reg64(cpu_V1
, rm
);
5316 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5317 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5319 neon_store_reg64(cpu_V0
, rd
);
5321 neon_store_reg64(cpu_V1
, rd
+ 1);
5323 } else if ((insn
& (1 << 11)) == 0) {
5324 /* Two register misc. */
5325 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5326 size
= (insn
>> 18) & 3;
5328 case 0: /* VREV64 */
5331 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5332 tmp
= neon_load_reg(rm
, pass
* 2);
5333 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5335 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5336 case 1: gen_swap_half(tmp
); break;
5337 case 2: /* no-op */ break;
5340 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5342 neon_store_reg(rd
, pass
* 2, tmp2
);
5345 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5346 case 1: gen_swap_half(tmp2
); break;
5349 neon_store_reg(rd
, pass
* 2, tmp2
);
5353 case 4: case 5: /* VPADDL */
5354 case 12: case 13: /* VPADAL */
5357 for (pass
= 0; pass
< q
+ 1; pass
++) {
5358 tmp
= neon_load_reg(rm
, pass
* 2);
5359 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5360 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5361 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5363 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5364 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5365 case 2: tcg_gen_add_i64(CPU_V001
); break;
5370 neon_load_reg64(cpu_V1
, rd
+ pass
);
5371 gen_neon_addl(size
);
5373 neon_store_reg64(cpu_V0
, rd
+ pass
);
5378 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5379 tmp
= neon_load_reg(rm
, n
);
5380 tmp2
= neon_load_reg(rd
, n
+ 1);
5381 neon_store_reg(rm
, n
, tmp2
);
5382 neon_store_reg(rd
, n
+ 1, tmp
);
5390 Rd A3 A2 A1 A0 B2 B0 A2 A0
5391 Rm B3 B2 B1 B0 B3 B1 A3 A1
5395 gen_neon_unzip(rd
, q
, 0, size
);
5396 gen_neon_unzip(rm
, q
, 4, size
);
5398 static int unzip_order_q
[8] =
5399 {0, 2, 4, 6, 1, 3, 5, 7};
5400 for (n
= 0; n
< 8; n
++) {
5401 int reg
= (n
< 4) ? rd
: rm
;
5402 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5403 neon_store_reg(reg
, n
% 4, tmp
);
5406 static int unzip_order
[4] =
5408 for (n
= 0; n
< 4; n
++) {
5409 int reg
= (n
< 2) ? rd
: rm
;
5410 tmp
= neon_load_scratch(unzip_order
[n
]);
5411 neon_store_reg(reg
, n
% 2, tmp
);
5417 Rd A3 A2 A1 A0 B1 A1 B0 A0
5418 Rm B3 B2 B1 B0 B3 A3 B2 A2
5422 count
= (q
? 4 : 2);
5423 for (n
= 0; n
< count
; n
++) {
5424 tmp
= neon_load_reg(rd
, n
);
5425 tmp2
= neon_load_reg(rd
, n
);
5427 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5428 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5429 case 2: /* no-op */; break;
5432 neon_store_scratch(n
* 2, tmp
);
5433 neon_store_scratch(n
* 2 + 1, tmp2
);
5435 for (n
= 0; n
< count
* 2; n
++) {
5436 int reg
= (n
< count
) ? rd
: rm
;
5437 tmp
= neon_load_scratch(n
);
5438 neon_store_reg(reg
, n
% count
, tmp
);
5441 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5445 for (pass
= 0; pass
< 2; pass
++) {
5446 neon_load_reg64(cpu_V0
, rm
+ pass
);
5448 if (op
== 36 && q
== 0) {
5449 gen_neon_narrow(size
, tmp
, cpu_V0
);
5451 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5453 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5458 neon_store_reg(rd
, 0, tmp2
);
5459 neon_store_reg(rd
, 1, tmp
);
5463 case 38: /* VSHLL */
5466 tmp
= neon_load_reg(rm
, 0);
5467 tmp2
= neon_load_reg(rm
, 1);
5468 for (pass
= 0; pass
< 2; pass
++) {
5471 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5472 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5473 neon_store_reg64(cpu_V0
, rd
+ pass
);
5476 case 44: /* VCVT.F16.F32 */
5477 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5481 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5482 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5483 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5484 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5485 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5486 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5487 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5488 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5489 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5490 neon_store_reg(rd
, 0, tmp2
);
5492 gen_helper_vfp_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5493 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5494 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5495 neon_store_reg(rd
, 1, tmp2
);
5498 case 46: /* VCVT.F32.F16 */
5499 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
))
5502 tmp
= neon_load_reg(rm
, 0);
5503 tmp2
= neon_load_reg(rm
, 1);
5504 tcg_gen_ext16u_i32(tmp3
, tmp
);
5505 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5506 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5507 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5508 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5509 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5511 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5512 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5513 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5514 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5515 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5516 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5522 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5523 if (op
== 30 || op
== 31 || op
>= 58) {
5524 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5525 neon_reg_offset(rm
, pass
));
5528 tmp
= neon_load_reg(rm
, pass
);
5531 case 1: /* VREV32 */
5533 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5534 case 1: gen_swap_half(tmp
); break;
5538 case 2: /* VREV16 */
5545 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5546 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5547 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5553 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5554 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5555 case 2: gen_helper_clz(tmp
, tmp
); break;
5562 gen_helper_neon_cnt_u8(tmp
, tmp
);
5567 tcg_gen_not_i32(tmp
, tmp
);
5569 case 14: /* VQABS */
5571 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5572 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5573 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5577 case 15: /* VQNEG */
5579 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5580 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5581 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5585 case 16: case 19: /* VCGT #0, VCLE #0 */
5586 tmp2
= tcg_const_i32(0);
5588 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5589 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5590 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5593 tcg_temp_free(tmp2
);
5595 tcg_gen_not_i32(tmp
, tmp
);
5597 case 17: case 20: /* VCGE #0, VCLT #0 */
5598 tmp2
= tcg_const_i32(0);
5600 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5601 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5602 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5605 tcg_temp_free(tmp2
);
5607 tcg_gen_not_i32(tmp
, tmp
);
5609 case 18: /* VCEQ #0 */
5610 tmp2
= tcg_const_i32(0);
5612 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5613 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5614 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5617 tcg_temp_free(tmp2
);
5621 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5622 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5623 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5630 tmp2
= tcg_const_i32(0);
5631 gen_neon_rsb(size
, tmp
, tmp2
);
5632 tcg_temp_free(tmp2
);
5634 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5635 tmp2
= tcg_const_i32(0);
5636 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5637 tcg_temp_free(tmp2
);
5639 tcg_gen_not_i32(tmp
, tmp
);
5641 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5642 tmp2
= tcg_const_i32(0);
5643 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5644 tcg_temp_free(tmp2
);
5646 tcg_gen_not_i32(tmp
, tmp
);
5648 case 26: /* Float VCEQ #0 */
5649 tmp2
= tcg_const_i32(0);
5650 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5651 tcg_temp_free(tmp2
);
5653 case 30: /* Float VABS */
5656 case 31: /* Float VNEG */
5660 tmp2
= neon_load_reg(rd
, pass
);
5661 neon_store_reg(rm
, pass
, tmp2
);
5664 tmp2
= neon_load_reg(rd
, pass
);
5666 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5667 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5671 neon_store_reg(rm
, pass
, tmp2
);
5673 case 56: /* Integer VRECPE */
5674 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5676 case 57: /* Integer VRSQRTE */
5677 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5679 case 58: /* Float VRECPE */
5680 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5682 case 59: /* Float VRSQRTE */
5683 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5685 case 60: /* VCVT.F32.S32 */
5688 case 61: /* VCVT.F32.U32 */
5691 case 62: /* VCVT.S32.F32 */
5694 case 63: /* VCVT.U32.F32 */
5698 /* Reserved: 21, 29, 39-56 */
5701 if (op
== 30 || op
== 31 || op
>= 58) {
5702 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5703 neon_reg_offset(rd
, pass
));
5705 neon_store_reg(rd
, pass
, tmp
);
5710 } else if ((insn
& (1 << 10)) == 0) {
5712 n
= ((insn
>> 5) & 0x18) + 8;
5713 if (insn
& (1 << 6)) {
5714 tmp
= neon_load_reg(rd
, 0);
5717 tcg_gen_movi_i32(tmp
, 0);
5719 tmp2
= neon_load_reg(rm
, 0);
5720 tmp4
= tcg_const_i32(rn
);
5721 tmp5
= tcg_const_i32(n
);
5722 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5724 if (insn
& (1 << 6)) {
5725 tmp
= neon_load_reg(rd
, 1);
5728 tcg_gen_movi_i32(tmp
, 0);
5730 tmp3
= neon_load_reg(rm
, 1);
5731 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5732 tcg_temp_free_i32(tmp5
);
5733 tcg_temp_free_i32(tmp4
);
5734 neon_store_reg(rd
, 0, tmp2
);
5735 neon_store_reg(rd
, 1, tmp3
);
5737 } else if ((insn
& 0x380) == 0) {
5739 if (insn
& (1 << 19)) {
5740 tmp
= neon_load_reg(rm
, 1);
5742 tmp
= neon_load_reg(rm
, 0);
5744 if (insn
& (1 << 16)) {
5745 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5746 } else if (insn
& (1 << 17)) {
5747 if ((insn
>> 18) & 1)
5748 gen_neon_dup_high16(tmp
);
5750 gen_neon_dup_low16(tmp
);
5752 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5754 tcg_gen_mov_i32(tmp2
, tmp
);
5755 neon_store_reg(rd
, pass
, tmp2
);
5766 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5768 int crn
= (insn
>> 16) & 0xf;
5769 int crm
= insn
& 0xf;
5770 int op1
= (insn
>> 21) & 7;
5771 int op2
= (insn
>> 5) & 7;
5772 int rt
= (insn
>> 12) & 0xf;
5775 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5776 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5780 tmp
= load_cpu_field(teecr
);
5781 store_reg(s
, rt
, tmp
);
5784 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5786 if (IS_USER(s
) && (env
->teecr
& 1))
5788 tmp
= load_cpu_field(teehbr
);
5789 store_reg(s
, rt
, tmp
);
5793 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5794 op1
, crn
, crm
, op2
);
5798 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5800 int crn
= (insn
>> 16) & 0xf;
5801 int crm
= insn
& 0xf;
5802 int op1
= (insn
>> 21) & 7;
5803 int op2
= (insn
>> 5) & 7;
5804 int rt
= (insn
>> 12) & 0xf;
5807 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5808 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5812 tmp
= load_reg(s
, rt
);
5813 gen_helper_set_teecr(cpu_env
, tmp
);
5817 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5819 if (IS_USER(s
) && (env
->teecr
& 1))
5821 tmp
= load_reg(s
, rt
);
5822 store_cpu_field(tmp
, teehbr
);
5826 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5827 op1
, crn
, crm
, op2
);
5831 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5835 cpnum
= (insn
>> 8) & 0xf;
5836 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5837 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5843 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5844 return disas_iwmmxt_insn(env
, s
, insn
);
5845 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5846 return disas_dsp_insn(env
, s
, insn
);
5851 return disas_vfp_insn (env
, s
, insn
);
5853 /* Coprocessors 7-15 are architecturally reserved by ARM.
5854 Unfortunately Intel decided to ignore this. */
5855 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5857 if (insn
& (1 << 20))
5858 return disas_cp14_read(env
, s
, insn
);
5860 return disas_cp14_write(env
, s
, insn
);
5862 return disas_cp15_insn (env
, s
, insn
);
5865 /* Unknown coprocessor. See if the board has hooked it. */
5866 return disas_cp_insn (env
, s
, insn
);
5871 /* Store a 64-bit value to a register pair. Clobbers val. */
5872 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5876 tcg_gen_trunc_i64_i32(tmp
, val
);
5877 store_reg(s
, rlow
, tmp
);
5879 tcg_gen_shri_i64(val
, val
, 32);
5880 tcg_gen_trunc_i64_i32(tmp
, val
);
5881 store_reg(s
, rhigh
, tmp
);
5884 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5885 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5890 /* Load value and extend to 64 bits. */
5891 tmp
= tcg_temp_new_i64();
5892 tmp2
= load_reg(s
, rlow
);
5893 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5895 tcg_gen_add_i64(val
, val
, tmp
);
5896 tcg_temp_free_i64(tmp
);
5899 /* load and add a 64-bit value from a register pair. */
5900 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5906 /* Load 64-bit value rd:rn. */
5907 tmpl
= load_reg(s
, rlow
);
5908 tmph
= load_reg(s
, rhigh
);
5909 tmp
= tcg_temp_new_i64();
5910 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5913 tcg_gen_add_i64(val
, val
, tmp
);
5914 tcg_temp_free_i64(tmp
);
5917 /* Set N and Z flags from a 64-bit value. */
5918 static void gen_logicq_cc(TCGv_i64 val
)
5920 TCGv tmp
= new_tmp();
5921 gen_helper_logicq_cc(tmp
, val
);
5926 /* Load/Store exclusive instructions are implemented by remembering
5927 the value/address loaded, and seeing if these are the same
5928 when the store is performed. This should be is sufficient to implement
5929 the architecturally mandated semantics, and avoids having to monitor
5932 In system emulation mode only one CPU will be running at once, so
5933 this sequence is effectively atomic. In user emulation mode we
5934 throw an exception and handle the atomic operation elsewhere. */
5935 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
5936 TCGv addr
, int size
)
5942 tmp
= gen_ld8u(addr
, IS_USER(s
));
5945 tmp
= gen_ld16u(addr
, IS_USER(s
));
5949 tmp
= gen_ld32(addr
, IS_USER(s
));
5954 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
5955 store_reg(s
, rt
, tmp
);
5957 TCGv tmp2
= new_tmp();
5958 tcg_gen_addi_i32(tmp2
, addr
, 4);
5959 tmp
= gen_ld32(tmp2
, IS_USER(s
));
5961 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
5962 store_reg(s
, rt2
, tmp
);
5964 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
5967 static void gen_clrex(DisasContext
*s
)
5969 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
5972 #ifdef CONFIG_USER_ONLY
5973 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5974 TCGv addr
, int size
)
5976 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
5977 tcg_gen_movi_i32(cpu_exclusive_info
,
5978 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
5979 gen_set_condexec(s
);
5980 gen_set_pc_im(s
->pc
- 4);
5981 gen_exception(EXCP_STREX
);
5982 s
->is_jmp
= DISAS_JUMP
;
5985 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
5986 TCGv addr
, int size
)
5992 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5998 fail_label
= gen_new_label();
5999 done_label
= gen_new_label();
6000 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
6003 tmp
= gen_ld8u(addr
, IS_USER(s
));
6006 tmp
= gen_ld16u(addr
, IS_USER(s
));
6010 tmp
= gen_ld32(addr
, IS_USER(s
));
6015 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
6018 TCGv tmp2
= new_tmp();
6019 tcg_gen_addi_i32(tmp2
, addr
, 4);
6020 tmp
= gen_ld32(tmp2
, IS_USER(s
));
6022 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6025 tmp
= load_reg(s
, rt
);
6028 gen_st8(tmp
, addr
, IS_USER(s
));
6031 gen_st16(tmp
, addr
, IS_USER(s
));
6035 gen_st32(tmp
, addr
, IS_USER(s
));
6041 tcg_gen_addi_i32(addr
, addr
, 4);
6042 tmp
= load_reg(s
, rt2
);
6043 gen_st32(tmp
, addr
, IS_USER(s
));
6045 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6046 tcg_gen_br(done_label
);
6047 gen_set_label(fail_label
);
6048 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6049 gen_set_label(done_label
);
6050 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6054 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
6056 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6063 insn
= ldl_code(s
->pc
);
6066 /* M variants do not implement ARM mode. */
6071 /* Unconditional instructions. */
6072 if (((insn
>> 25) & 7) == 1) {
6073 /* NEON Data processing. */
6074 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6077 if (disas_neon_data_insn(env
, s
, insn
))
6081 if ((insn
& 0x0f100000) == 0x04000000) {
6082 /* NEON load/store. */
6083 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6086 if (disas_neon_ls_insn(env
, s
, insn
))
6090 if ((insn
& 0x0d70f000) == 0x0550f000)
6092 else if ((insn
& 0x0ffffdff) == 0x01010000) {
6095 if (insn
& (1 << 9)) {
6096 /* BE8 mode not implemented. */
6100 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6101 switch ((insn
>> 4) & 0xf) {
6110 /* We don't emulate caches so these are a no-op. */
6115 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6121 op1
= (insn
& 0x1f);
6123 tmp
= tcg_const_i32(op1
);
6124 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6125 tcg_temp_free_i32(tmp
);
6126 i
= (insn
>> 23) & 3;
6128 case 0: offset
= -4; break; /* DA */
6129 case 1: offset
= 0; break; /* IA */
6130 case 2: offset
= -8; break; /* DB */
6131 case 3: offset
= 4; break; /* IB */
6135 tcg_gen_addi_i32(addr
, addr
, offset
);
6136 tmp
= load_reg(s
, 14);
6137 gen_st32(tmp
, addr
, 0);
6138 tmp
= load_cpu_field(spsr
);
6139 tcg_gen_addi_i32(addr
, addr
, 4);
6140 gen_st32(tmp
, addr
, 0);
6141 if (insn
& (1 << 21)) {
6142 /* Base writeback. */
6144 case 0: offset
= -8; break;
6145 case 1: offset
= 4; break;
6146 case 2: offset
= -4; break;
6147 case 3: offset
= 0; break;
6151 tcg_gen_addi_i32(addr
, addr
, offset
);
6152 tmp
= tcg_const_i32(op1
);
6153 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6154 tcg_temp_free_i32(tmp
);
6160 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6166 rn
= (insn
>> 16) & 0xf;
6167 addr
= load_reg(s
, rn
);
6168 i
= (insn
>> 23) & 3;
6170 case 0: offset
= -4; break; /* DA */
6171 case 1: offset
= 0; break; /* IA */
6172 case 2: offset
= -8; break; /* DB */
6173 case 3: offset
= 4; break; /* IB */
6177 tcg_gen_addi_i32(addr
, addr
, offset
);
6178 /* Load PC into tmp and CPSR into tmp2. */
6179 tmp
= gen_ld32(addr
, 0);
6180 tcg_gen_addi_i32(addr
, addr
, 4);
6181 tmp2
= gen_ld32(addr
, 0);
6182 if (insn
& (1 << 21)) {
6183 /* Base writeback. */
6185 case 0: offset
= -8; break;
6186 case 1: offset
= 4; break;
6187 case 2: offset
= -4; break;
6188 case 3: offset
= 0; break;
6192 tcg_gen_addi_i32(addr
, addr
, offset
);
6193 store_reg(s
, rn
, addr
);
6197 gen_rfe(s
, tmp
, tmp2
);
6199 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6200 /* branch link and change to thumb (blx <offset>) */
6203 val
= (uint32_t)s
->pc
;
6205 tcg_gen_movi_i32(tmp
, val
);
6206 store_reg(s
, 14, tmp
);
6207 /* Sign-extend the 24-bit offset */
6208 offset
= (((int32_t)insn
) << 8) >> 8;
6209 /* offset * 4 + bit24 * 2 + (thumb bit) */
6210 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6211 /* pipeline offset */
6215 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6216 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6217 /* iWMMXt register transfer. */
6218 if (env
->cp15
.c15_cpar
& (1 << 1))
6219 if (!disas_iwmmxt_insn(env
, s
, insn
))
6222 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6223 /* Coprocessor double register transfer. */
6224 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6225 /* Additional coprocessor register transfer. */
6226 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6229 /* cps (privileged) */
6233 if (insn
& (1 << 19)) {
6234 if (insn
& (1 << 8))
6236 if (insn
& (1 << 7))
6238 if (insn
& (1 << 6))
6240 if (insn
& (1 << 18))
6243 if (insn
& (1 << 17)) {
6245 val
|= (insn
& 0x1f);
6248 gen_set_psr_im(s
, mask
, 0, val
);
6255 /* if not always execute, we generate a conditional jump to
6257 s
->condlabel
= gen_new_label();
6258 gen_test_cc(cond
^ 1, s
->condlabel
);
6261 if ((insn
& 0x0f900000) == 0x03000000) {
6262 if ((insn
& (1 << 21)) == 0) {
6264 rd
= (insn
>> 12) & 0xf;
6265 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6266 if ((insn
& (1 << 22)) == 0) {
6269 tcg_gen_movi_i32(tmp
, val
);
6272 tmp
= load_reg(s
, rd
);
6273 tcg_gen_ext16u_i32(tmp
, tmp
);
6274 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6276 store_reg(s
, rd
, tmp
);
6278 if (((insn
>> 12) & 0xf) != 0xf)
6280 if (((insn
>> 16) & 0xf) == 0) {
6281 gen_nop_hint(s
, insn
& 0xff);
6283 /* CPSR = immediate */
6285 shift
= ((insn
>> 8) & 0xf) * 2;
6287 val
= (val
>> shift
) | (val
<< (32 - shift
));
6288 i
= ((insn
& (1 << 22)) != 0);
6289 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6293 } else if ((insn
& 0x0f900000) == 0x01000000
6294 && (insn
& 0x00000090) != 0x00000090) {
6295 /* miscellaneous instructions */
6296 op1
= (insn
>> 21) & 3;
6297 sh
= (insn
>> 4) & 0xf;
6300 case 0x0: /* move program status register */
6303 tmp
= load_reg(s
, rm
);
6304 i
= ((op1
& 2) != 0);
6305 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6309 rd
= (insn
>> 12) & 0xf;
6313 tmp
= load_cpu_field(spsr
);
6316 gen_helper_cpsr_read(tmp
);
6318 store_reg(s
, rd
, tmp
);
6323 /* branch/exchange thumb (bx). */
6324 tmp
= load_reg(s
, rm
);
6326 } else if (op1
== 3) {
6328 rd
= (insn
>> 12) & 0xf;
6329 tmp
= load_reg(s
, rm
);
6330 gen_helper_clz(tmp
, tmp
);
6331 store_reg(s
, rd
, tmp
);
6339 /* Trivial implementation equivalent to bx. */
6340 tmp
= load_reg(s
, rm
);
6350 /* branch link/exchange thumb (blx) */
6351 tmp
= load_reg(s
, rm
);
6353 tcg_gen_movi_i32(tmp2
, s
->pc
);
6354 store_reg(s
, 14, tmp2
);
6357 case 0x5: /* saturating add/subtract */
6358 rd
= (insn
>> 12) & 0xf;
6359 rn
= (insn
>> 16) & 0xf;
6360 tmp
= load_reg(s
, rm
);
6361 tmp2
= load_reg(s
, rn
);
6363 gen_helper_double_saturate(tmp2
, tmp2
);
6365 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6367 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6369 store_reg(s
, rd
, tmp
);
6372 /* SMC instruction (op1 == 3)
6373 and undefined instructions (op1 == 0 || op1 == 2)
6379 gen_set_condexec(s
);
6380 gen_set_pc_im(s
->pc
- 4);
6381 gen_exception(EXCP_BKPT
);
6382 s
->is_jmp
= DISAS_JUMP
;
6384 case 0x8: /* signed multiply */
6388 rs
= (insn
>> 8) & 0xf;
6389 rn
= (insn
>> 12) & 0xf;
6390 rd
= (insn
>> 16) & 0xf;
6392 /* (32 * 16) >> 16 */
6393 tmp
= load_reg(s
, rm
);
6394 tmp2
= load_reg(s
, rs
);
6396 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6399 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6400 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6402 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6403 tcg_temp_free_i64(tmp64
);
6404 if ((sh
& 2) == 0) {
6405 tmp2
= load_reg(s
, rn
);
6406 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6409 store_reg(s
, rd
, tmp
);
6412 tmp
= load_reg(s
, rm
);
6413 tmp2
= load_reg(s
, rs
);
6414 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6417 tmp64
= tcg_temp_new_i64();
6418 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6420 gen_addq(s
, tmp64
, rn
, rd
);
6421 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6422 tcg_temp_free_i64(tmp64
);
6425 tmp2
= load_reg(s
, rn
);
6426 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6429 store_reg(s
, rd
, tmp
);
6436 } else if (((insn
& 0x0e000000) == 0 &&
6437 (insn
& 0x00000090) != 0x90) ||
6438 ((insn
& 0x0e000000) == (1 << 25))) {
6439 int set_cc
, logic_cc
, shiftop
;
6441 op1
= (insn
>> 21) & 0xf;
6442 set_cc
= (insn
>> 20) & 1;
6443 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6445 /* data processing instruction */
6446 if (insn
& (1 << 25)) {
6447 /* immediate operand */
6449 shift
= ((insn
>> 8) & 0xf) * 2;
6451 val
= (val
>> shift
) | (val
<< (32 - shift
));
6454 tcg_gen_movi_i32(tmp2
, val
);
6455 if (logic_cc
&& shift
) {
6456 gen_set_CF_bit31(tmp2
);
6461 tmp2
= load_reg(s
, rm
);
6462 shiftop
= (insn
>> 5) & 3;
6463 if (!(insn
& (1 << 4))) {
6464 shift
= (insn
>> 7) & 0x1f;
6465 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6467 rs
= (insn
>> 8) & 0xf;
6468 tmp
= load_reg(s
, rs
);
6469 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6472 if (op1
!= 0x0f && op1
!= 0x0d) {
6473 rn
= (insn
>> 16) & 0xf;
6474 tmp
= load_reg(s
, rn
);
6478 rd
= (insn
>> 12) & 0xf;
6481 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6485 store_reg_bx(env
, s
, rd
, tmp
);
6488 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6492 store_reg_bx(env
, s
, rd
, tmp
);
6495 if (set_cc
&& rd
== 15) {
6496 /* SUBS r15, ... is used for exception return. */
6500 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6501 gen_exception_return(s
, tmp
);
6504 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6506 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6508 store_reg_bx(env
, s
, rd
, tmp
);
6513 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6515 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6517 store_reg_bx(env
, s
, rd
, tmp
);
6521 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6523 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6525 store_reg_bx(env
, s
, rd
, tmp
);
6529 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6531 gen_add_carry(tmp
, tmp
, tmp2
);
6533 store_reg_bx(env
, s
, rd
, tmp
);
6537 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6539 gen_sub_carry(tmp
, tmp
, tmp2
);
6541 store_reg_bx(env
, s
, rd
, tmp
);
6545 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6547 gen_sub_carry(tmp
, tmp2
, tmp
);
6549 store_reg_bx(env
, s
, rd
, tmp
);
6553 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6560 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6567 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6573 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6578 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6582 store_reg_bx(env
, s
, rd
, tmp
);
6585 if (logic_cc
&& rd
== 15) {
6586 /* MOVS r15, ... is used for exception return. */
6590 gen_exception_return(s
, tmp2
);
6595 store_reg_bx(env
, s
, rd
, tmp2
);
6599 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
6603 store_reg_bx(env
, s
, rd
, tmp
);
6607 tcg_gen_not_i32(tmp2
, tmp2
);
6611 store_reg_bx(env
, s
, rd
, tmp2
);
6614 if (op1
!= 0x0f && op1
!= 0x0d) {
6618 /* other instructions */
6619 op1
= (insn
>> 24) & 0xf;
6623 /* multiplies, extra load/stores */
6624 sh
= (insn
>> 5) & 3;
6627 rd
= (insn
>> 16) & 0xf;
6628 rn
= (insn
>> 12) & 0xf;
6629 rs
= (insn
>> 8) & 0xf;
6631 op1
= (insn
>> 20) & 0xf;
6633 case 0: case 1: case 2: case 3: case 6:
6635 tmp
= load_reg(s
, rs
);
6636 tmp2
= load_reg(s
, rm
);
6637 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6639 if (insn
& (1 << 22)) {
6640 /* Subtract (mls) */
6642 tmp2
= load_reg(s
, rn
);
6643 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6645 } else if (insn
& (1 << 21)) {
6647 tmp2
= load_reg(s
, rn
);
6648 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6651 if (insn
& (1 << 20))
6653 store_reg(s
, rd
, tmp
);
6656 /* 64 bit mul double accumulate (UMAAL) */
6658 tmp
= load_reg(s
, rs
);
6659 tmp2
= load_reg(s
, rm
);
6660 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6661 gen_addq_lo(s
, tmp64
, rn
);
6662 gen_addq_lo(s
, tmp64
, rd
);
6663 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6664 tcg_temp_free_i64(tmp64
);
6666 case 8: case 9: case 10: case 11:
6667 case 12: case 13: case 14: case 15:
6668 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6669 tmp
= load_reg(s
, rs
);
6670 tmp2
= load_reg(s
, rm
);
6671 if (insn
& (1 << 22)) {
6672 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6674 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6676 if (insn
& (1 << 21)) { /* mult accumulate */
6677 gen_addq(s
, tmp64
, rn
, rd
);
6679 if (insn
& (1 << 20)) {
6680 gen_logicq_cc(tmp64
);
6682 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6683 tcg_temp_free_i64(tmp64
);
6689 rn
= (insn
>> 16) & 0xf;
6690 rd
= (insn
>> 12) & 0xf;
6691 if (insn
& (1 << 23)) {
6692 /* load/store exclusive */
6693 op1
= (insn
>> 21) & 0x3;
6698 addr
= tcg_temp_local_new_i32();
6699 load_reg_var(s
, addr
, rn
);
6700 if (insn
& (1 << 20)) {
6703 gen_load_exclusive(s
, rd
, 15, addr
, 2);
6705 case 1: /* ldrexd */
6706 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
6708 case 2: /* ldrexb */
6709 gen_load_exclusive(s
, rd
, 15, addr
, 0);
6711 case 3: /* ldrexh */
6712 gen_load_exclusive(s
, rd
, 15, addr
, 1);
6721 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
6723 case 1: /* strexd */
6724 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
6726 case 2: /* strexb */
6727 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
6729 case 3: /* strexh */
6730 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
6736 tcg_temp_free(addr
);
6738 /* SWP instruction */
6741 /* ??? This is not really atomic. However we know
6742 we never have multiple CPUs running in parallel,
6743 so it is good enough. */
6744 addr
= load_reg(s
, rn
);
6745 tmp
= load_reg(s
, rm
);
6746 if (insn
& (1 << 22)) {
6747 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6748 gen_st8(tmp
, addr
, IS_USER(s
));
6750 tmp2
= gen_ld32(addr
, IS_USER(s
));
6751 gen_st32(tmp
, addr
, IS_USER(s
));
6754 store_reg(s
, rd
, tmp2
);
6760 /* Misc load/store */
6761 rn
= (insn
>> 16) & 0xf;
6762 rd
= (insn
>> 12) & 0xf;
6763 addr
= load_reg(s
, rn
);
6764 if (insn
& (1 << 24))
6765 gen_add_datah_offset(s
, insn
, 0, addr
);
6767 if (insn
& (1 << 20)) {
6771 tmp
= gen_ld16u(addr
, IS_USER(s
));
6774 tmp
= gen_ld8s(addr
, IS_USER(s
));
6778 tmp
= gen_ld16s(addr
, IS_USER(s
));
6782 } else if (sh
& 2) {
6786 tmp
= load_reg(s
, rd
);
6787 gen_st32(tmp
, addr
, IS_USER(s
));
6788 tcg_gen_addi_i32(addr
, addr
, 4);
6789 tmp
= load_reg(s
, rd
+ 1);
6790 gen_st32(tmp
, addr
, IS_USER(s
));
6794 tmp
= gen_ld32(addr
, IS_USER(s
));
6795 store_reg(s
, rd
, tmp
);
6796 tcg_gen_addi_i32(addr
, addr
, 4);
6797 tmp
= gen_ld32(addr
, IS_USER(s
));
6801 address_offset
= -4;
6804 tmp
= load_reg(s
, rd
);
6805 gen_st16(tmp
, addr
, IS_USER(s
));
6808 /* Perform base writeback before the loaded value to
6809 ensure correct behavior with overlapping index registers.
6810 ldrd with base writeback is is undefined if the
6811 destination and index registers overlap. */
6812 if (!(insn
& (1 << 24))) {
6813 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6814 store_reg(s
, rn
, addr
);
6815 } else if (insn
& (1 << 21)) {
6817 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6818 store_reg(s
, rn
, addr
);
6823 /* Complete the load. */
6824 store_reg(s
, rd
, tmp
);
6833 if (insn
& (1 << 4)) {
6835 /* Armv6 Media instructions. */
6837 rn
= (insn
>> 16) & 0xf;
6838 rd
= (insn
>> 12) & 0xf;
6839 rs
= (insn
>> 8) & 0xf;
6840 switch ((insn
>> 23) & 3) {
6841 case 0: /* Parallel add/subtract. */
6842 op1
= (insn
>> 20) & 7;
6843 tmp
= load_reg(s
, rn
);
6844 tmp2
= load_reg(s
, rm
);
6845 sh
= (insn
>> 5) & 7;
6846 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6848 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6850 store_reg(s
, rd
, tmp
);
6853 if ((insn
& 0x00700020) == 0) {
6854 /* Halfword pack. */
6855 tmp
= load_reg(s
, rn
);
6856 tmp2
= load_reg(s
, rm
);
6857 shift
= (insn
>> 7) & 0x1f;
6858 if (insn
& (1 << 6)) {
6862 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6863 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6864 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6868 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6869 tcg_gen_ext16u_i32(tmp
, tmp
);
6870 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6872 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6874 store_reg(s
, rd
, tmp
);
6875 } else if ((insn
& 0x00200020) == 0x00200000) {
6877 tmp
= load_reg(s
, rm
);
6878 shift
= (insn
>> 7) & 0x1f;
6879 if (insn
& (1 << 6)) {
6882 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6884 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6886 sh
= (insn
>> 16) & 0x1f;
6888 tmp2
= tcg_const_i32(sh
);
6889 if (insn
& (1 << 22))
6890 gen_helper_usat(tmp
, tmp
, tmp2
);
6892 gen_helper_ssat(tmp
, tmp
, tmp2
);
6893 tcg_temp_free_i32(tmp2
);
6895 store_reg(s
, rd
, tmp
);
6896 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6898 tmp
= load_reg(s
, rm
);
6899 sh
= (insn
>> 16) & 0x1f;
6901 tmp2
= tcg_const_i32(sh
);
6902 if (insn
& (1 << 22))
6903 gen_helper_usat16(tmp
, tmp
, tmp2
);
6905 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6906 tcg_temp_free_i32(tmp2
);
6908 store_reg(s
, rd
, tmp
);
6909 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6911 tmp
= load_reg(s
, rn
);
6912 tmp2
= load_reg(s
, rm
);
6914 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6915 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6918 store_reg(s
, rd
, tmp
);
6919 } else if ((insn
& 0x000003e0) == 0x00000060) {
6920 tmp
= load_reg(s
, rm
);
6921 shift
= (insn
>> 10) & 3;
6922 /* ??? In many cases it's not neccessary to do a
6923 rotate, a shift is sufficient. */
6925 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6926 op1
= (insn
>> 20) & 7;
6928 case 0: gen_sxtb16(tmp
); break;
6929 case 2: gen_sxtb(tmp
); break;
6930 case 3: gen_sxth(tmp
); break;
6931 case 4: gen_uxtb16(tmp
); break;
6932 case 6: gen_uxtb(tmp
); break;
6933 case 7: gen_uxth(tmp
); break;
6934 default: goto illegal_op
;
6937 tmp2
= load_reg(s
, rn
);
6938 if ((op1
& 3) == 0) {
6939 gen_add16(tmp
, tmp2
);
6941 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6945 store_reg(s
, rd
, tmp
);
6946 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6948 tmp
= load_reg(s
, rm
);
6949 if (insn
& (1 << 22)) {
6950 if (insn
& (1 << 7)) {
6954 gen_helper_rbit(tmp
, tmp
);
6957 if (insn
& (1 << 7))
6960 tcg_gen_bswap32_i32(tmp
, tmp
);
6962 store_reg(s
, rd
, tmp
);
6967 case 2: /* Multiplies (Type 3). */
6968 tmp
= load_reg(s
, rm
);
6969 tmp2
= load_reg(s
, rs
);
6970 if (insn
& (1 << 20)) {
6971 /* Signed multiply most significant [accumulate].
6972 (SMMUL, SMMLA, SMMLS) */
6973 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6976 tmp
= load_reg(s
, rd
);
6977 if (insn
& (1 << 6)) {
6978 tmp64
= gen_subq_msw(tmp64
, tmp
);
6980 tmp64
= gen_addq_msw(tmp64
, tmp
);
6983 if (insn
& (1 << 5)) {
6984 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6986 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6988 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6989 tcg_temp_free_i64(tmp64
);
6990 store_reg(s
, rn
, tmp
);
6992 if (insn
& (1 << 5))
6993 gen_swap_half(tmp2
);
6994 gen_smul_dual(tmp
, tmp2
);
6995 /* This addition cannot overflow. */
6996 if (insn
& (1 << 6)) {
6997 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6999 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7002 if (insn
& (1 << 22)) {
7003 /* smlald, smlsld */
7004 tmp64
= tcg_temp_new_i64();
7005 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7007 gen_addq(s
, tmp64
, rd
, rn
);
7008 gen_storeq_reg(s
, rd
, rn
, tmp64
);
7009 tcg_temp_free_i64(tmp64
);
7011 /* smuad, smusd, smlad, smlsd */
7014 tmp2
= load_reg(s
, rd
);
7015 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7018 store_reg(s
, rn
, tmp
);
7023 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
7025 case 0: /* Unsigned sum of absolute differences. */
7027 tmp
= load_reg(s
, rm
);
7028 tmp2
= load_reg(s
, rs
);
7029 gen_helper_usad8(tmp
, tmp
, tmp2
);
7032 tmp2
= load_reg(s
, rd
);
7033 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7036 store_reg(s
, rn
, tmp
);
7038 case 0x20: case 0x24: case 0x28: case 0x2c:
7039 /* Bitfield insert/clear. */
7041 shift
= (insn
>> 7) & 0x1f;
7042 i
= (insn
>> 16) & 0x1f;
7046 tcg_gen_movi_i32(tmp
, 0);
7048 tmp
= load_reg(s
, rm
);
7051 tmp2
= load_reg(s
, rd
);
7052 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
7055 store_reg(s
, rd
, tmp
);
7057 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7058 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7060 tmp
= load_reg(s
, rm
);
7061 shift
= (insn
>> 7) & 0x1f;
7062 i
= ((insn
>> 16) & 0x1f) + 1;
7067 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7069 gen_sbfx(tmp
, shift
, i
);
7072 store_reg(s
, rd
, tmp
);
7082 /* Check for undefined extension instructions
7083 * per the ARM Bible IE:
7084 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7086 sh
= (0xf << 20) | (0xf << 4);
7087 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7091 /* load/store byte/word */
7092 rn
= (insn
>> 16) & 0xf;
7093 rd
= (insn
>> 12) & 0xf;
7094 tmp2
= load_reg(s
, rn
);
7095 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7096 if (insn
& (1 << 24))
7097 gen_add_data_offset(s
, insn
, tmp2
);
7098 if (insn
& (1 << 20)) {
7100 if (insn
& (1 << 22)) {
7101 tmp
= gen_ld8u(tmp2
, i
);
7103 tmp
= gen_ld32(tmp2
, i
);
7107 tmp
= load_reg(s
, rd
);
7108 if (insn
& (1 << 22))
7109 gen_st8(tmp
, tmp2
, i
);
7111 gen_st32(tmp
, tmp2
, i
);
7113 if (!(insn
& (1 << 24))) {
7114 gen_add_data_offset(s
, insn
, tmp2
);
7115 store_reg(s
, rn
, tmp2
);
7116 } else if (insn
& (1 << 21)) {
7117 store_reg(s
, rn
, tmp2
);
7121 if (insn
& (1 << 20)) {
7122 /* Complete the load. */
7126 store_reg(s
, rd
, tmp
);
7132 int j
, n
, user
, loaded_base
;
7134 /* load/store multiple words */
7135 /* XXX: store correct base if write back */
7137 if (insn
& (1 << 22)) {
7139 goto illegal_op
; /* only usable in supervisor mode */
7141 if ((insn
& (1 << 15)) == 0)
7144 rn
= (insn
>> 16) & 0xf;
7145 addr
= load_reg(s
, rn
);
7147 /* compute total size */
7149 TCGV_UNUSED(loaded_var
);
7152 if (insn
& (1 << i
))
7155 /* XXX: test invalid n == 0 case ? */
7156 if (insn
& (1 << 23)) {
7157 if (insn
& (1 << 24)) {
7159 tcg_gen_addi_i32(addr
, addr
, 4);
7161 /* post increment */
7164 if (insn
& (1 << 24)) {
7166 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7168 /* post decrement */
7170 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7175 if (insn
& (1 << i
)) {
7176 if (insn
& (1 << 20)) {
7178 tmp
= gen_ld32(addr
, IS_USER(s
));
7182 tmp2
= tcg_const_i32(i
);
7183 gen_helper_set_user_reg(tmp2
, tmp
);
7184 tcg_temp_free_i32(tmp2
);
7186 } else if (i
== rn
) {
7190 store_reg(s
, i
, tmp
);
7195 /* special case: r15 = PC + 8 */
7196 val
= (long)s
->pc
+ 4;
7198 tcg_gen_movi_i32(tmp
, val
);
7201 tmp2
= tcg_const_i32(i
);
7202 gen_helper_get_user_reg(tmp
, tmp2
);
7203 tcg_temp_free_i32(tmp2
);
7205 tmp
= load_reg(s
, i
);
7207 gen_st32(tmp
, addr
, IS_USER(s
));
7210 /* no need to add after the last transfer */
7212 tcg_gen_addi_i32(addr
, addr
, 4);
7215 if (insn
& (1 << 21)) {
7217 if (insn
& (1 << 23)) {
7218 if (insn
& (1 << 24)) {
7221 /* post increment */
7222 tcg_gen_addi_i32(addr
, addr
, 4);
7225 if (insn
& (1 << 24)) {
7228 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7230 /* post decrement */
7231 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7234 store_reg(s
, rn
, addr
);
7239 store_reg(s
, rn
, loaded_var
);
7241 if ((insn
& (1 << 22)) && !user
) {
7242 /* Restore CPSR from SPSR. */
7243 tmp
= load_cpu_field(spsr
);
7244 gen_set_cpsr(tmp
, 0xffffffff);
7246 s
->is_jmp
= DISAS_UPDATE
;
7255 /* branch (and link) */
7256 val
= (int32_t)s
->pc
;
7257 if (insn
& (1 << 24)) {
7259 tcg_gen_movi_i32(tmp
, val
);
7260 store_reg(s
, 14, tmp
);
7262 offset
= (((int32_t)insn
<< 8) >> 8);
7263 val
+= (offset
<< 2) + 4;
7271 if (disas_coproc_insn(env
, s
, insn
))
7276 gen_set_pc_im(s
->pc
);
7277 s
->is_jmp
= DISAS_SWI
;
7281 gen_set_condexec(s
);
7282 gen_set_pc_im(s
->pc
- 4);
7283 gen_exception(EXCP_UDEF
);
7284 s
->is_jmp
= DISAS_JUMP
;
7290 /* Return true if this is a Thumb-2 logical op. */
7292 thumb2_logic_op(int op
)
7297 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7298 then set condition code flags based on the result of the operation.
7299 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7300 to the high bit of T1.
7301 Returns zero if the opcode is valid. */
7304 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7311 tcg_gen_and_i32(t0
, t0
, t1
);
7315 tcg_gen_andc_i32(t0
, t0
, t1
);
7319 tcg_gen_or_i32(t0
, t0
, t1
);
7323 tcg_gen_not_i32(t1
, t1
);
7324 tcg_gen_or_i32(t0
, t0
, t1
);
7328 tcg_gen_xor_i32(t0
, t0
, t1
);
7333 gen_helper_add_cc(t0
, t0
, t1
);
7335 tcg_gen_add_i32(t0
, t0
, t1
);
7339 gen_helper_adc_cc(t0
, t0
, t1
);
7345 gen_helper_sbc_cc(t0
, t0
, t1
);
7347 gen_sub_carry(t0
, t0
, t1
);
7351 gen_helper_sub_cc(t0
, t0
, t1
);
7353 tcg_gen_sub_i32(t0
, t0
, t1
);
7357 gen_helper_sub_cc(t0
, t1
, t0
);
7359 tcg_gen_sub_i32(t0
, t1
, t0
);
7361 default: /* 5, 6, 7, 9, 12, 15. */
7367 gen_set_CF_bit31(t1
);
7372 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7374 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7376 uint32_t insn
, imm
, shift
, offset
;
7377 uint32_t rd
, rn
, rm
, rs
;
7388 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7389 || arm_feature (env
, ARM_FEATURE_M
))) {
7390 /* Thumb-1 cores may need to treat bl and blx as a pair of
7391 16-bit instructions to get correct prefetch abort behavior. */
7393 if ((insn
& (1 << 12)) == 0) {
7394 /* Second half of blx. */
7395 offset
= ((insn
& 0x7ff) << 1);
7396 tmp
= load_reg(s
, 14);
7397 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7398 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7401 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7402 store_reg(s
, 14, tmp2
);
7406 if (insn
& (1 << 11)) {
7407 /* Second half of bl. */
7408 offset
= ((insn
& 0x7ff) << 1) | 1;
7409 tmp
= load_reg(s
, 14);
7410 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7413 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7414 store_reg(s
, 14, tmp2
);
7418 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7419 /* Instruction spans a page boundary. Implement it as two
7420 16-bit instructions in case the second half causes an
7422 offset
= ((int32_t)insn
<< 21) >> 9;
7423 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7426 /* Fall through to 32-bit decode. */
7429 insn
= lduw_code(s
->pc
);
7431 insn
|= (uint32_t)insn_hw1
<< 16;
7433 if ((insn
& 0xf800e800) != 0xf000e800) {
7437 rn
= (insn
>> 16) & 0xf;
7438 rs
= (insn
>> 12) & 0xf;
7439 rd
= (insn
>> 8) & 0xf;
7441 switch ((insn
>> 25) & 0xf) {
7442 case 0: case 1: case 2: case 3:
7443 /* 16-bit instructions. Should never happen. */
7446 if (insn
& (1 << 22)) {
7447 /* Other load/store, table branch. */
7448 if (insn
& 0x01200000) {
7449 /* Load/store doubleword. */
7452 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7454 addr
= load_reg(s
, rn
);
7456 offset
= (insn
& 0xff) * 4;
7457 if ((insn
& (1 << 23)) == 0)
7459 if (insn
& (1 << 24)) {
7460 tcg_gen_addi_i32(addr
, addr
, offset
);
7463 if (insn
& (1 << 20)) {
7465 tmp
= gen_ld32(addr
, IS_USER(s
));
7466 store_reg(s
, rs
, tmp
);
7467 tcg_gen_addi_i32(addr
, addr
, 4);
7468 tmp
= gen_ld32(addr
, IS_USER(s
));
7469 store_reg(s
, rd
, tmp
);
7472 tmp
= load_reg(s
, rs
);
7473 gen_st32(tmp
, addr
, IS_USER(s
));
7474 tcg_gen_addi_i32(addr
, addr
, 4);
7475 tmp
= load_reg(s
, rd
);
7476 gen_st32(tmp
, addr
, IS_USER(s
));
7478 if (insn
& (1 << 21)) {
7479 /* Base writeback. */
7482 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7483 store_reg(s
, rn
, addr
);
7487 } else if ((insn
& (1 << 23)) == 0) {
7488 /* Load/store exclusive word. */
7489 addr
= tcg_temp_local_new();
7490 load_reg_var(s
, addr
, rn
);
7491 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
7492 if (insn
& (1 << 20)) {
7493 gen_load_exclusive(s
, rs
, 15, addr
, 2);
7495 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
7497 tcg_temp_free(addr
);
7498 } else if ((insn
& (1 << 6)) == 0) {
7502 tcg_gen_movi_i32(addr
, s
->pc
);
7504 addr
= load_reg(s
, rn
);
7506 tmp
= load_reg(s
, rm
);
7507 tcg_gen_add_i32(addr
, addr
, tmp
);
7508 if (insn
& (1 << 4)) {
7510 tcg_gen_add_i32(addr
, addr
, tmp
);
7512 tmp
= gen_ld16u(addr
, IS_USER(s
));
7515 tmp
= gen_ld8u(addr
, IS_USER(s
));
7518 tcg_gen_shli_i32(tmp
, tmp
, 1);
7519 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7520 store_reg(s
, 15, tmp
);
7522 /* Load/store exclusive byte/halfword/doubleword. */
7524 op
= (insn
>> 4) & 0x3;
7528 addr
= tcg_temp_local_new();
7529 load_reg_var(s
, addr
, rn
);
7530 if (insn
& (1 << 20)) {
7531 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
7533 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
7535 tcg_temp_free(addr
);
7538 /* Load/store multiple, RFE, SRS. */
7539 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7540 /* Not available in user mode. */
7543 if (insn
& (1 << 20)) {
7545 addr
= load_reg(s
, rn
);
7546 if ((insn
& (1 << 24)) == 0)
7547 tcg_gen_addi_i32(addr
, addr
, -8);
7548 /* Load PC into tmp and CPSR into tmp2. */
7549 tmp
= gen_ld32(addr
, 0);
7550 tcg_gen_addi_i32(addr
, addr
, 4);
7551 tmp2
= gen_ld32(addr
, 0);
7552 if (insn
& (1 << 21)) {
7553 /* Base writeback. */
7554 if (insn
& (1 << 24)) {
7555 tcg_gen_addi_i32(addr
, addr
, 4);
7557 tcg_gen_addi_i32(addr
, addr
, -4);
7559 store_reg(s
, rn
, addr
);
7563 gen_rfe(s
, tmp
, tmp2
);
7568 tmp
= tcg_const_i32(op
);
7569 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7570 tcg_temp_free_i32(tmp
);
7571 if ((insn
& (1 << 24)) == 0) {
7572 tcg_gen_addi_i32(addr
, addr
, -8);
7574 tmp
= load_reg(s
, 14);
7575 gen_st32(tmp
, addr
, 0);
7576 tcg_gen_addi_i32(addr
, addr
, 4);
7578 gen_helper_cpsr_read(tmp
);
7579 gen_st32(tmp
, addr
, 0);
7580 if (insn
& (1 << 21)) {
7581 if ((insn
& (1 << 24)) == 0) {
7582 tcg_gen_addi_i32(addr
, addr
, -4);
7584 tcg_gen_addi_i32(addr
, addr
, 4);
7586 tmp
= tcg_const_i32(op
);
7587 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7588 tcg_temp_free_i32(tmp
);
7595 /* Load/store multiple. */
7596 addr
= load_reg(s
, rn
);
7598 for (i
= 0; i
< 16; i
++) {
7599 if (insn
& (1 << i
))
7602 if (insn
& (1 << 24)) {
7603 tcg_gen_addi_i32(addr
, addr
, -offset
);
7606 for (i
= 0; i
< 16; i
++) {
7607 if ((insn
& (1 << i
)) == 0)
7609 if (insn
& (1 << 20)) {
7611 tmp
= gen_ld32(addr
, IS_USER(s
));
7615 store_reg(s
, i
, tmp
);
7619 tmp
= load_reg(s
, i
);
7620 gen_st32(tmp
, addr
, IS_USER(s
));
7622 tcg_gen_addi_i32(addr
, addr
, 4);
7624 if (insn
& (1 << 21)) {
7625 /* Base register writeback. */
7626 if (insn
& (1 << 24)) {
7627 tcg_gen_addi_i32(addr
, addr
, -offset
);
7629 /* Fault if writeback register is in register list. */
7630 if (insn
& (1 << rn
))
7632 store_reg(s
, rn
, addr
);
7641 op
= (insn
>> 21) & 0xf;
7643 /* Halfword pack. */
7644 tmp
= load_reg(s
, rn
);
7645 tmp2
= load_reg(s
, rm
);
7646 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
7647 if (insn
& (1 << 5)) {
7651 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7652 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7653 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7657 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7658 tcg_gen_ext16u_i32(tmp
, tmp
);
7659 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7661 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7663 store_reg(s
, rd
, tmp
);
7665 /* Data processing register constant shift. */
7668 tcg_gen_movi_i32(tmp
, 0);
7670 tmp
= load_reg(s
, rn
);
7672 tmp2
= load_reg(s
, rm
);
7674 shiftop
= (insn
>> 4) & 3;
7675 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7676 conds
= (insn
& (1 << 20)) != 0;
7677 logic_cc
= (conds
&& thumb2_logic_op(op
));
7678 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7679 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7683 store_reg(s
, rd
, tmp
);
7689 case 13: /* Misc data processing. */
7690 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7691 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7694 case 0: /* Register controlled shift. */
7695 tmp
= load_reg(s
, rn
);
7696 tmp2
= load_reg(s
, rm
);
7697 if ((insn
& 0x70) != 0)
7699 op
= (insn
>> 21) & 3;
7700 logic_cc
= (insn
& (1 << 20)) != 0;
7701 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7704 store_reg_bx(env
, s
, rd
, tmp
);
7706 case 1: /* Sign/zero extend. */
7707 tmp
= load_reg(s
, rm
);
7708 shift
= (insn
>> 4) & 3;
7709 /* ??? In many cases it's not neccessary to do a
7710 rotate, a shift is sufficient. */
7712 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7713 op
= (insn
>> 20) & 7;
7715 case 0: gen_sxth(tmp
); break;
7716 case 1: gen_uxth(tmp
); break;
7717 case 2: gen_sxtb16(tmp
); break;
7718 case 3: gen_uxtb16(tmp
); break;
7719 case 4: gen_sxtb(tmp
); break;
7720 case 5: gen_uxtb(tmp
); break;
7721 default: goto illegal_op
;
7724 tmp2
= load_reg(s
, rn
);
7725 if ((op
>> 1) == 1) {
7726 gen_add16(tmp
, tmp2
);
7728 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7732 store_reg(s
, rd
, tmp
);
7734 case 2: /* SIMD add/subtract. */
7735 op
= (insn
>> 20) & 7;
7736 shift
= (insn
>> 4) & 7;
7737 if ((op
& 3) == 3 || (shift
& 3) == 3)
7739 tmp
= load_reg(s
, rn
);
7740 tmp2
= load_reg(s
, rm
);
7741 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7743 store_reg(s
, rd
, tmp
);
7745 case 3: /* Other data processing. */
7746 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7748 /* Saturating add/subtract. */
7749 tmp
= load_reg(s
, rn
);
7750 tmp2
= load_reg(s
, rm
);
7752 gen_helper_double_saturate(tmp
, tmp
);
7754 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7756 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7759 tmp
= load_reg(s
, rn
);
7761 case 0x0a: /* rbit */
7762 gen_helper_rbit(tmp
, tmp
);
7764 case 0x08: /* rev */
7765 tcg_gen_bswap32_i32(tmp
, tmp
);
7767 case 0x09: /* rev16 */
7770 case 0x0b: /* revsh */
7773 case 0x10: /* sel */
7774 tmp2
= load_reg(s
, rm
);
7776 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7777 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7781 case 0x18: /* clz */
7782 gen_helper_clz(tmp
, tmp
);
7788 store_reg(s
, rd
, tmp
);
7790 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7791 op
= (insn
>> 4) & 0xf;
7792 tmp
= load_reg(s
, rn
);
7793 tmp2
= load_reg(s
, rm
);
7794 switch ((insn
>> 20) & 7) {
7795 case 0: /* 32 x 32 -> 32 */
7796 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7799 tmp2
= load_reg(s
, rs
);
7801 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7803 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7807 case 1: /* 16 x 16 -> 32 */
7808 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7811 tmp2
= load_reg(s
, rs
);
7812 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7816 case 2: /* Dual multiply add. */
7817 case 4: /* Dual multiply subtract. */
7819 gen_swap_half(tmp2
);
7820 gen_smul_dual(tmp
, tmp2
);
7821 /* This addition cannot overflow. */
7822 if (insn
& (1 << 22)) {
7823 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7825 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7830 tmp2
= load_reg(s
, rs
);
7831 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7835 case 3: /* 32 * 16 -> 32msb */
7837 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7840 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7841 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7843 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7844 tcg_temp_free_i64(tmp64
);
7847 tmp2
= load_reg(s
, rs
);
7848 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7852 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7853 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7855 tmp
= load_reg(s
, rs
);
7856 if (insn
& (1 << 20)) {
7857 tmp64
= gen_addq_msw(tmp64
, tmp
);
7859 tmp64
= gen_subq_msw(tmp64
, tmp
);
7862 if (insn
& (1 << 4)) {
7863 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
7865 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
7867 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7868 tcg_temp_free_i64(tmp64
);
7870 case 7: /* Unsigned sum of absolute differences. */
7871 gen_helper_usad8(tmp
, tmp
, tmp2
);
7874 tmp2
= load_reg(s
, rs
);
7875 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7880 store_reg(s
, rd
, tmp
);
7882 case 6: case 7: /* 64-bit multiply, Divide. */
7883 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7884 tmp
= load_reg(s
, rn
);
7885 tmp2
= load_reg(s
, rm
);
7886 if ((op
& 0x50) == 0x10) {
7888 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7891 gen_helper_udiv(tmp
, tmp
, tmp2
);
7893 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7895 store_reg(s
, rd
, tmp
);
7896 } else if ((op
& 0xe) == 0xc) {
7897 /* Dual multiply accumulate long. */
7899 gen_swap_half(tmp2
);
7900 gen_smul_dual(tmp
, tmp2
);
7902 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7904 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7908 tmp64
= tcg_temp_new_i64();
7909 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7911 gen_addq(s
, tmp64
, rs
, rd
);
7912 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7913 tcg_temp_free_i64(tmp64
);
7916 /* Unsigned 64-bit multiply */
7917 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7921 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7923 tmp64
= tcg_temp_new_i64();
7924 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7927 /* Signed 64-bit multiply */
7928 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7933 gen_addq_lo(s
, tmp64
, rs
);
7934 gen_addq_lo(s
, tmp64
, rd
);
7935 } else if (op
& 0x40) {
7936 /* 64-bit accumulate. */
7937 gen_addq(s
, tmp64
, rs
, rd
);
7939 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7940 tcg_temp_free_i64(tmp64
);
7945 case 6: case 7: case 14: case 15:
7947 if (((insn
>> 24) & 3) == 3) {
7948 /* Translate into the equivalent ARM encoding. */
7949 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7950 if (disas_neon_data_insn(env
, s
, insn
))
7953 if (insn
& (1 << 28))
7955 if (disas_coproc_insn (env
, s
, insn
))
7959 case 8: case 9: case 10: case 11:
7960 if (insn
& (1 << 15)) {
7961 /* Branches, misc control. */
7962 if (insn
& 0x5000) {
7963 /* Unconditional branch. */
7964 /* signextend(hw1[10:0]) -> offset[:12]. */
7965 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7966 /* hw1[10:0] -> offset[11:1]. */
7967 offset
|= (insn
& 0x7ff) << 1;
7968 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7969 offset[24:22] already have the same value because of the
7970 sign extension above. */
7971 offset
^= ((~insn
) & (1 << 13)) << 10;
7972 offset
^= ((~insn
) & (1 << 11)) << 11;
7974 if (insn
& (1 << 14)) {
7975 /* Branch and link. */
7976 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7980 if (insn
& (1 << 12)) {
7985 offset
&= ~(uint32_t)2;
7986 gen_bx_im(s
, offset
);
7988 } else if (((insn
>> 23) & 7) == 7) {
7990 if (insn
& (1 << 13))
7993 if (insn
& (1 << 26)) {
7994 /* Secure monitor call (v6Z) */
7995 goto illegal_op
; /* not implemented. */
7997 op
= (insn
>> 20) & 7;
7999 case 0: /* msr cpsr. */
8001 tmp
= load_reg(s
, rn
);
8002 addr
= tcg_const_i32(insn
& 0xff);
8003 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8004 tcg_temp_free_i32(addr
);
8010 case 1: /* msr spsr. */
8013 tmp
= load_reg(s
, rn
);
8015 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
8019 case 2: /* cps, nop-hint. */
8020 if (((insn
>> 8) & 7) == 0) {
8021 gen_nop_hint(s
, insn
& 0xff);
8023 /* Implemented as NOP in user mode. */
8028 if (insn
& (1 << 10)) {
8029 if (insn
& (1 << 7))
8031 if (insn
& (1 << 6))
8033 if (insn
& (1 << 5))
8035 if (insn
& (1 << 9))
8036 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8038 if (insn
& (1 << 8)) {
8040 imm
|= (insn
& 0x1f);
8043 gen_set_psr_im(s
, offset
, 0, imm
);
8046 case 3: /* Special control operations. */
8048 op
= (insn
>> 4) & 0xf;
8056 /* These execute as NOPs. */
8063 /* Trivial implementation equivalent to bx. */
8064 tmp
= load_reg(s
, rn
);
8067 case 5: /* Exception return. */
8071 if (rn
!= 14 || rd
!= 15) {
8074 tmp
= load_reg(s
, rn
);
8075 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8076 gen_exception_return(s
, tmp
);
8078 case 6: /* mrs cpsr. */
8081 addr
= tcg_const_i32(insn
& 0xff);
8082 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8083 tcg_temp_free_i32(addr
);
8085 gen_helper_cpsr_read(tmp
);
8087 store_reg(s
, rd
, tmp
);
8089 case 7: /* mrs spsr. */
8090 /* Not accessible in user mode. */
8091 if (IS_USER(s
) || IS_M(env
))
8093 tmp
= load_cpu_field(spsr
);
8094 store_reg(s
, rd
, tmp
);
8099 /* Conditional branch. */
8100 op
= (insn
>> 22) & 0xf;
8101 /* Generate a conditional jump to next instruction. */
8102 s
->condlabel
= gen_new_label();
8103 gen_test_cc(op
^ 1, s
->condlabel
);
8106 /* offset[11:1] = insn[10:0] */
8107 offset
= (insn
& 0x7ff) << 1;
8108 /* offset[17:12] = insn[21:16]. */
8109 offset
|= (insn
& 0x003f0000) >> 4;
8110 /* offset[31:20] = insn[26]. */
8111 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8112 /* offset[18] = insn[13]. */
8113 offset
|= (insn
& (1 << 13)) << 5;
8114 /* offset[19] = insn[11]. */
8115 offset
|= (insn
& (1 << 11)) << 8;
8117 /* jump to the offset */
8118 gen_jmp(s
, s
->pc
+ offset
);
8121 /* Data processing immediate. */
8122 if (insn
& (1 << 25)) {
8123 if (insn
& (1 << 24)) {
8124 if (insn
& (1 << 20))
8126 /* Bitfield/Saturate. */
8127 op
= (insn
>> 21) & 7;
8129 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8132 tcg_gen_movi_i32(tmp
, 0);
8134 tmp
= load_reg(s
, rn
);
8137 case 2: /* Signed bitfield extract. */
8139 if (shift
+ imm
> 32)
8142 gen_sbfx(tmp
, shift
, imm
);
8144 case 6: /* Unsigned bitfield extract. */
8146 if (shift
+ imm
> 32)
8149 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8151 case 3: /* Bitfield insert/clear. */
8154 imm
= imm
+ 1 - shift
;
8156 tmp2
= load_reg(s
, rd
);
8157 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
8163 default: /* Saturate. */
8166 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8168 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8170 tmp2
= tcg_const_i32(imm
);
8173 if ((op
& 1) && shift
== 0)
8174 gen_helper_usat16(tmp
, tmp
, tmp2
);
8176 gen_helper_usat(tmp
, tmp
, tmp2
);
8179 if ((op
& 1) && shift
== 0)
8180 gen_helper_ssat16(tmp
, tmp
, tmp2
);
8182 gen_helper_ssat(tmp
, tmp
, tmp2
);
8184 tcg_temp_free_i32(tmp2
);
8187 store_reg(s
, rd
, tmp
);
8189 imm
= ((insn
& 0x04000000) >> 15)
8190 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8191 if (insn
& (1 << 22)) {
8192 /* 16-bit immediate. */
8193 imm
|= (insn
>> 4) & 0xf000;
8194 if (insn
& (1 << 23)) {
8196 tmp
= load_reg(s
, rd
);
8197 tcg_gen_ext16u_i32(tmp
, tmp
);
8198 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8202 tcg_gen_movi_i32(tmp
, imm
);
8205 /* Add/sub 12-bit immediate. */
8207 offset
= s
->pc
& ~(uint32_t)3;
8208 if (insn
& (1 << 23))
8213 tcg_gen_movi_i32(tmp
, offset
);
8215 tmp
= load_reg(s
, rn
);
8216 if (insn
& (1 << 23))
8217 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8219 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8222 store_reg(s
, rd
, tmp
);
8225 int shifter_out
= 0;
8226 /* modified 12-bit immediate. */
8227 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8228 imm
= (insn
& 0xff);
8231 /* Nothing to do. */
8233 case 1: /* 00XY00XY */
8236 case 2: /* XY00XY00 */
8240 case 3: /* XYXYXYXY */
8244 default: /* Rotated constant. */
8245 shift
= (shift
<< 1) | (imm
>> 7);
8247 imm
= imm
<< (32 - shift
);
8252 tcg_gen_movi_i32(tmp2
, imm
);
8253 rn
= (insn
>> 16) & 0xf;
8256 tcg_gen_movi_i32(tmp
, 0);
8258 tmp
= load_reg(s
, rn
);
8260 op
= (insn
>> 21) & 0xf;
8261 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8262 shifter_out
, tmp
, tmp2
))
8265 rd
= (insn
>> 8) & 0xf;
8267 store_reg(s
, rd
, tmp
);
8274 case 12: /* Load/store single data item. */
8279 if ((insn
& 0x01100000) == 0x01000000) {
8280 if (disas_neon_ls_insn(env
, s
, insn
))
8288 /* s->pc has already been incremented by 4. */
8289 imm
= s
->pc
& 0xfffffffc;
8290 if (insn
& (1 << 23))
8291 imm
+= insn
& 0xfff;
8293 imm
-= insn
& 0xfff;
8294 tcg_gen_movi_i32(addr
, imm
);
8296 addr
= load_reg(s
, rn
);
8297 if (insn
& (1 << 23)) {
8298 /* Positive offset. */
8300 tcg_gen_addi_i32(addr
, addr
, imm
);
8302 op
= (insn
>> 8) & 7;
8305 case 0: case 8: /* Shifted Register. */
8306 shift
= (insn
>> 4) & 0xf;
8309 tmp
= load_reg(s
, rm
);
8311 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8312 tcg_gen_add_i32(addr
, addr
, tmp
);
8315 case 4: /* Negative offset. */
8316 tcg_gen_addi_i32(addr
, addr
, -imm
);
8318 case 6: /* User privilege. */
8319 tcg_gen_addi_i32(addr
, addr
, imm
);
8322 case 1: /* Post-decrement. */
8325 case 3: /* Post-increment. */
8329 case 5: /* Pre-decrement. */
8332 case 7: /* Pre-increment. */
8333 tcg_gen_addi_i32(addr
, addr
, imm
);
8341 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8342 if (insn
& (1 << 20)) {
8344 if (rs
== 15 && op
!= 2) {
8347 /* Memory hint. Implemented as NOP. */
8350 case 0: tmp
= gen_ld8u(addr
, user
); break;
8351 case 4: tmp
= gen_ld8s(addr
, user
); break;
8352 case 1: tmp
= gen_ld16u(addr
, user
); break;
8353 case 5: tmp
= gen_ld16s(addr
, user
); break;
8354 case 2: tmp
= gen_ld32(addr
, user
); break;
8355 default: goto illegal_op
;
8360 store_reg(s
, rs
, tmp
);
8367 tmp
= load_reg(s
, rs
);
8369 case 0: gen_st8(tmp
, addr
, user
); break;
8370 case 1: gen_st16(tmp
, addr
, user
); break;
8371 case 2: gen_st32(tmp
, addr
, user
); break;
8372 default: goto illegal_op
;
8376 tcg_gen_addi_i32(addr
, addr
, imm
);
8378 store_reg(s
, rn
, addr
);
8392 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8394 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8401 if (s
->condexec_mask
) {
8402 cond
= s
->condexec_cond
;
8403 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
8404 s
->condlabel
= gen_new_label();
8405 gen_test_cc(cond
^ 1, s
->condlabel
);
8410 insn
= lduw_code(s
->pc
);
8413 switch (insn
>> 12) {
8417 op
= (insn
>> 11) & 3;
8420 rn
= (insn
>> 3) & 7;
8421 tmp
= load_reg(s
, rn
);
8422 if (insn
& (1 << 10)) {
8425 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8428 rm
= (insn
>> 6) & 7;
8429 tmp2
= load_reg(s
, rm
);
8431 if (insn
& (1 << 9)) {
8432 if (s
->condexec_mask
)
8433 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8435 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8437 if (s
->condexec_mask
)
8438 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8440 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8443 store_reg(s
, rd
, tmp
);
8445 /* shift immediate */
8446 rm
= (insn
>> 3) & 7;
8447 shift
= (insn
>> 6) & 0x1f;
8448 tmp
= load_reg(s
, rm
);
8449 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8450 if (!s
->condexec_mask
)
8452 store_reg(s
, rd
, tmp
);
8456 /* arithmetic large immediate */
8457 op
= (insn
>> 11) & 3;
8458 rd
= (insn
>> 8) & 0x7;
8459 if (op
== 0) { /* mov */
8461 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8462 if (!s
->condexec_mask
)
8464 store_reg(s
, rd
, tmp
);
8466 tmp
= load_reg(s
, rd
);
8468 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8471 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8476 if (s
->condexec_mask
)
8477 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8479 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8481 store_reg(s
, rd
, tmp
);
8484 if (s
->condexec_mask
)
8485 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8487 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8489 store_reg(s
, rd
, tmp
);
8495 if (insn
& (1 << 11)) {
8496 rd
= (insn
>> 8) & 7;
8497 /* load pc-relative. Bit 1 of PC is ignored. */
8498 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8499 val
&= ~(uint32_t)2;
8501 tcg_gen_movi_i32(addr
, val
);
8502 tmp
= gen_ld32(addr
, IS_USER(s
));
8504 store_reg(s
, rd
, tmp
);
8507 if (insn
& (1 << 10)) {
8508 /* data processing extended or blx */
8509 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8510 rm
= (insn
>> 3) & 0xf;
8511 op
= (insn
>> 8) & 3;
8514 tmp
= load_reg(s
, rd
);
8515 tmp2
= load_reg(s
, rm
);
8516 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8518 store_reg(s
, rd
, tmp
);
8521 tmp
= load_reg(s
, rd
);
8522 tmp2
= load_reg(s
, rm
);
8523 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8527 case 2: /* mov/cpy */
8528 tmp
= load_reg(s
, rm
);
8529 store_reg(s
, rd
, tmp
);
8531 case 3:/* branch [and link] exchange thumb register */
8532 tmp
= load_reg(s
, rm
);
8533 if (insn
& (1 << 7)) {
8534 val
= (uint32_t)s
->pc
| 1;
8536 tcg_gen_movi_i32(tmp2
, val
);
8537 store_reg(s
, 14, tmp2
);
8545 /* data processing register */
8547 rm
= (insn
>> 3) & 7;
8548 op
= (insn
>> 6) & 0xf;
8549 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8550 /* the shift/rotate ops want the operands backwards */
8559 if (op
== 9) { /* neg */
8561 tcg_gen_movi_i32(tmp
, 0);
8562 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8563 tmp
= load_reg(s
, rd
);
8568 tmp2
= load_reg(s
, rm
);
8571 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8572 if (!s
->condexec_mask
)
8576 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8577 if (!s
->condexec_mask
)
8581 if (s
->condexec_mask
) {
8582 gen_helper_shl(tmp2
, tmp2
, tmp
);
8584 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8589 if (s
->condexec_mask
) {
8590 gen_helper_shr(tmp2
, tmp2
, tmp
);
8592 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8597 if (s
->condexec_mask
) {
8598 gen_helper_sar(tmp2
, tmp2
, tmp
);
8600 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8605 if (s
->condexec_mask
)
8608 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8611 if (s
->condexec_mask
)
8612 gen_sub_carry(tmp
, tmp
, tmp2
);
8614 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8617 if (s
->condexec_mask
) {
8618 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
8619 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
8621 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8626 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8631 if (s
->condexec_mask
)
8632 tcg_gen_neg_i32(tmp
, tmp2
);
8634 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8637 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8641 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8645 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8646 if (!s
->condexec_mask
)
8650 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8651 if (!s
->condexec_mask
)
8655 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
8656 if (!s
->condexec_mask
)
8660 tcg_gen_not_i32(tmp2
, tmp2
);
8661 if (!s
->condexec_mask
)
8669 store_reg(s
, rm
, tmp2
);
8673 store_reg(s
, rd
, tmp
);
8683 /* load/store register offset. */
8685 rn
= (insn
>> 3) & 7;
8686 rm
= (insn
>> 6) & 7;
8687 op
= (insn
>> 9) & 7;
8688 addr
= load_reg(s
, rn
);
8689 tmp
= load_reg(s
, rm
);
8690 tcg_gen_add_i32(addr
, addr
, tmp
);
8693 if (op
< 3) /* store */
8694 tmp
= load_reg(s
, rd
);
8698 gen_st32(tmp
, addr
, IS_USER(s
));
8701 gen_st16(tmp
, addr
, IS_USER(s
));
8704 gen_st8(tmp
, addr
, IS_USER(s
));
8707 tmp
= gen_ld8s(addr
, IS_USER(s
));
8710 tmp
= gen_ld32(addr
, IS_USER(s
));
8713 tmp
= gen_ld16u(addr
, IS_USER(s
));
8716 tmp
= gen_ld8u(addr
, IS_USER(s
));
8719 tmp
= gen_ld16s(addr
, IS_USER(s
));
8722 if (op
>= 3) /* load */
8723 store_reg(s
, rd
, tmp
);
8728 /* load/store word immediate offset */
8730 rn
= (insn
>> 3) & 7;
8731 addr
= load_reg(s
, rn
);
8732 val
= (insn
>> 4) & 0x7c;
8733 tcg_gen_addi_i32(addr
, addr
, val
);
8735 if (insn
& (1 << 11)) {
8737 tmp
= gen_ld32(addr
, IS_USER(s
));
8738 store_reg(s
, rd
, tmp
);
8741 tmp
= load_reg(s
, rd
);
8742 gen_st32(tmp
, addr
, IS_USER(s
));
8748 /* load/store byte immediate offset */
8750 rn
= (insn
>> 3) & 7;
8751 addr
= load_reg(s
, rn
);
8752 val
= (insn
>> 6) & 0x1f;
8753 tcg_gen_addi_i32(addr
, addr
, val
);
8755 if (insn
& (1 << 11)) {
8757 tmp
= gen_ld8u(addr
, IS_USER(s
));
8758 store_reg(s
, rd
, tmp
);
8761 tmp
= load_reg(s
, rd
);
8762 gen_st8(tmp
, addr
, IS_USER(s
));
8768 /* load/store halfword immediate offset */
8770 rn
= (insn
>> 3) & 7;
8771 addr
= load_reg(s
, rn
);
8772 val
= (insn
>> 5) & 0x3e;
8773 tcg_gen_addi_i32(addr
, addr
, val
);
8775 if (insn
& (1 << 11)) {
8777 tmp
= gen_ld16u(addr
, IS_USER(s
));
8778 store_reg(s
, rd
, tmp
);
8781 tmp
= load_reg(s
, rd
);
8782 gen_st16(tmp
, addr
, IS_USER(s
));
8788 /* load/store from stack */
8789 rd
= (insn
>> 8) & 7;
8790 addr
= load_reg(s
, 13);
8791 val
= (insn
& 0xff) * 4;
8792 tcg_gen_addi_i32(addr
, addr
, val
);
8794 if (insn
& (1 << 11)) {
8796 tmp
= gen_ld32(addr
, IS_USER(s
));
8797 store_reg(s
, rd
, tmp
);
8800 tmp
= load_reg(s
, rd
);
8801 gen_st32(tmp
, addr
, IS_USER(s
));
8807 /* add to high reg */
8808 rd
= (insn
>> 8) & 7;
8809 if (insn
& (1 << 11)) {
8811 tmp
= load_reg(s
, 13);
8813 /* PC. bit 1 is ignored. */
8815 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8817 val
= (insn
& 0xff) * 4;
8818 tcg_gen_addi_i32(tmp
, tmp
, val
);
8819 store_reg(s
, rd
, tmp
);
8824 op
= (insn
>> 8) & 0xf;
8827 /* adjust stack pointer */
8828 tmp
= load_reg(s
, 13);
8829 val
= (insn
& 0x7f) * 4;
8830 if (insn
& (1 << 7))
8831 val
= -(int32_t)val
;
8832 tcg_gen_addi_i32(tmp
, tmp
, val
);
8833 store_reg(s
, 13, tmp
);
8836 case 2: /* sign/zero extend. */
8839 rm
= (insn
>> 3) & 7;
8840 tmp
= load_reg(s
, rm
);
8841 switch ((insn
>> 6) & 3) {
8842 case 0: gen_sxth(tmp
); break;
8843 case 1: gen_sxtb(tmp
); break;
8844 case 2: gen_uxth(tmp
); break;
8845 case 3: gen_uxtb(tmp
); break;
8847 store_reg(s
, rd
, tmp
);
8849 case 4: case 5: case 0xc: case 0xd:
8851 addr
= load_reg(s
, 13);
8852 if (insn
& (1 << 8))
8856 for (i
= 0; i
< 8; i
++) {
8857 if (insn
& (1 << i
))
8860 if ((insn
& (1 << 11)) == 0) {
8861 tcg_gen_addi_i32(addr
, addr
, -offset
);
8863 for (i
= 0; i
< 8; i
++) {
8864 if (insn
& (1 << i
)) {
8865 if (insn
& (1 << 11)) {
8867 tmp
= gen_ld32(addr
, IS_USER(s
));
8868 store_reg(s
, i
, tmp
);
8871 tmp
= load_reg(s
, i
);
8872 gen_st32(tmp
, addr
, IS_USER(s
));
8874 /* advance to the next address. */
8875 tcg_gen_addi_i32(addr
, addr
, 4);
8879 if (insn
& (1 << 8)) {
8880 if (insn
& (1 << 11)) {
8882 tmp
= gen_ld32(addr
, IS_USER(s
));
8883 /* don't set the pc until the rest of the instruction
8887 tmp
= load_reg(s
, 14);
8888 gen_st32(tmp
, addr
, IS_USER(s
));
8890 tcg_gen_addi_i32(addr
, addr
, 4);
8892 if ((insn
& (1 << 11)) == 0) {
8893 tcg_gen_addi_i32(addr
, addr
, -offset
);
8895 /* write back the new stack pointer */
8896 store_reg(s
, 13, addr
);
8897 /* set the new PC value */
8898 if ((insn
& 0x0900) == 0x0900)
8902 case 1: case 3: case 9: case 11: /* czb */
8904 tmp
= load_reg(s
, rm
);
8905 s
->condlabel
= gen_new_label();
8907 if (insn
& (1 << 11))
8908 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8910 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8912 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8913 val
= (uint32_t)s
->pc
+ 2;
8918 case 15: /* IT, nop-hint. */
8919 if ((insn
& 0xf) == 0) {
8920 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8924 s
->condexec_cond
= (insn
>> 4) & 0xe;
8925 s
->condexec_mask
= insn
& 0x1f;
8926 /* No actual code generated for this insn, just setup state. */
8929 case 0xe: /* bkpt */
8930 gen_set_condexec(s
);
8931 gen_set_pc_im(s
->pc
- 2);
8932 gen_exception(EXCP_BKPT
);
8933 s
->is_jmp
= DISAS_JUMP
;
8938 rn
= (insn
>> 3) & 0x7;
8940 tmp
= load_reg(s
, rn
);
8941 switch ((insn
>> 6) & 3) {
8942 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8943 case 1: gen_rev16(tmp
); break;
8944 case 3: gen_revsh(tmp
); break;
8945 default: goto illegal_op
;
8947 store_reg(s
, rd
, tmp
);
8955 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8958 addr
= tcg_const_i32(16);
8959 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8960 tcg_temp_free_i32(addr
);
8964 addr
= tcg_const_i32(17);
8965 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8966 tcg_temp_free_i32(addr
);
8968 tcg_temp_free_i32(tmp
);
8971 if (insn
& (1 << 4))
8972 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8975 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
8985 /* load/store multiple */
8986 rn
= (insn
>> 8) & 0x7;
8987 addr
= load_reg(s
, rn
);
8988 for (i
= 0; i
< 8; i
++) {
8989 if (insn
& (1 << i
)) {
8990 if (insn
& (1 << 11)) {
8992 tmp
= gen_ld32(addr
, IS_USER(s
));
8993 store_reg(s
, i
, tmp
);
8996 tmp
= load_reg(s
, i
);
8997 gen_st32(tmp
, addr
, IS_USER(s
));
8999 /* advance to the next address */
9000 tcg_gen_addi_i32(addr
, addr
, 4);
9003 /* Base register writeback. */
9004 if ((insn
& (1 << rn
)) == 0) {
9005 store_reg(s
, rn
, addr
);
9012 /* conditional branch or swi */
9013 cond
= (insn
>> 8) & 0xf;
9019 gen_set_condexec(s
);
9020 gen_set_pc_im(s
->pc
);
9021 s
->is_jmp
= DISAS_SWI
;
9024 /* generate a conditional jump to next instruction */
9025 s
->condlabel
= gen_new_label();
9026 gen_test_cc(cond
^ 1, s
->condlabel
);
9029 /* jump to the offset */
9030 val
= (uint32_t)s
->pc
+ 2;
9031 offset
= ((int32_t)insn
<< 24) >> 24;
9037 if (insn
& (1 << 11)) {
9038 if (disas_thumb2_insn(env
, s
, insn
))
9042 /* unconditional branch */
9043 val
= (uint32_t)s
->pc
;
9044 offset
= ((int32_t)insn
<< 21) >> 21;
9045 val
+= (offset
<< 1) + 2;
9050 if (disas_thumb2_insn(env
, s
, insn
))
9056 gen_set_condexec(s
);
9057 gen_set_pc_im(s
->pc
- 4);
9058 gen_exception(EXCP_UDEF
);
9059 s
->is_jmp
= DISAS_JUMP
;
9063 gen_set_condexec(s
);
9064 gen_set_pc_im(s
->pc
- 2);
9065 gen_exception(EXCP_UDEF
);
9066 s
->is_jmp
= DISAS_JUMP
;
9069 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9070 basic block 'tb'. If search_pc is TRUE, also generate PC
9071 information for each intermediate instruction. */
9072 static inline void gen_intermediate_code_internal(CPUState
*env
,
9073 TranslationBlock
*tb
,
9076 DisasContext dc1
, *dc
= &dc1
;
9078 uint16_t *gen_opc_end
;
9080 target_ulong pc_start
;
9081 uint32_t next_page_start
;
9085 /* generate intermediate code */
9092 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
9094 dc
->is_jmp
= DISAS_NEXT
;
9096 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9098 dc
->thumb
= ARM_TBFLAG_THUMB(tb
->flags
);
9099 dc
->condexec_mask
= (ARM_TBFLAG_CONDEXEC(tb
->flags
) & 0xf) << 1;
9100 dc
->condexec_cond
= ARM_TBFLAG_CONDEXEC(tb
->flags
) >> 4;
9101 #if !defined(CONFIG_USER_ONLY)
9103 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
9105 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
9108 dc
->vfp_enabled
= ARM_TBFLAG_VFPEN(tb
->flags
);
9109 dc
->vec_len
= ARM_TBFLAG_VECLEN(tb
->flags
);
9110 dc
->vec_stride
= ARM_TBFLAG_VECSTRIDE(tb
->flags
);
9111 cpu_F0s
= tcg_temp_new_i32();
9112 cpu_F1s
= tcg_temp_new_i32();
9113 cpu_F0d
= tcg_temp_new_i64();
9114 cpu_F1d
= tcg_temp_new_i64();
9117 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9118 cpu_M0
= tcg_temp_new_i64();
9119 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9122 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9124 max_insns
= CF_COUNT_MASK
;
9127 /* Reset the conditional execution bits immediately. This avoids
9128 complications trying to do it at the end of the block. */
9129 if (dc
->condexec_mask
|| dc
->condexec_cond
)
9131 TCGv tmp
= new_tmp();
9132 tcg_gen_movi_i32(tmp
, 0);
9133 store_cpu_field(tmp
, condexec_bits
);
9136 #ifdef CONFIG_USER_ONLY
9137 /* Intercept jump to the magic kernel page. */
9138 if (dc
->pc
>= 0xffff0000) {
9139 /* We always get here via a jump, so know we are not in a
9140 conditional execution block. */
9141 gen_exception(EXCP_KERNEL_TRAP
);
9142 dc
->is_jmp
= DISAS_UPDATE
;
9146 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9147 /* We always get here via a jump, so know we are not in a
9148 conditional execution block. */
9149 gen_exception(EXCP_EXCEPTION_EXIT
);
9150 dc
->is_jmp
= DISAS_UPDATE
;
9155 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9156 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9157 if (bp
->pc
== dc
->pc
) {
9158 gen_set_condexec(dc
);
9159 gen_set_pc_im(dc
->pc
);
9160 gen_exception(EXCP_DEBUG
);
9161 dc
->is_jmp
= DISAS_JUMP
;
9162 /* Advance PC so that clearing the breakpoint will
9163 invalidate this TB. */
9165 goto done_generating
;
9171 j
= gen_opc_ptr
- gen_opc_buf
;
9175 gen_opc_instr_start
[lj
++] = 0;
9177 gen_opc_pc
[lj
] = dc
->pc
;
9178 gen_opc_instr_start
[lj
] = 1;
9179 gen_opc_icount
[lj
] = num_insns
;
9182 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9186 disas_thumb_insn(env
, dc
);
9187 if (dc
->condexec_mask
) {
9188 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9189 | ((dc
->condexec_mask
>> 4) & 1);
9190 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9191 if (dc
->condexec_mask
== 0) {
9192 dc
->condexec_cond
= 0;
9196 disas_arm_insn(env
, dc
);
9199 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
9203 if (dc
->condjmp
&& !dc
->is_jmp
) {
9204 gen_set_label(dc
->condlabel
);
9207 /* Translation stops when a conditional branch is encountered.
9208 * Otherwise the subsequent code could get translated several times.
9209 * Also stop translation when a page boundary is reached. This
9210 * ensures prefetch aborts occur at the right place. */
9212 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
9213 !env
->singlestep_enabled
&&
9215 dc
->pc
< next_page_start
&&
9216 num_insns
< max_insns
);
9218 if (tb
->cflags
& CF_LAST_IO
) {
9220 /* FIXME: This can theoretically happen with self-modifying
9222 cpu_abort(env
, "IO on conditional branch instruction");
9227 /* At this stage dc->condjmp will only be set when the skipped
9228 instruction was a conditional branch or trap, and the PC has
9229 already been written. */
9230 if (unlikely(env
->singlestep_enabled
)) {
9231 /* Make sure the pc is updated, and raise a debug exception. */
9233 gen_set_condexec(dc
);
9234 if (dc
->is_jmp
== DISAS_SWI
) {
9235 gen_exception(EXCP_SWI
);
9237 gen_exception(EXCP_DEBUG
);
9239 gen_set_label(dc
->condlabel
);
9241 if (dc
->condjmp
|| !dc
->is_jmp
) {
9242 gen_set_pc_im(dc
->pc
);
9245 gen_set_condexec(dc
);
9246 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9247 gen_exception(EXCP_SWI
);
9249 /* FIXME: Single stepping a WFI insn will not halt
9251 gen_exception(EXCP_DEBUG
);
9254 /* While branches must always occur at the end of an IT block,
9255 there are a few other things that can cause us to terminate
9256 the TB in the middel of an IT block:
9257 - Exception generating instructions (bkpt, swi, undefined).
9259 - Hardware watchpoints.
9260 Hardware breakpoints have already been handled and skip this code.
9262 gen_set_condexec(dc
);
9263 switch(dc
->is_jmp
) {
9265 gen_goto_tb(dc
, 1, dc
->pc
);
9270 /* indicate that the hash table must be used to find the next TB */
9274 /* nothing more to generate */
9280 gen_exception(EXCP_SWI
);
9284 gen_set_label(dc
->condlabel
);
9285 gen_set_condexec(dc
);
9286 gen_goto_tb(dc
, 1, dc
->pc
);
9292 gen_icount_end(tb
, num_insns
);
9293 *gen_opc_ptr
= INDEX_op_end
;
9296 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9297 qemu_log("----------------\n");
9298 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9299 log_target_disas(pc_start
, dc
->pc
- pc_start
, dc
->thumb
);
9304 j
= gen_opc_ptr
- gen_opc_buf
;
9307 gen_opc_instr_start
[lj
++] = 0;
9309 tb
->size
= dc
->pc
- pc_start
;
9310 tb
->icount
= num_insns
;
9314 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9316 gen_intermediate_code_internal(env
, tb
, 0);
9319 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9321 gen_intermediate_code_internal(env
, tb
, 1);
9324 static const char *cpu_mode_names
[16] = {
9325 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9326 "???", "???", "???", "und", "???", "???", "???", "sys"
9329 void cpu_dump_state(CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
9339 /* ??? This assumes float64 and double have the same layout.
9340 Oh well, it's only debug dumps. */
9349 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9351 cpu_fprintf(f
, "\n");
9353 cpu_fprintf(f
, " ");
9355 psr
= cpsr_read(env
);
9356 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9358 psr
& (1 << 31) ? 'N' : '-',
9359 psr
& (1 << 30) ? 'Z' : '-',
9360 psr
& (1 << 29) ? 'C' : '-',
9361 psr
& (1 << 28) ? 'V' : '-',
9362 psr
& CPSR_T
? 'T' : 'A',
9363 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9366 for (i
= 0; i
< 16; i
++) {
9367 d
.d
= env
->vfp
.regs
[i
];
9371 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9372 i
* 2, (int)s0
.i
, s0
.s
,
9373 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9374 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9377 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9381 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9382 unsigned long searched_pc
, int pc_pos
, void *puc
)
9384 env
->regs
[15] = gen_opc_pc
[pc_pos
];