4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s
, cpu_F1s
;
82 static TCGv_i64 cpu_F0d
, cpu_F1d
;
84 #include "gen-icount.h"
86 static const char *regnames
[] =
87 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
88 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
90 /* initialize TCG globals. */
91 void arm_translate_init(void)
95 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
97 for (i
= 0; i
< 16; i
++) {
98 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
99 offsetof(CPUState
, regs
[i
]),
107 static int num_temps
;
109 /* Allocate a temporary variable. */
110 static TCGv_i32
new_tmp(void)
113 return tcg_temp_new_i32();
116 /* Release a temporary variable. */
117 static void dead_tmp(TCGv tmp
)
123 static inline TCGv
load_cpu_offset(int offset
)
125 TCGv tmp
= new_tmp();
126 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
130 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
132 static inline void store_cpu_offset(TCGv var
, int offset
)
134 tcg_gen_st_i32(var
, cpu_env
, offset
);
138 #define store_cpu_field(var, name) \
139 store_cpu_offset(var, offsetof(CPUState, name))
141 /* Set a variable to the value of a CPU register. */
142 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
146 /* normaly, since we updated PC, we need only to add one insn */
148 addr
= (long)s
->pc
+ 2;
150 addr
= (long)s
->pc
+ 4;
151 tcg_gen_movi_i32(var
, addr
);
153 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
157 /* Create a new temporary and set it to the value of a CPU register. */
158 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
160 TCGv tmp
= new_tmp();
161 load_reg_var(s
, tmp
, reg
);
165 /* Set a CPU register. The source must be a temporary and will be
167 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
170 tcg_gen_andi_i32(var
, var
, ~1);
171 s
->is_jmp
= DISAS_JUMP
;
173 tcg_gen_mov_i32(cpu_R
[reg
], var
);
177 /* Value extensions. */
178 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
179 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
180 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
181 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
183 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
184 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
187 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
189 TCGv tmp_mask
= tcg_const_i32(mask
);
190 gen_helper_cpsr_write(var
, tmp_mask
);
191 tcg_temp_free_i32(tmp_mask
);
193 /* Set NZCV flags from the high 4 bits of var. */
194 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
196 static void gen_exception(int excp
)
198 TCGv tmp
= new_tmp();
199 tcg_gen_movi_i32(tmp
, excp
);
200 gen_helper_exception(tmp
);
204 static void gen_smul_dual(TCGv a
, TCGv b
)
206 TCGv tmp1
= new_tmp();
207 TCGv tmp2
= new_tmp();
208 tcg_gen_ext16s_i32(tmp1
, a
);
209 tcg_gen_ext16s_i32(tmp2
, b
);
210 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
212 tcg_gen_sari_i32(a
, a
, 16);
213 tcg_gen_sari_i32(b
, b
, 16);
214 tcg_gen_mul_i32(b
, b
, a
);
215 tcg_gen_mov_i32(a
, tmp1
);
219 /* Byteswap each halfword. */
220 static void gen_rev16(TCGv var
)
222 TCGv tmp
= new_tmp();
223 tcg_gen_shri_i32(tmp
, var
, 8);
224 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
225 tcg_gen_shli_i32(var
, var
, 8);
226 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
227 tcg_gen_or_i32(var
, var
, tmp
);
231 /* Byteswap low halfword and sign extend. */
232 static void gen_revsh(TCGv var
)
234 TCGv tmp
= new_tmp();
235 tcg_gen_shri_i32(tmp
, var
, 8);
236 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
237 tcg_gen_shli_i32(var
, var
, 8);
238 tcg_gen_ext8s_i32(var
, var
);
239 tcg_gen_or_i32(var
, var
, tmp
);
243 /* Unsigned bitfield extract. */
244 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
247 tcg_gen_shri_i32(var
, var
, shift
);
248 tcg_gen_andi_i32(var
, var
, mask
);
251 /* Signed bitfield extract. */
252 static void gen_sbfx(TCGv var
, int shift
, int width
)
257 tcg_gen_sari_i32(var
, var
, shift
);
258 if (shift
+ width
< 32) {
259 signbit
= 1u << (width
- 1);
260 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
261 tcg_gen_xori_i32(var
, var
, signbit
);
262 tcg_gen_subi_i32(var
, var
, signbit
);
266 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
267 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
269 tcg_gen_andi_i32(val
, val
, mask
);
270 tcg_gen_shli_i32(val
, val
, shift
);
271 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
272 tcg_gen_or_i32(dest
, base
, val
);
275 /* Round the top 32 bits of a 64-bit value. */
276 static void gen_roundqd(TCGv a
, TCGv b
)
278 tcg_gen_shri_i32(a
, a
, 31);
279 tcg_gen_add_i32(a
, a
, b
);
282 /* FIXME: Most targets have native widening multiplication.
283 It would be good to use that instead of a full wide multiply. */
284 /* 32x32->64 multiply. Marks inputs as dead. */
285 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
287 TCGv_i64 tmp1
= tcg_temp_new_i64();
288 TCGv_i64 tmp2
= tcg_temp_new_i64();
290 tcg_gen_extu_i32_i64(tmp1
, a
);
292 tcg_gen_extu_i32_i64(tmp2
, b
);
294 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
295 tcg_temp_free_i64(tmp2
);
299 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
301 TCGv_i64 tmp1
= tcg_temp_new_i64();
302 TCGv_i64 tmp2
= tcg_temp_new_i64();
304 tcg_gen_ext_i32_i64(tmp1
, a
);
306 tcg_gen_ext_i32_i64(tmp2
, b
);
308 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
309 tcg_temp_free_i64(tmp2
);
313 /* Signed 32x32->64 multiply. */
314 static void gen_imull(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1
, a
);
320 tcg_gen_ext_i32_i64(tmp2
, b
);
321 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
322 tcg_temp_free_i64(tmp2
);
323 tcg_gen_trunc_i64_i32(a
, tmp1
);
324 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
325 tcg_gen_trunc_i64_i32(b
, tmp1
);
326 tcg_temp_free_i64(tmp1
);
329 /* Swap low and high halfwords. */
330 static void gen_swap_half(TCGv var
)
332 TCGv tmp
= new_tmp();
333 tcg_gen_shri_i32(tmp
, var
, 16);
334 tcg_gen_shli_i32(var
, var
, 16);
335 tcg_gen_or_i32(var
, var
, tmp
);
339 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
340 tmp = (t0 ^ t1) & 0x8000;
343 t0 = (t0 + t1) ^ tmp;
346 static void gen_add16(TCGv t0
, TCGv t1
)
348 TCGv tmp
= new_tmp();
349 tcg_gen_xor_i32(tmp
, t0
, t1
);
350 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
351 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
352 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
353 tcg_gen_add_i32(t0
, t0
, t1
);
354 tcg_gen_xor_i32(t0
, t0
, tmp
);
359 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
361 /* Set CF to the top bit of var. */
362 static void gen_set_CF_bit31(TCGv var
)
364 TCGv tmp
= new_tmp();
365 tcg_gen_shri_i32(tmp
, var
, 31);
370 /* Set N and Z flags from var. */
371 static inline void gen_logic_CC(TCGv var
)
373 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
374 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
378 static void gen_adc(TCGv t0
, TCGv t1
)
381 tcg_gen_add_i32(t0
, t0
, t1
);
382 tmp
= load_cpu_field(CF
);
383 tcg_gen_add_i32(t0
, t0
, tmp
);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
391 tcg_gen_add_i32(dest
, t0
, t1
);
392 tmp
= load_cpu_field(CF
);
393 tcg_gen_add_i32(dest
, dest
, tmp
);
397 /* dest = T0 - T1 + CF - 1. */
398 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
401 tcg_gen_sub_i32(dest
, t0
, t1
);
402 tmp
= load_cpu_field(CF
);
403 tcg_gen_add_i32(dest
, dest
, tmp
);
404 tcg_gen_subi_i32(dest
, dest
, 1);
408 /* T0 &= ~T1. Clobbers T1. */
409 /* FIXME: Implement bic natively. */
410 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
412 TCGv tmp
= new_tmp();
413 tcg_gen_not_i32(tmp
, t1
);
414 tcg_gen_and_i32(dest
, t0
, tmp
);
418 /* FIXME: Implement this natively. */
419 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
421 /* FIXME: Implement this natively. */
422 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
430 tcg_gen_shri_i32(tmp
, t1
, i
);
431 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
432 tcg_gen_or_i32(t0
, t1
, tmp
);
436 static void shifter_out_im(TCGv var
, int shift
)
438 TCGv tmp
= new_tmp();
440 tcg_gen_andi_i32(tmp
, var
, 1);
442 tcg_gen_shri_i32(tmp
, var
, shift
);
444 tcg_gen_andi_i32(tmp
, tmp
, 1);
450 /* Shift by immediate. Includes special handling for shift == 0. */
451 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
457 shifter_out_im(var
, 32 - shift
);
458 tcg_gen_shli_i32(var
, var
, shift
);
464 tcg_gen_shri_i32(var
, var
, 31);
467 tcg_gen_movi_i32(var
, 0);
470 shifter_out_im(var
, shift
- 1);
471 tcg_gen_shri_i32(var
, var
, shift
);
478 shifter_out_im(var
, shift
- 1);
481 tcg_gen_sari_i32(var
, var
, shift
);
483 case 3: /* ROR/RRX */
486 shifter_out_im(var
, shift
- 1);
487 tcg_gen_rori_i32(var
, var
, shift
); break;
489 TCGv tmp
= load_cpu_field(CF
);
491 shifter_out_im(var
, 0);
492 tcg_gen_shri_i32(var
, var
, 1);
493 tcg_gen_shli_i32(tmp
, tmp
, 31);
494 tcg_gen_or_i32(var
, var
, tmp
);
500 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
501 TCGv shift
, int flags
)
505 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
506 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
507 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
508 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
512 case 0: gen_helper_shl(var
, var
, shift
); break;
513 case 1: gen_helper_shr(var
, var
, shift
); break;
514 case 2: gen_helper_sar(var
, var
, shift
); break;
515 case 3: gen_helper_ror(var
, var
, shift
); break;
521 #define PAS_OP(pfx) \
523 case 0: gen_pas_helper(glue(pfx,add16)); break; \
524 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
525 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
526 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
527 case 4: gen_pas_helper(glue(pfx,add8)); break; \
528 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
530 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
535 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
537 tmp
= tcg_temp_new_ptr();
538 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
540 tcg_temp_free_ptr(tmp
);
543 tmp
= tcg_temp_new_ptr();
544 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
546 tcg_temp_free_ptr(tmp
);
548 #undef gen_pas_helper
549 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
562 #undef gen_pas_helper
567 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
568 #define PAS_OP(pfx) \
570 case 0: gen_pas_helper(glue(pfx,add8)); break; \
571 case 1: gen_pas_helper(glue(pfx,add16)); break; \
572 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
573 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
574 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
575 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
577 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
582 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
584 tmp
= tcg_temp_new_ptr();
585 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
587 tcg_temp_free_ptr(tmp
);
590 tmp
= tcg_temp_new_ptr();
591 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
593 tcg_temp_free_ptr(tmp
);
595 #undef gen_pas_helper
596 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
609 #undef gen_pas_helper
614 static void gen_test_cc(int cc
, int label
)
622 tmp
= load_cpu_field(ZF
);
623 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
626 tmp
= load_cpu_field(ZF
);
627 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
630 tmp
= load_cpu_field(CF
);
631 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
634 tmp
= load_cpu_field(CF
);
635 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
638 tmp
= load_cpu_field(NF
);
639 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
642 tmp
= load_cpu_field(NF
);
643 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
646 tmp
= load_cpu_field(VF
);
647 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
650 tmp
= load_cpu_field(VF
);
651 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
653 case 8: /* hi: C && !Z */
654 inv
= gen_new_label();
655 tmp
= load_cpu_field(CF
);
656 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
658 tmp
= load_cpu_field(ZF
);
659 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
662 case 9: /* ls: !C || Z */
663 tmp
= load_cpu_field(CF
);
664 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
666 tmp
= load_cpu_field(ZF
);
667 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
669 case 10: /* ge: N == V -> N ^ V == 0 */
670 tmp
= load_cpu_field(VF
);
671 tmp2
= load_cpu_field(NF
);
672 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
674 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
676 case 11: /* lt: N != V -> N ^ V != 0 */
677 tmp
= load_cpu_field(VF
);
678 tmp2
= load_cpu_field(NF
);
679 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
681 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
683 case 12: /* gt: !Z && N == V */
684 inv
= gen_new_label();
685 tmp
= load_cpu_field(ZF
);
686 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
688 tmp
= load_cpu_field(VF
);
689 tmp2
= load_cpu_field(NF
);
690 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
692 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
695 case 13: /* le: Z || N != V */
696 tmp
= load_cpu_field(ZF
);
697 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
699 tmp
= load_cpu_field(VF
);
700 tmp2
= load_cpu_field(NF
);
701 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
703 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
706 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
712 static const uint8_t table_logic_cc
[16] = {
731 /* Set PC and Thumb state from an immediate address. */
732 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
736 s
->is_jmp
= DISAS_UPDATE
;
737 if (s
->thumb
!= (addr
& 1)) {
739 tcg_gen_movi_i32(tmp
, addr
& 1);
740 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
743 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
746 /* Set PC and Thumb state from var. var is marked as dead. */
747 static inline void gen_bx(DisasContext
*s
, TCGv var
)
749 s
->is_jmp
= DISAS_UPDATE
;
750 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
751 tcg_gen_andi_i32(var
, var
, 1);
752 store_cpu_field(var
, thumb
);
755 /* Variant of store_reg which uses branch&exchange logic when storing
756 to r15 in ARM architecture v7 and above. The source must be a temporary
757 and will be marked as dead. */
758 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
761 if (reg
== 15 && ENABLE_ARCH_7
) {
764 store_reg(s
, reg
, var
);
768 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
770 TCGv tmp
= new_tmp();
771 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
774 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
776 TCGv tmp
= new_tmp();
777 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
780 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
782 TCGv tmp
= new_tmp();
783 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
786 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
788 TCGv tmp
= new_tmp();
789 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
792 static inline TCGv
gen_ld32(TCGv addr
, int index
)
794 TCGv tmp
= new_tmp();
795 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
798 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
800 tcg_gen_qemu_st8(val
, addr
, index
);
803 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
805 tcg_gen_qemu_st16(val
, addr
, index
);
808 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
810 tcg_gen_qemu_st32(val
, addr
, index
);
814 static inline void gen_set_pc_im(uint32_t val
)
816 tcg_gen_movi_i32(cpu_R
[15], val
);
819 /* Force a TB lookup after an instruction that changes the CPU state. */
820 static inline void gen_lookup_tb(DisasContext
*s
)
822 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
823 s
->is_jmp
= DISAS_UPDATE
;
826 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
829 int val
, rm
, shift
, shiftop
;
832 if (!(insn
& (1 << 25))) {
835 if (!(insn
& (1 << 23)))
838 tcg_gen_addi_i32(var
, var
, val
);
842 shift
= (insn
>> 7) & 0x1f;
843 shiftop
= (insn
>> 5) & 3;
844 offset
= load_reg(s
, rm
);
845 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
846 if (!(insn
& (1 << 23)))
847 tcg_gen_sub_i32(var
, var
, offset
);
849 tcg_gen_add_i32(var
, var
, offset
);
854 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
860 if (insn
& (1 << 22)) {
862 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
863 if (!(insn
& (1 << 23)))
867 tcg_gen_addi_i32(var
, var
, val
);
871 tcg_gen_addi_i32(var
, var
, extra
);
873 offset
= load_reg(s
, rm
);
874 if (!(insn
& (1 << 23)))
875 tcg_gen_sub_i32(var
, var
, offset
);
877 tcg_gen_add_i32(var
, var
, offset
);
882 #define VFP_OP2(name) \
883 static inline void gen_vfp_##name(int dp) \
886 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
888 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
898 static inline void gen_vfp_abs(int dp
)
901 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
903 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
906 static inline void gen_vfp_neg(int dp
)
909 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
911 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
914 static inline void gen_vfp_sqrt(int dp
)
917 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
919 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
922 static inline void gen_vfp_cmp(int dp
)
925 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
927 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
930 static inline void gen_vfp_cmpe(int dp
)
933 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
935 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
938 static inline void gen_vfp_F1_ld0(int dp
)
941 tcg_gen_movi_i64(cpu_F1d
, 0);
943 tcg_gen_movi_i32(cpu_F1s
, 0);
946 static inline void gen_vfp_uito(int dp
)
949 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
951 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
954 static inline void gen_vfp_sito(int dp
)
957 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
959 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
962 static inline void gen_vfp_toui(int dp
)
965 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
967 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
970 static inline void gen_vfp_touiz(int dp
)
973 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
975 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
978 static inline void gen_vfp_tosi(int dp
)
981 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
983 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
986 static inline void gen_vfp_tosiz(int dp
)
989 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
991 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
994 #define VFP_GEN_FIX(name) \
995 static inline void gen_vfp_##name(int dp, int shift) \
997 TCGv tmp_shift = tcg_const_i32(shift); \
999 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1001 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1002 tcg_temp_free_i32(tmp_shift); \
1014 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1017 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1019 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1022 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1025 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1027 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1031 vfp_reg_offset (int dp
, int reg
)
1034 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1036 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1037 + offsetof(CPU_DoubleU
, l
.upper
);
1039 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1040 + offsetof(CPU_DoubleU
, l
.lower
);
1044 /* Return the offset of a 32-bit piece of a NEON register.
1045 zero is the least significant end of the register. */
1047 neon_reg_offset (int reg
, int n
)
1051 return vfp_reg_offset(0, sreg
);
1054 static TCGv
neon_load_reg(int reg
, int pass
)
1056 TCGv tmp
= new_tmp();
1057 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1061 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1063 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1067 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1069 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1072 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1074 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1077 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1078 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1079 #define tcg_gen_st_f32 tcg_gen_st_i32
1080 #define tcg_gen_st_f64 tcg_gen_st_i64
1082 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1085 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1087 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1090 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1093 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1095 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1098 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1101 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1103 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1106 #define ARM_CP_RW_BIT (1 << 20)
1108 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1110 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1113 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1115 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1118 static inline TCGv
iwmmxt_load_creg(int reg
)
1120 TCGv var
= new_tmp();
1121 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1125 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1127 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1130 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1132 iwmmxt_store_reg(cpu_M0
, rn
);
1135 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1137 iwmmxt_load_reg(cpu_M0
, rn
);
1140 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1142 iwmmxt_load_reg(cpu_V1
, rn
);
1143 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1146 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1148 iwmmxt_load_reg(cpu_V1
, rn
);
1149 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1152 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1154 iwmmxt_load_reg(cpu_V1
, rn
);
1155 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1158 #define IWMMXT_OP(name) \
1159 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1161 iwmmxt_load_reg(cpu_V1, rn); \
1162 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1165 #define IWMMXT_OP_ENV(name) \
1166 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1168 iwmmxt_load_reg(cpu_V1, rn); \
1169 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1172 #define IWMMXT_OP_ENV_SIZE(name) \
1173 IWMMXT_OP_ENV(name##b) \
1174 IWMMXT_OP_ENV(name##w) \
1175 IWMMXT_OP_ENV(name##l)
1177 #define IWMMXT_OP_ENV1(name) \
1178 static inline void gen_op_iwmmxt_##name##_M0(void) \
1180 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1194 IWMMXT_OP_ENV_SIZE(unpackl
)
1195 IWMMXT_OP_ENV_SIZE(unpackh
)
1197 IWMMXT_OP_ENV1(unpacklub
)
1198 IWMMXT_OP_ENV1(unpackluw
)
1199 IWMMXT_OP_ENV1(unpacklul
)
1200 IWMMXT_OP_ENV1(unpackhub
)
1201 IWMMXT_OP_ENV1(unpackhuw
)
1202 IWMMXT_OP_ENV1(unpackhul
)
1203 IWMMXT_OP_ENV1(unpacklsb
)
1204 IWMMXT_OP_ENV1(unpacklsw
)
1205 IWMMXT_OP_ENV1(unpacklsl
)
1206 IWMMXT_OP_ENV1(unpackhsb
)
1207 IWMMXT_OP_ENV1(unpackhsw
)
1208 IWMMXT_OP_ENV1(unpackhsl
)
1210 IWMMXT_OP_ENV_SIZE(cmpeq
)
1211 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1212 IWMMXT_OP_ENV_SIZE(cmpgts
)
1214 IWMMXT_OP_ENV_SIZE(mins
)
1215 IWMMXT_OP_ENV_SIZE(minu
)
1216 IWMMXT_OP_ENV_SIZE(maxs
)
1217 IWMMXT_OP_ENV_SIZE(maxu
)
1219 IWMMXT_OP_ENV_SIZE(subn
)
1220 IWMMXT_OP_ENV_SIZE(addn
)
1221 IWMMXT_OP_ENV_SIZE(subu
)
1222 IWMMXT_OP_ENV_SIZE(addu
)
1223 IWMMXT_OP_ENV_SIZE(subs
)
1224 IWMMXT_OP_ENV_SIZE(adds
)
1226 IWMMXT_OP_ENV(avgb0
)
1227 IWMMXT_OP_ENV(avgb1
)
1228 IWMMXT_OP_ENV(avgw0
)
1229 IWMMXT_OP_ENV(avgw1
)
1233 IWMMXT_OP_ENV(packuw
)
1234 IWMMXT_OP_ENV(packul
)
1235 IWMMXT_OP_ENV(packuq
)
1236 IWMMXT_OP_ENV(packsw
)
1237 IWMMXT_OP_ENV(packsl
)
1238 IWMMXT_OP_ENV(packsq
)
1240 static void gen_op_iwmmxt_set_mup(void)
1243 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1244 tcg_gen_ori_i32(tmp
, tmp
, 2);
1245 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1248 static void gen_op_iwmmxt_set_cup(void)
1251 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1252 tcg_gen_ori_i32(tmp
, tmp
, 1);
1253 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1256 static void gen_op_iwmmxt_setpsr_nz(void)
1258 TCGv tmp
= new_tmp();
1259 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1260 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1263 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1265 iwmmxt_load_reg(cpu_V1
, rn
);
1266 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1267 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1270 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1276 rd
= (insn
>> 16) & 0xf;
1277 tmp
= load_reg(s
, rd
);
1279 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1280 if (insn
& (1 << 24)) {
1282 if (insn
& (1 << 23))
1283 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1285 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1286 tcg_gen_mov_i32(dest
, tmp
);
1287 if (insn
& (1 << 21))
1288 store_reg(s
, rd
, tmp
);
1291 } else if (insn
& (1 << 21)) {
1293 tcg_gen_mov_i32(dest
, tmp
);
1294 if (insn
& (1 << 23))
1295 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1297 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1298 store_reg(s
, rd
, tmp
);
1299 } else if (!(insn
& (1 << 23)))
1304 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1306 int rd
= (insn
>> 0) & 0xf;
1309 if (insn
& (1 << 8)) {
1310 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1313 tmp
= iwmmxt_load_creg(rd
);
1317 iwmmxt_load_reg(cpu_V0
, rd
);
1318 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1320 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1321 tcg_gen_mov_i32(dest
, tmp
);
1326 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1327 (ie. an undefined instruction). */
1328 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1331 int rdhi
, rdlo
, rd0
, rd1
, i
;
1333 TCGv tmp
, tmp2
, tmp3
;
1335 if ((insn
& 0x0e000e00) == 0x0c000000) {
1336 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1338 rdlo
= (insn
>> 12) & 0xf;
1339 rdhi
= (insn
>> 16) & 0xf;
1340 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1341 iwmmxt_load_reg(cpu_V0
, wrd
);
1342 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1343 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1344 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1345 } else { /* TMCRR */
1346 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1347 iwmmxt_store_reg(cpu_V0
, wrd
);
1348 gen_op_iwmmxt_set_mup();
1353 wrd
= (insn
>> 12) & 0xf;
1355 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1359 if (insn
& ARM_CP_RW_BIT
) {
1360 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1362 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1363 iwmmxt_store_creg(wrd
, tmp
);
1366 if (insn
& (1 << 8)) {
1367 if (insn
& (1 << 22)) { /* WLDRD */
1368 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1370 } else { /* WLDRW wRd */
1371 tmp
= gen_ld32(addr
, IS_USER(s
));
1374 if (insn
& (1 << 22)) { /* WLDRH */
1375 tmp
= gen_ld16u(addr
, IS_USER(s
));
1376 } else { /* WLDRB */
1377 tmp
= gen_ld8u(addr
, IS_USER(s
));
1381 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1384 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1387 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1388 tmp
= iwmmxt_load_creg(wrd
);
1389 gen_st32(tmp
, addr
, IS_USER(s
));
1391 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1393 if (insn
& (1 << 8)) {
1394 if (insn
& (1 << 22)) { /* WSTRD */
1396 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1397 } else { /* WSTRW wRd */
1398 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1399 gen_st32(tmp
, addr
, IS_USER(s
));
1402 if (insn
& (1 << 22)) { /* WSTRH */
1403 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1404 gen_st16(tmp
, addr
, IS_USER(s
));
1405 } else { /* WSTRB */
1406 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1407 gen_st8(tmp
, addr
, IS_USER(s
));
1415 if ((insn
& 0x0f000000) != 0x0e000000)
1418 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1419 case 0x000: /* WOR */
1420 wrd
= (insn
>> 12) & 0xf;
1421 rd0
= (insn
>> 0) & 0xf;
1422 rd1
= (insn
>> 16) & 0xf;
1423 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1424 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1425 gen_op_iwmmxt_setpsr_nz();
1426 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1427 gen_op_iwmmxt_set_mup();
1428 gen_op_iwmmxt_set_cup();
1430 case 0x011: /* TMCR */
1433 rd
= (insn
>> 12) & 0xf;
1434 wrd
= (insn
>> 16) & 0xf;
1436 case ARM_IWMMXT_wCID
:
1437 case ARM_IWMMXT_wCASF
:
1439 case ARM_IWMMXT_wCon
:
1440 gen_op_iwmmxt_set_cup();
1442 case ARM_IWMMXT_wCSSF
:
1443 tmp
= iwmmxt_load_creg(wrd
);
1444 tmp2
= load_reg(s
, rd
);
1445 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
1447 iwmmxt_store_creg(wrd
, tmp
);
1449 case ARM_IWMMXT_wCGR0
:
1450 case ARM_IWMMXT_wCGR1
:
1451 case ARM_IWMMXT_wCGR2
:
1452 case ARM_IWMMXT_wCGR3
:
1453 gen_op_iwmmxt_set_cup();
1454 tmp
= load_reg(s
, rd
);
1455 iwmmxt_store_creg(wrd
, tmp
);
1461 case 0x100: /* WXOR */
1462 wrd
= (insn
>> 12) & 0xf;
1463 rd0
= (insn
>> 0) & 0xf;
1464 rd1
= (insn
>> 16) & 0xf;
1465 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1466 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1467 gen_op_iwmmxt_setpsr_nz();
1468 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1469 gen_op_iwmmxt_set_mup();
1470 gen_op_iwmmxt_set_cup();
1472 case 0x111: /* TMRC */
1475 rd
= (insn
>> 12) & 0xf;
1476 wrd
= (insn
>> 16) & 0xf;
1477 tmp
= iwmmxt_load_creg(wrd
);
1478 store_reg(s
, rd
, tmp
);
1480 case 0x300: /* WANDN */
1481 wrd
= (insn
>> 12) & 0xf;
1482 rd0
= (insn
>> 0) & 0xf;
1483 rd1
= (insn
>> 16) & 0xf;
1484 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1485 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1486 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1487 gen_op_iwmmxt_setpsr_nz();
1488 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1489 gen_op_iwmmxt_set_mup();
1490 gen_op_iwmmxt_set_cup();
1492 case 0x200: /* WAND */
1493 wrd
= (insn
>> 12) & 0xf;
1494 rd0
= (insn
>> 0) & 0xf;
1495 rd1
= (insn
>> 16) & 0xf;
1496 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1497 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1498 gen_op_iwmmxt_setpsr_nz();
1499 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1500 gen_op_iwmmxt_set_mup();
1501 gen_op_iwmmxt_set_cup();
1503 case 0x810: case 0xa10: /* WMADD */
1504 wrd
= (insn
>> 12) & 0xf;
1505 rd0
= (insn
>> 0) & 0xf;
1506 rd1
= (insn
>> 16) & 0xf;
1507 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1508 if (insn
& (1 << 21))
1509 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1511 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1512 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1513 gen_op_iwmmxt_set_mup();
1515 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1516 wrd
= (insn
>> 12) & 0xf;
1517 rd0
= (insn
>> 16) & 0xf;
1518 rd1
= (insn
>> 0) & 0xf;
1519 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1520 switch ((insn
>> 22) & 3) {
1522 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1525 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1528 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1533 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1534 gen_op_iwmmxt_set_mup();
1535 gen_op_iwmmxt_set_cup();
1537 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1538 wrd
= (insn
>> 12) & 0xf;
1539 rd0
= (insn
>> 16) & 0xf;
1540 rd1
= (insn
>> 0) & 0xf;
1541 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1542 switch ((insn
>> 22) & 3) {
1544 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1547 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1550 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1555 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1556 gen_op_iwmmxt_set_mup();
1557 gen_op_iwmmxt_set_cup();
1559 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1560 wrd
= (insn
>> 12) & 0xf;
1561 rd0
= (insn
>> 16) & 0xf;
1562 rd1
= (insn
>> 0) & 0xf;
1563 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1564 if (insn
& (1 << 22))
1565 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1567 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1568 if (!(insn
& (1 << 20)))
1569 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1570 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1571 gen_op_iwmmxt_set_mup();
1573 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1574 wrd
= (insn
>> 12) & 0xf;
1575 rd0
= (insn
>> 16) & 0xf;
1576 rd1
= (insn
>> 0) & 0xf;
1577 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1578 if (insn
& (1 << 21)) {
1579 if (insn
& (1 << 20))
1580 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1582 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1584 if (insn
& (1 << 20))
1585 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1587 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1589 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1590 gen_op_iwmmxt_set_mup();
1592 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1593 wrd
= (insn
>> 12) & 0xf;
1594 rd0
= (insn
>> 16) & 0xf;
1595 rd1
= (insn
>> 0) & 0xf;
1596 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1597 if (insn
& (1 << 21))
1598 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1600 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1601 if (!(insn
& (1 << 20))) {
1602 iwmmxt_load_reg(cpu_V1
, wrd
);
1603 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1605 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1606 gen_op_iwmmxt_set_mup();
1608 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1609 wrd
= (insn
>> 12) & 0xf;
1610 rd0
= (insn
>> 16) & 0xf;
1611 rd1
= (insn
>> 0) & 0xf;
1612 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1613 switch ((insn
>> 22) & 3) {
1615 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1618 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1621 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1626 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1627 gen_op_iwmmxt_set_mup();
1628 gen_op_iwmmxt_set_cup();
1630 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1631 wrd
= (insn
>> 12) & 0xf;
1632 rd0
= (insn
>> 16) & 0xf;
1633 rd1
= (insn
>> 0) & 0xf;
1634 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1635 if (insn
& (1 << 22)) {
1636 if (insn
& (1 << 20))
1637 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1639 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1641 if (insn
& (1 << 20))
1642 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1644 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1646 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1647 gen_op_iwmmxt_set_mup();
1648 gen_op_iwmmxt_set_cup();
1650 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1651 wrd
= (insn
>> 12) & 0xf;
1652 rd0
= (insn
>> 16) & 0xf;
1653 rd1
= (insn
>> 0) & 0xf;
1654 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1655 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1656 tcg_gen_andi_i32(tmp
, tmp
, 7);
1657 iwmmxt_load_reg(cpu_V1
, rd1
);
1658 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1660 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1661 gen_op_iwmmxt_set_mup();
1663 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1664 if (((insn
>> 6) & 3) == 3)
1666 rd
= (insn
>> 12) & 0xf;
1667 wrd
= (insn
>> 16) & 0xf;
1668 tmp
= load_reg(s
, rd
);
1669 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1670 switch ((insn
>> 6) & 3) {
1672 tmp2
= tcg_const_i32(0xff);
1673 tmp3
= tcg_const_i32((insn
& 7) << 3);
1676 tmp2
= tcg_const_i32(0xffff);
1677 tmp3
= tcg_const_i32((insn
& 3) << 4);
1680 tmp2
= tcg_const_i32(0xffffffff);
1681 tmp3
= tcg_const_i32((insn
& 1) << 5);
1687 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1688 tcg_temp_free(tmp3
);
1689 tcg_temp_free(tmp2
);
1691 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1692 gen_op_iwmmxt_set_mup();
1694 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1695 rd
= (insn
>> 12) & 0xf;
1696 wrd
= (insn
>> 16) & 0xf;
1697 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1699 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1701 switch ((insn
>> 22) & 3) {
1703 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1704 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1706 tcg_gen_ext8s_i32(tmp
, tmp
);
1708 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1712 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1713 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1715 tcg_gen_ext16s_i32(tmp
, tmp
);
1717 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1721 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1722 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1725 store_reg(s
, rd
, tmp
);
1727 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1728 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1730 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1731 switch ((insn
>> 22) & 3) {
1733 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1736 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1739 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1742 tcg_gen_shli_i32(tmp
, tmp
, 28);
1746 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1747 if (((insn
>> 6) & 3) == 3)
1749 rd
= (insn
>> 12) & 0xf;
1750 wrd
= (insn
>> 16) & 0xf;
1751 tmp
= load_reg(s
, rd
);
1752 switch ((insn
>> 6) & 3) {
1754 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1757 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1760 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1764 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1765 gen_op_iwmmxt_set_mup();
1767 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1768 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1770 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1772 tcg_gen_mov_i32(tmp2
, tmp
);
1773 switch ((insn
>> 22) & 3) {
1775 for (i
= 0; i
< 7; i
++) {
1776 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1777 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1781 for (i
= 0; i
< 3; i
++) {
1782 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1783 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1787 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1788 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1795 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1796 wrd
= (insn
>> 12) & 0xf;
1797 rd0
= (insn
>> 16) & 0xf;
1798 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1799 switch ((insn
>> 22) & 3) {
1801 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1804 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1807 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1812 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1813 gen_op_iwmmxt_set_mup();
1815 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1816 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1818 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1820 tcg_gen_mov_i32(tmp2
, tmp
);
1821 switch ((insn
>> 22) & 3) {
1823 for (i
= 0; i
< 7; i
++) {
1824 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1825 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1829 for (i
= 0; i
< 3; i
++) {
1830 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1831 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1835 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1836 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1843 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1844 rd
= (insn
>> 12) & 0xf;
1845 rd0
= (insn
>> 16) & 0xf;
1846 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1848 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1850 switch ((insn
>> 22) & 3) {
1852 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1855 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1858 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1861 store_reg(s
, rd
, tmp
);
1863 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1864 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1865 wrd
= (insn
>> 12) & 0xf;
1866 rd0
= (insn
>> 16) & 0xf;
1867 rd1
= (insn
>> 0) & 0xf;
1868 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1869 switch ((insn
>> 22) & 3) {
1871 if (insn
& (1 << 21))
1872 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1874 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1877 if (insn
& (1 << 21))
1878 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1880 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1883 if (insn
& (1 << 21))
1884 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1886 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1891 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1892 gen_op_iwmmxt_set_mup();
1893 gen_op_iwmmxt_set_cup();
1895 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1896 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1897 wrd
= (insn
>> 12) & 0xf;
1898 rd0
= (insn
>> 16) & 0xf;
1899 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1900 switch ((insn
>> 22) & 3) {
1902 if (insn
& (1 << 21))
1903 gen_op_iwmmxt_unpacklsb_M0();
1905 gen_op_iwmmxt_unpacklub_M0();
1908 if (insn
& (1 << 21))
1909 gen_op_iwmmxt_unpacklsw_M0();
1911 gen_op_iwmmxt_unpackluw_M0();
1914 if (insn
& (1 << 21))
1915 gen_op_iwmmxt_unpacklsl_M0();
1917 gen_op_iwmmxt_unpacklul_M0();
1922 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1923 gen_op_iwmmxt_set_mup();
1924 gen_op_iwmmxt_set_cup();
1926 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1927 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1928 wrd
= (insn
>> 12) & 0xf;
1929 rd0
= (insn
>> 16) & 0xf;
1930 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1931 switch ((insn
>> 22) & 3) {
1933 if (insn
& (1 << 21))
1934 gen_op_iwmmxt_unpackhsb_M0();
1936 gen_op_iwmmxt_unpackhub_M0();
1939 if (insn
& (1 << 21))
1940 gen_op_iwmmxt_unpackhsw_M0();
1942 gen_op_iwmmxt_unpackhuw_M0();
1945 if (insn
& (1 << 21))
1946 gen_op_iwmmxt_unpackhsl_M0();
1948 gen_op_iwmmxt_unpackhul_M0();
1953 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1954 gen_op_iwmmxt_set_mup();
1955 gen_op_iwmmxt_set_cup();
1957 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1958 case 0x214: case 0x614: case 0xa14: case 0xe14:
1959 if (((insn
>> 22) & 3) == 0)
1961 wrd
= (insn
>> 12) & 0xf;
1962 rd0
= (insn
>> 16) & 0xf;
1963 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1965 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1969 switch ((insn
>> 22) & 3) {
1971 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1974 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1977 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1981 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1982 gen_op_iwmmxt_set_mup();
1983 gen_op_iwmmxt_set_cup();
1985 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1986 case 0x014: case 0x414: case 0x814: case 0xc14:
1987 if (((insn
>> 22) & 3) == 0)
1989 wrd
= (insn
>> 12) & 0xf;
1990 rd0
= (insn
>> 16) & 0xf;
1991 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1993 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1997 switch ((insn
>> 22) & 3) {
1999 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2002 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2005 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2009 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2010 gen_op_iwmmxt_set_mup();
2011 gen_op_iwmmxt_set_cup();
2013 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2014 case 0x114: case 0x514: case 0x914: case 0xd14:
2015 if (((insn
>> 22) & 3) == 0)
2017 wrd
= (insn
>> 12) & 0xf;
2018 rd0
= (insn
>> 16) & 0xf;
2019 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2021 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2025 switch ((insn
>> 22) & 3) {
2027 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2030 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2033 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2037 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2038 gen_op_iwmmxt_set_mup();
2039 gen_op_iwmmxt_set_cup();
2041 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2042 case 0x314: case 0x714: case 0xb14: case 0xf14:
2043 if (((insn
>> 22) & 3) == 0)
2045 wrd
= (insn
>> 12) & 0xf;
2046 rd0
= (insn
>> 16) & 0xf;
2047 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2049 switch ((insn
>> 22) & 3) {
2051 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2055 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2058 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2062 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2065 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2069 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2073 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2074 gen_op_iwmmxt_set_mup();
2075 gen_op_iwmmxt_set_cup();
2077 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2078 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2079 wrd
= (insn
>> 12) & 0xf;
2080 rd0
= (insn
>> 16) & 0xf;
2081 rd1
= (insn
>> 0) & 0xf;
2082 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2083 switch ((insn
>> 22) & 3) {
2085 if (insn
& (1 << 21))
2086 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2088 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2091 if (insn
& (1 << 21))
2092 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2094 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2097 if (insn
& (1 << 21))
2098 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2100 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2105 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2106 gen_op_iwmmxt_set_mup();
2108 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2109 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2110 wrd
= (insn
>> 12) & 0xf;
2111 rd0
= (insn
>> 16) & 0xf;
2112 rd1
= (insn
>> 0) & 0xf;
2113 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2114 switch ((insn
>> 22) & 3) {
2116 if (insn
& (1 << 21))
2117 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2119 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2122 if (insn
& (1 << 21))
2123 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2125 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2128 if (insn
& (1 << 21))
2129 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2131 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2136 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2137 gen_op_iwmmxt_set_mup();
2139 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2140 case 0x402: case 0x502: case 0x602: case 0x702:
2141 wrd
= (insn
>> 12) & 0xf;
2142 rd0
= (insn
>> 16) & 0xf;
2143 rd1
= (insn
>> 0) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2145 tmp
= tcg_const_i32((insn
>> 20) & 3);
2146 iwmmxt_load_reg(cpu_V1
, rd1
);
2147 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2149 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2150 gen_op_iwmmxt_set_mup();
2152 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2153 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2154 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2155 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2156 wrd
= (insn
>> 12) & 0xf;
2157 rd0
= (insn
>> 16) & 0xf;
2158 rd1
= (insn
>> 0) & 0xf;
2159 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2160 switch ((insn
>> 20) & 0xf) {
2162 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2165 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2168 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2171 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2174 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2177 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2180 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2183 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2186 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2191 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2192 gen_op_iwmmxt_set_mup();
2193 gen_op_iwmmxt_set_cup();
2195 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2196 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2197 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2198 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2199 wrd
= (insn
>> 12) & 0xf;
2200 rd0
= (insn
>> 16) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2202 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2203 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2205 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2206 gen_op_iwmmxt_set_mup();
2207 gen_op_iwmmxt_set_cup();
2209 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2210 case 0x418: case 0x518: case 0x618: case 0x718:
2211 case 0x818: case 0x918: case 0xa18: case 0xb18:
2212 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2213 wrd
= (insn
>> 12) & 0xf;
2214 rd0
= (insn
>> 16) & 0xf;
2215 rd1
= (insn
>> 0) & 0xf;
2216 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2217 switch ((insn
>> 20) & 0xf) {
2219 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2222 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2225 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2228 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2231 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2234 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2237 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2240 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2243 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2248 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2249 gen_op_iwmmxt_set_mup();
2250 gen_op_iwmmxt_set_cup();
2252 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2253 case 0x408: case 0x508: case 0x608: case 0x708:
2254 case 0x808: case 0x908: case 0xa08: case 0xb08:
2255 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2256 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2258 wrd
= (insn
>> 12) & 0xf;
2259 rd0
= (insn
>> 16) & 0xf;
2260 rd1
= (insn
>> 0) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2262 switch ((insn
>> 22) & 3) {
2264 if (insn
& (1 << 21))
2265 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2267 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2270 if (insn
& (1 << 21))
2271 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2273 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2276 if (insn
& (1 << 21))
2277 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2279 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2282 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2283 gen_op_iwmmxt_set_mup();
2284 gen_op_iwmmxt_set_cup();
2286 case 0x201: case 0x203: case 0x205: case 0x207:
2287 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2288 case 0x211: case 0x213: case 0x215: case 0x217:
2289 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2290 wrd
= (insn
>> 5) & 0xf;
2291 rd0
= (insn
>> 12) & 0xf;
2292 rd1
= (insn
>> 0) & 0xf;
2293 if (rd0
== 0xf || rd1
== 0xf)
2295 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2296 tmp
= load_reg(s
, rd0
);
2297 tmp2
= load_reg(s
, rd1
);
2298 switch ((insn
>> 16) & 0xf) {
2299 case 0x0: /* TMIA */
2300 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2302 case 0x8: /* TMIAPH */
2303 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2305 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2306 if (insn
& (1 << 16))
2307 tcg_gen_shri_i32(tmp
, tmp
, 16);
2308 if (insn
& (1 << 17))
2309 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2310 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2319 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2320 gen_op_iwmmxt_set_mup();
2329 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2330 (ie. an undefined instruction). */
2331 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2333 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2336 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2337 /* Multiply with Internal Accumulate Format */
2338 rd0
= (insn
>> 12) & 0xf;
2340 acc
= (insn
>> 5) & 7;
2345 tmp
= load_reg(s
, rd0
);
2346 tmp2
= load_reg(s
, rd1
);
2347 switch ((insn
>> 16) & 0xf) {
2349 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2351 case 0x8: /* MIAPH */
2352 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2354 case 0xc: /* MIABB */
2355 case 0xd: /* MIABT */
2356 case 0xe: /* MIATB */
2357 case 0xf: /* MIATT */
2358 if (insn
& (1 << 16))
2359 tcg_gen_shri_i32(tmp
, tmp
, 16);
2360 if (insn
& (1 << 17))
2361 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2362 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2370 gen_op_iwmmxt_movq_wRn_M0(acc
);
2374 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2375 /* Internal Accumulator Access Format */
2376 rdhi
= (insn
>> 16) & 0xf;
2377 rdlo
= (insn
>> 12) & 0xf;
2383 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2384 iwmmxt_load_reg(cpu_V0
, acc
);
2385 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2386 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2387 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2388 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2390 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2391 iwmmxt_store_reg(cpu_V0
, acc
);
2399 /* Disassemble system coprocessor instruction. Return nonzero if
2400 instruction is not defined. */
2401 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2404 uint32_t rd
= (insn
>> 12) & 0xf;
2405 uint32_t cp
= (insn
>> 8) & 0xf;
2410 if (insn
& ARM_CP_RW_BIT
) {
2411 if (!env
->cp
[cp
].cp_read
)
2413 gen_set_pc_im(s
->pc
);
2415 tmp2
= tcg_const_i32(insn
);
2416 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2417 tcg_temp_free(tmp2
);
2418 store_reg(s
, rd
, tmp
);
2420 if (!env
->cp
[cp
].cp_write
)
2422 gen_set_pc_im(s
->pc
);
2423 tmp
= load_reg(s
, rd
);
2424 tmp2
= tcg_const_i32(insn
);
2425 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2426 tcg_temp_free(tmp2
);
2432 static int cp15_user_ok(uint32_t insn
)
2434 int cpn
= (insn
>> 16) & 0xf;
2435 int cpm
= insn
& 0xf;
2436 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2438 if (cpn
== 13 && cpm
== 0) {
2440 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2444 /* ISB, DSB, DMB. */
2445 if ((cpm
== 5 && op
== 4)
2446 || (cpm
== 10 && (op
== 4 || op
== 5)))
2452 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2453 instruction is not defined. */
2454 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2459 /* M profile cores use memory mapped registers instead of cp15. */
2460 if (arm_feature(env
, ARM_FEATURE_M
))
2463 if ((insn
& (1 << 25)) == 0) {
2464 if (insn
& (1 << 20)) {
2468 /* mcrr. Used for block cache operations, so implement as no-op. */
2471 if ((insn
& (1 << 4)) == 0) {
2475 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2478 if ((insn
& 0x0fff0fff) == 0x0e070f90
2479 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2480 /* Wait for interrupt. */
2481 gen_set_pc_im(s
->pc
);
2482 s
->is_jmp
= DISAS_WFI
;
2485 rd
= (insn
>> 12) & 0xf;
2486 tmp2
= tcg_const_i32(insn
);
2487 if (insn
& ARM_CP_RW_BIT
) {
2489 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2490 /* If the destination register is r15 then sets condition codes. */
2492 store_reg(s
, rd
, tmp
);
2496 tmp
= load_reg(s
, rd
);
2497 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2499 /* Normally we would always end the TB here, but Linux
2500 * arch/arm/mach-pxa/sleep.S expects two instructions following
2501 * an MMU enable to execute from cache. Imitate this behaviour. */
2502 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2503 (insn
& 0x0fff0fff) != 0x0e010f10)
2506 tcg_temp_free_i32(tmp2
);
2510 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2511 #define VFP_SREG(insn, bigbit, smallbit) \
2512 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2513 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2514 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2515 reg = (((insn) >> (bigbit)) & 0x0f) \
2516 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2518 if (insn & (1 << (smallbit))) \
2520 reg = ((insn) >> (bigbit)) & 0x0f; \
2523 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2524 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2525 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2526 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2527 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2528 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2530 /* Move between integer and VFP cores. */
2531 static TCGv
gen_vfp_mrs(void)
2533 TCGv tmp
= new_tmp();
2534 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2538 static void gen_vfp_msr(TCGv tmp
)
2540 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2545 vfp_enabled(CPUState
* env
)
2547 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2550 static void gen_neon_dup_u8(TCGv var
, int shift
)
2552 TCGv tmp
= new_tmp();
2554 tcg_gen_shri_i32(var
, var
, shift
);
2555 tcg_gen_ext8u_i32(var
, var
);
2556 tcg_gen_shli_i32(tmp
, var
, 8);
2557 tcg_gen_or_i32(var
, var
, tmp
);
2558 tcg_gen_shli_i32(tmp
, var
, 16);
2559 tcg_gen_or_i32(var
, var
, tmp
);
2563 static void gen_neon_dup_low16(TCGv var
)
2565 TCGv tmp
= new_tmp();
2566 tcg_gen_ext16u_i32(var
, var
);
2567 tcg_gen_shli_i32(tmp
, var
, 16);
2568 tcg_gen_or_i32(var
, var
, tmp
);
2572 static void gen_neon_dup_high16(TCGv var
)
2574 TCGv tmp
= new_tmp();
2575 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2576 tcg_gen_shri_i32(tmp
, var
, 16);
2577 tcg_gen_or_i32(var
, var
, tmp
);
2581 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2582 (ie. an undefined instruction). */
2583 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2585 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2591 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2594 if (!vfp_enabled(env
)) {
2595 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2596 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2598 rn
= (insn
>> 16) & 0xf;
2599 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2600 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2603 dp
= ((insn
& 0xf00) == 0xb00);
2604 switch ((insn
>> 24) & 0xf) {
2606 if (insn
& (1 << 4)) {
2607 /* single register transfer */
2608 rd
= (insn
>> 12) & 0xf;
2613 VFP_DREG_N(rn
, insn
);
2616 if (insn
& 0x00c00060
2617 && !arm_feature(env
, ARM_FEATURE_NEON
))
2620 pass
= (insn
>> 21) & 1;
2621 if (insn
& (1 << 22)) {
2623 offset
= ((insn
>> 5) & 3) * 8;
2624 } else if (insn
& (1 << 5)) {
2626 offset
= (insn
& (1 << 6)) ? 16 : 0;
2631 if (insn
& ARM_CP_RW_BIT
) {
2633 tmp
= neon_load_reg(rn
, pass
);
2637 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2638 if (insn
& (1 << 23))
2644 if (insn
& (1 << 23)) {
2646 tcg_gen_shri_i32(tmp
, tmp
, 16);
2652 tcg_gen_sari_i32(tmp
, tmp
, 16);
2661 store_reg(s
, rd
, tmp
);
2664 tmp
= load_reg(s
, rd
);
2665 if (insn
& (1 << 23)) {
2668 gen_neon_dup_u8(tmp
, 0);
2669 } else if (size
== 1) {
2670 gen_neon_dup_low16(tmp
);
2672 for (n
= 0; n
<= pass
* 2; n
++) {
2674 tcg_gen_mov_i32(tmp2
, tmp
);
2675 neon_store_reg(rn
, n
, tmp2
);
2677 neon_store_reg(rn
, n
, tmp
);
2682 tmp2
= neon_load_reg(rn
, pass
);
2683 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2687 tmp2
= neon_load_reg(rn
, pass
);
2688 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2694 neon_store_reg(rn
, pass
, tmp
);
2698 if ((insn
& 0x6f) != 0x00)
2700 rn
= VFP_SREG_N(insn
);
2701 if (insn
& ARM_CP_RW_BIT
) {
2703 if (insn
& (1 << 21)) {
2704 /* system register */
2709 /* VFP2 allows access to FSID from userspace.
2710 VFP3 restricts all id registers to privileged
2713 && arm_feature(env
, ARM_FEATURE_VFP3
))
2715 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2720 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2722 case ARM_VFP_FPINST
:
2723 case ARM_VFP_FPINST2
:
2724 /* Not present in VFP3. */
2726 || arm_feature(env
, ARM_FEATURE_VFP3
))
2728 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2732 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2733 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2736 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2742 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2744 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2750 gen_mov_F0_vreg(0, rn
);
2751 tmp
= gen_vfp_mrs();
2754 /* Set the 4 flag bits in the CPSR. */
2758 store_reg(s
, rd
, tmp
);
2762 tmp
= load_reg(s
, rd
);
2763 if (insn
& (1 << 21)) {
2765 /* system register */
2770 /* Writes are ignored. */
2773 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2780 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2783 case ARM_VFP_FPINST
:
2784 case ARM_VFP_FPINST2
:
2785 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2792 gen_mov_vreg_F0(0, rn
);
2797 /* data processing */
2798 /* The opcode is in bits 23, 21, 20 and 6. */
2799 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2803 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2805 /* rn is register number */
2806 VFP_DREG_N(rn
, insn
);
2809 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2810 /* Integer or single precision destination. */
2811 rd
= VFP_SREG_D(insn
);
2813 VFP_DREG_D(rd
, insn
);
2816 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2817 /* Integer source. */
2818 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2820 VFP_DREG_M(rm
, insn
);
2823 rn
= VFP_SREG_N(insn
);
2824 if (op
== 15 && rn
== 15) {
2825 /* Double precision destination. */
2826 VFP_DREG_D(rd
, insn
);
2828 rd
= VFP_SREG_D(insn
);
2830 rm
= VFP_SREG_M(insn
);
2833 veclen
= env
->vfp
.vec_len
;
2834 if (op
== 15 && rn
> 3)
2837 /* Shut up compiler warnings. */
2848 /* Figure out what type of vector operation this is. */
2849 if ((rd
& bank_mask
) == 0) {
2854 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2856 delta_d
= env
->vfp
.vec_stride
+ 1;
2858 if ((rm
& bank_mask
) == 0) {
2859 /* mixed scalar/vector */
2868 /* Load the initial operands. */
2873 /* Integer source */
2874 gen_mov_F0_vreg(0, rm
);
2879 gen_mov_F0_vreg(dp
, rd
);
2880 gen_mov_F1_vreg(dp
, rm
);
2884 /* Compare with zero */
2885 gen_mov_F0_vreg(dp
, rd
);
2896 /* Source and destination the same. */
2897 gen_mov_F0_vreg(dp
, rd
);
2900 /* One source operand. */
2901 gen_mov_F0_vreg(dp
, rm
);
2905 /* Two source operands. */
2906 gen_mov_F0_vreg(dp
, rn
);
2907 gen_mov_F1_vreg(dp
, rm
);
2911 /* Perform the calculation. */
2913 case 0: /* mac: fd + (fn * fm) */
2915 gen_mov_F1_vreg(dp
, rd
);
2918 case 1: /* nmac: fd - (fn * fm) */
2921 gen_mov_F1_vreg(dp
, rd
);
2924 case 2: /* msc: -fd + (fn * fm) */
2926 gen_mov_F1_vreg(dp
, rd
);
2929 case 3: /* nmsc: -fd - (fn * fm) */
2932 gen_mov_F1_vreg(dp
, rd
);
2935 case 4: /* mul: fn * fm */
2938 case 5: /* nmul: -(fn * fm) */
2942 case 6: /* add: fn + fm */
2945 case 7: /* sub: fn - fm */
2948 case 8: /* div: fn / fm */
2951 case 14: /* fconst */
2952 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2955 n
= (insn
<< 12) & 0x80000000;
2956 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2963 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
2970 tcg_gen_movi_i32(cpu_F0s
, n
);
2973 case 15: /* extension space */
2996 case 11: /* cmpez */
3000 case 15: /* single<->double conversion */
3002 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3004 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3006 case 16: /* fuito */
3009 case 17: /* fsito */
3012 case 20: /* fshto */
3013 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3015 gen_vfp_shto(dp
, 16 - rm
);
3017 case 21: /* fslto */
3018 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3020 gen_vfp_slto(dp
, 32 - rm
);
3022 case 22: /* fuhto */
3023 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3025 gen_vfp_uhto(dp
, 16 - rm
);
3027 case 23: /* fulto */
3028 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3030 gen_vfp_ulto(dp
, 32 - rm
);
3032 case 24: /* ftoui */
3035 case 25: /* ftouiz */
3038 case 26: /* ftosi */
3041 case 27: /* ftosiz */
3044 case 28: /* ftosh */
3045 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3047 gen_vfp_tosh(dp
, 16 - rm
);
3049 case 29: /* ftosl */
3050 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3052 gen_vfp_tosl(dp
, 32 - rm
);
3054 case 30: /* ftouh */
3055 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3057 gen_vfp_touh(dp
, 16 - rm
);
3059 case 31: /* ftoul */
3060 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3062 gen_vfp_toul(dp
, 32 - rm
);
3064 default: /* undefined */
3065 printf ("rn:%d\n", rn
);
3069 default: /* undefined */
3070 printf ("op:%d\n", op
);
3074 /* Write back the result. */
3075 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3076 ; /* Comparison, do nothing. */
3077 else if (op
== 15 && rn
> 17)
3078 /* Integer result. */
3079 gen_mov_vreg_F0(0, rd
);
3080 else if (op
== 15 && rn
== 15)
3082 gen_mov_vreg_F0(!dp
, rd
);
3084 gen_mov_vreg_F0(dp
, rd
);
3086 /* break out of the loop if we have finished */
3090 if (op
== 15 && delta_m
== 0) {
3091 /* single source one-many */
3093 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3095 gen_mov_vreg_F0(dp
, rd
);
3099 /* Setup the next operands. */
3101 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3105 /* One source operand. */
3106 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3108 gen_mov_F0_vreg(dp
, rm
);
3110 /* Two source operands. */
3111 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3113 gen_mov_F0_vreg(dp
, rn
);
3115 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3117 gen_mov_F1_vreg(dp
, rm
);
3125 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3126 /* two-register transfer */
3127 rn
= (insn
>> 16) & 0xf;
3128 rd
= (insn
>> 12) & 0xf;
3130 VFP_DREG_M(rm
, insn
);
3132 rm
= VFP_SREG_M(insn
);
3135 if (insn
& ARM_CP_RW_BIT
) {
3138 gen_mov_F0_vreg(0, rm
* 2);
3139 tmp
= gen_vfp_mrs();
3140 store_reg(s
, rd
, tmp
);
3141 gen_mov_F0_vreg(0, rm
* 2 + 1);
3142 tmp
= gen_vfp_mrs();
3143 store_reg(s
, rn
, tmp
);
3145 gen_mov_F0_vreg(0, rm
);
3146 tmp
= gen_vfp_mrs();
3147 store_reg(s
, rn
, tmp
);
3148 gen_mov_F0_vreg(0, rm
+ 1);
3149 tmp
= gen_vfp_mrs();
3150 store_reg(s
, rd
, tmp
);
3155 tmp
= load_reg(s
, rd
);
3157 gen_mov_vreg_F0(0, rm
* 2);
3158 tmp
= load_reg(s
, rn
);
3160 gen_mov_vreg_F0(0, rm
* 2 + 1);
3162 tmp
= load_reg(s
, rn
);
3164 gen_mov_vreg_F0(0, rm
);
3165 tmp
= load_reg(s
, rd
);
3167 gen_mov_vreg_F0(0, rm
+ 1);
3172 rn
= (insn
>> 16) & 0xf;
3174 VFP_DREG_D(rd
, insn
);
3176 rd
= VFP_SREG_D(insn
);
3177 if (s
->thumb
&& rn
== 15) {
3179 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3181 addr
= load_reg(s
, rn
);
3183 if ((insn
& 0x01200000) == 0x01000000) {
3184 /* Single load/store */
3185 offset
= (insn
& 0xff) << 2;
3186 if ((insn
& (1 << 23)) == 0)
3188 tcg_gen_addi_i32(addr
, addr
, offset
);
3189 if (insn
& (1 << 20)) {
3190 gen_vfp_ld(s
, dp
, addr
);
3191 gen_mov_vreg_F0(dp
, rd
);
3193 gen_mov_F0_vreg(dp
, rd
);
3194 gen_vfp_st(s
, dp
, addr
);
3198 /* load/store multiple */
3200 n
= (insn
>> 1) & 0x7f;
3204 if (insn
& (1 << 24)) /* pre-decrement */
3205 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3211 for (i
= 0; i
< n
; i
++) {
3212 if (insn
& ARM_CP_RW_BIT
) {
3214 gen_vfp_ld(s
, dp
, addr
);
3215 gen_mov_vreg_F0(dp
, rd
+ i
);
3218 gen_mov_F0_vreg(dp
, rd
+ i
);
3219 gen_vfp_st(s
, dp
, addr
);
3221 tcg_gen_addi_i32(addr
, addr
, offset
);
3223 if (insn
& (1 << 21)) {
3225 if (insn
& (1 << 24))
3226 offset
= -offset
* n
;
3227 else if (dp
&& (insn
& 1))
3233 tcg_gen_addi_i32(addr
, addr
, offset
);
3234 store_reg(s
, rn
, addr
);
3242 /* Should never happen. */
3248 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3250 TranslationBlock
*tb
;
3253 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3255 gen_set_pc_im(dest
);
3256 tcg_gen_exit_tb((long)tb
+ n
);
3258 gen_set_pc_im(dest
);
3263 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3265 if (unlikely(s
->singlestep_enabled
)) {
3266 /* An indirect jump so that we still trigger the debug exception. */
3271 gen_goto_tb(s
, 0, dest
);
3272 s
->is_jmp
= DISAS_TB_JUMP
;
3276 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3279 tcg_gen_sari_i32(t0
, t0
, 16);
3283 tcg_gen_sari_i32(t1
, t1
, 16);
3286 tcg_gen_mul_i32(t0
, t0
, t1
);
3289 /* Return the mask of PSR bits set by a MSR instruction. */
3290 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3294 if (flags
& (1 << 0))
3296 if (flags
& (1 << 1))
3298 if (flags
& (1 << 2))
3300 if (flags
& (1 << 3))
3303 /* Mask out undefined bits. */
3304 mask
&= ~CPSR_RESERVED
;
3305 if (!arm_feature(env
, ARM_FEATURE_V6
))
3306 mask
&= ~(CPSR_E
| CPSR_GE
);
3307 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3309 /* Mask out execution state bits. */
3312 /* Mask out privileged bits. */
3318 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3319 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3323 /* ??? This is also undefined in system mode. */
3327 tmp
= load_cpu_field(spsr
);
3328 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3329 tcg_gen_andi_i32(t0
, t0
, mask
);
3330 tcg_gen_or_i32(tmp
, tmp
, t0
);
3331 store_cpu_field(tmp
, spsr
);
3333 gen_set_cpsr(t0
, mask
);
3340 /* Returns nonzero if access to the PSR is not permitted. */
3341 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3345 tcg_gen_movi_i32(tmp
, val
);
3346 return gen_set_psr(s
, mask
, spsr
, tmp
);
3349 /* Generate an old-style exception return. Marks pc as dead. */
3350 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3353 store_reg(s
, 15, pc
);
3354 tmp
= load_cpu_field(spsr
);
3355 gen_set_cpsr(tmp
, 0xffffffff);
3357 s
->is_jmp
= DISAS_UPDATE
;
3360 /* Generate a v6 exception return. Marks both values as dead. */
3361 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3363 gen_set_cpsr(cpsr
, 0xffffffff);
3365 store_reg(s
, 15, pc
);
3366 s
->is_jmp
= DISAS_UPDATE
;
3370 gen_set_condexec (DisasContext
*s
)
3372 if (s
->condexec_mask
) {
3373 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3374 TCGv tmp
= new_tmp();
3375 tcg_gen_movi_i32(tmp
, val
);
3376 store_cpu_field(tmp
, condexec_bits
);
3380 static void gen_nop_hint(DisasContext
*s
, int val
)
3384 gen_set_pc_im(s
->pc
);
3385 s
->is_jmp
= DISAS_WFI
;
3389 /* TODO: Implement SEV and WFE. May help SMP performance. */
3395 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3397 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3400 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3401 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3402 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3408 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3411 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3412 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3413 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3418 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3419 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3420 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3421 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3422 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3424 /* FIXME: This is wrong. They set the wrong overflow bit. */
3425 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3426 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3427 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3428 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3430 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3431 switch ((size << 1) | u) { \
3433 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3436 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3439 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3442 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3445 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3448 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3450 default: return 1; \
3453 #define GEN_NEON_INTEGER_OP(name) do { \
3454 switch ((size << 1) | u) { \
3456 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3459 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3462 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3465 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3468 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3471 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3473 default: return 1; \
3476 static TCGv
neon_load_scratch(int scratch
)
3478 TCGv tmp
= new_tmp();
3479 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3483 static void neon_store_scratch(int scratch
, TCGv var
)
3485 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3489 static inline TCGv
neon_get_scalar(int size
, int reg
)
3493 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3495 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3497 gen_neon_dup_low16(tmp
);
3499 gen_neon_dup_high16(tmp
);
3505 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3513 tcg_gen_andi_i32(rd
, t0
, 0xff);
3514 tcg_gen_shri_i32(tmp
, t0
, 8);
3515 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3516 tcg_gen_or_i32(rd
, rd
, tmp
);
3517 tcg_gen_shli_i32(tmp
, t1
, 16);
3518 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3519 tcg_gen_or_i32(rd
, rd
, tmp
);
3520 tcg_gen_shli_i32(tmp
, t1
, 8);
3521 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3522 tcg_gen_or_i32(rd
, rd
, tmp
);
3524 tcg_gen_shri_i32(rm
, t0
, 8);
3525 tcg_gen_andi_i32(rm
, rm
, 0xff);
3526 tcg_gen_shri_i32(tmp
, t0
, 16);
3527 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3528 tcg_gen_or_i32(rm
, rm
, tmp
);
3529 tcg_gen_shli_i32(tmp
, t1
, 8);
3530 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3531 tcg_gen_or_i32(rm
, rm
, tmp
);
3532 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3533 tcg_gen_or_i32(t1
, rm
, tmp
);
3534 tcg_gen_mov_i32(t0
, rd
);
3541 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3549 tcg_gen_andi_i32(rd
, t0
, 0xff);
3550 tcg_gen_shli_i32(tmp
, t1
, 8);
3551 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3552 tcg_gen_or_i32(rd
, rd
, tmp
);
3553 tcg_gen_shli_i32(tmp
, t0
, 16);
3554 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3555 tcg_gen_or_i32(rd
, rd
, tmp
);
3556 tcg_gen_shli_i32(tmp
, t1
, 24);
3557 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3558 tcg_gen_or_i32(rd
, rd
, tmp
);
3560 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3561 tcg_gen_shri_i32(tmp
, t0
, 8);
3562 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3563 tcg_gen_or_i32(rm
, rm
, tmp
);
3564 tcg_gen_shri_i32(tmp
, t1
, 8);
3565 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3566 tcg_gen_or_i32(rm
, rm
, tmp
);
3567 tcg_gen_shri_i32(tmp
, t0
, 16);
3568 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3569 tcg_gen_or_i32(t1
, rm
, tmp
);
3570 tcg_gen_mov_i32(t0
, rd
);
3577 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3584 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3585 tcg_gen_shli_i32(tmp2
, t1
, 16);
3586 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3587 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3588 tcg_gen_shri_i32(tmp2
, t0
, 16);
3589 tcg_gen_or_i32(t1
, t1
, tmp2
);
3590 tcg_gen_mov_i32(t0
, tmp
);
3596 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3601 for (n
= 0; n
< q
+ 1; n
+= 2) {
3602 t0
= neon_load_reg(reg
, n
);
3603 t1
= neon_load_reg(reg
, n
+ 1);
3605 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3606 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3607 case 2: /* no-op */; break;
3610 neon_store_scratch(tmp
+ n
, t0
);
3611 neon_store_scratch(tmp
+ n
+ 1, t1
);
3615 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3622 tcg_gen_shli_i32(rd
, t0
, 8);
3623 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3624 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3625 tcg_gen_or_i32(rd
, rd
, tmp
);
3627 tcg_gen_shri_i32(t1
, t1
, 8);
3628 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3629 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3630 tcg_gen_or_i32(t1
, t1
, tmp
);
3631 tcg_gen_mov_i32(t0
, rd
);
3637 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3644 tcg_gen_shli_i32(rd
, t0
, 16);
3645 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3646 tcg_gen_or_i32(rd
, rd
, tmp
);
3647 tcg_gen_shri_i32(t1
, t1
, 16);
3648 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3649 tcg_gen_or_i32(t1
, t1
, tmp
);
3650 tcg_gen_mov_i32(t0
, rd
);
3661 } neon_ls_element_type
[11] = {
3675 /* Translate a NEON load/store element instruction. Return nonzero if the
3676 instruction is invalid. */
3677 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3694 if (!vfp_enabled(env
))
3696 VFP_DREG_D(rd
, insn
);
3697 rn
= (insn
>> 16) & 0xf;
3699 load
= (insn
& (1 << 21)) != 0;
3701 if ((insn
& (1 << 23)) == 0) {
3702 /* Load store all elements. */
3703 op
= (insn
>> 8) & 0xf;
3704 size
= (insn
>> 6) & 3;
3705 if (op
> 10 || size
== 3)
3707 nregs
= neon_ls_element_type
[op
].nregs
;
3708 interleave
= neon_ls_element_type
[op
].interleave
;
3709 load_reg_var(s
, addr
, rn
);
3710 stride
= (1 << size
) * interleave
;
3711 for (reg
= 0; reg
< nregs
; reg
++) {
3712 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3713 load_reg_var(s
, addr
, rn
);
3714 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3715 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3716 load_reg_var(s
, addr
, rn
);
3717 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3719 for (pass
= 0; pass
< 2; pass
++) {
3722 tmp
= gen_ld32(addr
, IS_USER(s
));
3723 neon_store_reg(rd
, pass
, tmp
);
3725 tmp
= neon_load_reg(rd
, pass
);
3726 gen_st32(tmp
, addr
, IS_USER(s
));
3728 tcg_gen_addi_i32(addr
, addr
, stride
);
3729 } else if (size
== 1) {
3731 tmp
= gen_ld16u(addr
, IS_USER(s
));
3732 tcg_gen_addi_i32(addr
, addr
, stride
);
3733 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3734 tcg_gen_addi_i32(addr
, addr
, stride
);
3735 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3737 neon_store_reg(rd
, pass
, tmp
);
3739 tmp
= neon_load_reg(rd
, pass
);
3741 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3742 gen_st16(tmp
, addr
, IS_USER(s
));
3743 tcg_gen_addi_i32(addr
, addr
, stride
);
3744 gen_st16(tmp2
, addr
, IS_USER(s
));
3745 tcg_gen_addi_i32(addr
, addr
, stride
);
3747 } else /* size == 0 */ {
3750 for (n
= 0; n
< 4; n
++) {
3751 tmp
= gen_ld8u(addr
, IS_USER(s
));
3752 tcg_gen_addi_i32(addr
, addr
, stride
);
3756 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3760 neon_store_reg(rd
, pass
, tmp2
);
3762 tmp2
= neon_load_reg(rd
, pass
);
3763 for (n
= 0; n
< 4; n
++) {
3766 tcg_gen_mov_i32(tmp
, tmp2
);
3768 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3770 gen_st8(tmp
, addr
, IS_USER(s
));
3771 tcg_gen_addi_i32(addr
, addr
, stride
);
3777 rd
+= neon_ls_element_type
[op
].spacing
;
3781 size
= (insn
>> 10) & 3;
3783 /* Load single element to all lanes. */
3786 size
= (insn
>> 6) & 3;
3787 nregs
= ((insn
>> 8) & 3) + 1;
3788 stride
= (insn
& (1 << 5)) ? 2 : 1;
3789 load_reg_var(s
, addr
, rn
);
3790 for (reg
= 0; reg
< nregs
; reg
++) {
3793 tmp
= gen_ld8u(addr
, IS_USER(s
));
3794 gen_neon_dup_u8(tmp
, 0);
3797 tmp
= gen_ld16u(addr
, IS_USER(s
));
3798 gen_neon_dup_low16(tmp
);
3801 tmp
= gen_ld32(addr
, IS_USER(s
));
3805 default: /* Avoid compiler warnings. */
3808 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3810 tcg_gen_mov_i32(tmp2
, tmp
);
3811 neon_store_reg(rd
, 0, tmp2
);
3812 neon_store_reg(rd
, 1, tmp
);
3815 stride
= (1 << size
) * nregs
;
3817 /* Single element. */
3818 pass
= (insn
>> 7) & 1;
3821 shift
= ((insn
>> 5) & 3) * 8;
3825 shift
= ((insn
>> 6) & 1) * 16;
3826 stride
= (insn
& (1 << 5)) ? 2 : 1;
3830 stride
= (insn
& (1 << 6)) ? 2 : 1;
3835 nregs
= ((insn
>> 8) & 3) + 1;
3836 load_reg_var(s
, addr
, rn
);
3837 for (reg
= 0; reg
< nregs
; reg
++) {
3841 tmp
= gen_ld8u(addr
, IS_USER(s
));
3844 tmp
= gen_ld16u(addr
, IS_USER(s
));
3847 tmp
= gen_ld32(addr
, IS_USER(s
));
3849 default: /* Avoid compiler warnings. */
3853 tmp2
= neon_load_reg(rd
, pass
);
3854 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3857 neon_store_reg(rd
, pass
, tmp
);
3858 } else { /* Store */
3859 tmp
= neon_load_reg(rd
, pass
);
3861 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3864 gen_st8(tmp
, addr
, IS_USER(s
));
3867 gen_st16(tmp
, addr
, IS_USER(s
));
3870 gen_st32(tmp
, addr
, IS_USER(s
));
3875 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3877 stride
= nregs
* (1 << size
);
3884 base
= load_reg(s
, rn
);
3886 tcg_gen_addi_i32(base
, base
, stride
);
3889 index
= load_reg(s
, rm
);
3890 tcg_gen_add_i32(base
, base
, index
);
3893 store_reg(s
, rn
, base
);
3898 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3899 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3901 tcg_gen_and_i32(t
, t
, c
);
3902 tcg_gen_bic_i32(f
, f
, c
);
3903 tcg_gen_or_i32(dest
, t
, f
);
3906 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3909 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3910 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3911 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3916 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3919 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3920 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3921 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3926 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3929 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3930 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3931 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3936 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3942 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3943 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3948 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3949 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3956 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3957 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3962 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3963 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3970 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3974 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3975 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3976 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3981 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3982 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3983 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3990 static inline void gen_neon_addl(int size
)
3993 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3994 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3995 case 2: tcg_gen_add_i64(CPU_V001
); break;
4000 static inline void gen_neon_subl(int size
)
4003 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4004 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4005 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4010 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4013 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4014 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4015 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4020 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4023 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4024 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4029 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4033 switch ((size
<< 1) | u
) {
4034 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4035 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4036 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4037 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4039 tmp
= gen_muls_i64_i32(a
, b
);
4040 tcg_gen_mov_i64(dest
, tmp
);
4043 tmp
= gen_mulu_i64_i32(a
, b
);
4044 tcg_gen_mov_i64(dest
, tmp
);
4050 /* Translate a NEON data processing instruction. Return nonzero if the
4051 instruction is invalid.
4052 We process data in a mixture of 32-bit and 64-bit chunks.
4053 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4055 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4068 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4071 if (!vfp_enabled(env
))
4073 q
= (insn
& (1 << 6)) != 0;
4074 u
= (insn
>> 24) & 1;
4075 VFP_DREG_D(rd
, insn
);
4076 VFP_DREG_N(rn
, insn
);
4077 VFP_DREG_M(rm
, insn
);
4078 size
= (insn
>> 20) & 3;
4079 if ((insn
& (1 << 23)) == 0) {
4080 /* Three register same length. */
4081 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4082 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4083 || op
== 10 || op
== 11 || op
== 16)) {
4084 /* 64-bit element instructions. */
4085 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4086 neon_load_reg64(cpu_V0
, rn
+ pass
);
4087 neon_load_reg64(cpu_V1
, rm
+ pass
);
4091 gen_helper_neon_add_saturate_u64(CPU_V001
);
4093 gen_helper_neon_add_saturate_s64(CPU_V001
);
4098 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4100 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4105 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4107 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4112 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4115 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4119 case 10: /* VRSHL */
4121 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4123 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4126 case 11: /* VQRSHL */
4128 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4131 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4137 tcg_gen_sub_i64(CPU_V001
);
4139 tcg_gen_add_i64(CPU_V001
);
4145 neon_store_reg64(cpu_V0
, rd
+ pass
);
4152 case 10: /* VRSHL */
4153 case 11: /* VQRSHL */
4156 /* Shift instruction operands are reversed. */
4163 case 20: /* VPMAX */
4164 case 21: /* VPMIN */
4165 case 23: /* VPADD */
4168 case 26: /* VPADD (float) */
4169 pairwise
= (u
&& size
< 2);
4171 case 30: /* VPMIN/VPMAX (float) */
4179 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4188 tmp
= neon_load_reg(rn
, n
);
4189 tmp2
= neon_load_reg(rn
, n
+ 1);
4191 tmp
= neon_load_reg(rm
, n
);
4192 tmp2
= neon_load_reg(rm
, n
+ 1);
4196 tmp
= neon_load_reg(rn
, pass
);
4197 tmp2
= neon_load_reg(rm
, pass
);
4201 GEN_NEON_INTEGER_OP(hadd
);
4204 GEN_NEON_INTEGER_OP_ENV(qadd
);
4206 case 2: /* VRHADD */
4207 GEN_NEON_INTEGER_OP(rhadd
);
4209 case 3: /* Logic ops. */
4210 switch ((u
<< 2) | size
) {
4212 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4215 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4218 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4221 tcg_gen_not_i32(tmp2
, tmp2
);
4222 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4225 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4228 tmp3
= neon_load_reg(rd
, pass
);
4229 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4233 tmp3
= neon_load_reg(rd
, pass
);
4234 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4238 tmp3
= neon_load_reg(rd
, pass
);
4239 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4245 GEN_NEON_INTEGER_OP(hsub
);
4248 GEN_NEON_INTEGER_OP_ENV(qsub
);
4251 GEN_NEON_INTEGER_OP(cgt
);
4254 GEN_NEON_INTEGER_OP(cge
);
4257 GEN_NEON_INTEGER_OP(shl
);
4260 GEN_NEON_INTEGER_OP_ENV(qshl
);
4262 case 10: /* VRSHL */
4263 GEN_NEON_INTEGER_OP(rshl
);
4265 case 11: /* VQRSHL */
4266 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4269 GEN_NEON_INTEGER_OP(max
);
4272 GEN_NEON_INTEGER_OP(min
);
4275 GEN_NEON_INTEGER_OP(abd
);
4278 GEN_NEON_INTEGER_OP(abd
);
4280 tmp2
= neon_load_reg(rd
, pass
);
4281 gen_neon_add(size
, tmp
, tmp2
);
4284 if (!u
) { /* VADD */
4285 if (gen_neon_add(size
, tmp
, tmp2
))
4289 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4290 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4291 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4297 if (!u
) { /* VTST */
4299 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4300 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4301 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4306 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4307 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4308 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4313 case 18: /* Multiply. */
4315 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4316 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4317 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4321 tmp2
= neon_load_reg(rd
, pass
);
4323 gen_neon_rsb(size
, tmp
, tmp2
);
4325 gen_neon_add(size
, tmp
, tmp2
);
4329 if (u
) { /* polynomial */
4330 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4331 } else { /* Integer */
4333 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4334 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4335 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4340 case 20: /* VPMAX */
4341 GEN_NEON_INTEGER_OP(pmax
);
4343 case 21: /* VPMIN */
4344 GEN_NEON_INTEGER_OP(pmin
);
4346 case 22: /* Hultiply high. */
4347 if (!u
) { /* VQDMULH */
4349 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4350 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4353 } else { /* VQRDHMUL */
4355 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4356 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4361 case 23: /* VPADD */
4365 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4366 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4367 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4371 case 26: /* Floating point arithnetic. */
4372 switch ((u
<< 2) | size
) {
4374 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4377 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4380 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4383 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4389 case 27: /* Float multiply. */
4390 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4393 tmp2
= neon_load_reg(rd
, pass
);
4395 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4397 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4401 case 28: /* Float compare. */
4403 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4406 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4408 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4411 case 29: /* Float compare absolute. */
4415 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4417 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4419 case 30: /* Float min/max. */
4421 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4423 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4427 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4429 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4436 /* Save the result. For elementwise operations we can put it
4437 straight into the destination register. For pairwise operations
4438 we have to be careful to avoid clobbering the source operands. */
4439 if (pairwise
&& rd
== rm
) {
4440 neon_store_scratch(pass
, tmp
);
4442 neon_store_reg(rd
, pass
, tmp
);
4446 if (pairwise
&& rd
== rm
) {
4447 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4448 tmp
= neon_load_scratch(pass
);
4449 neon_store_reg(rd
, pass
, tmp
);
4452 /* End of 3 register same size operations. */
4453 } else if (insn
& (1 << 4)) {
4454 if ((insn
& 0x00380080) != 0) {
4455 /* Two registers and shift. */
4456 op
= (insn
>> 8) & 0xf;
4457 if (insn
& (1 << 7)) {
4462 while ((insn
& (1 << (size
+ 19))) == 0)
4465 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4466 /* To avoid excessive dumplication of ops we implement shift
4467 by immediate using the variable shift operations. */
4469 /* Shift by immediate:
4470 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4471 /* Right shifts are encoded as N - shift, where N is the
4472 element size in bits. */
4474 shift
= shift
- (1 << (size
+ 3));
4482 imm
= (uint8_t) shift
;
4487 imm
= (uint16_t) shift
;
4498 for (pass
= 0; pass
< count
; pass
++) {
4500 neon_load_reg64(cpu_V0
, rm
+ pass
);
4501 tcg_gen_movi_i64(cpu_V1
, imm
);
4506 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4508 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4513 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4515 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4520 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4522 case 5: /* VSHL, VSLI */
4523 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4527 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4529 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4531 case 7: /* VQSHLU */
4532 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4535 if (op
== 1 || op
== 3) {
4537 neon_load_reg64(cpu_V0
, rd
+ pass
);
4538 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4539 } else if (op
== 4 || (op
== 5 && u
)) {
4541 cpu_abort(env
, "VS[LR]I.64 not implemented");
4543 neon_store_reg64(cpu_V0
, rd
+ pass
);
4544 } else { /* size < 3 */
4545 /* Operands in T0 and T1. */
4546 tmp
= neon_load_reg(rm
, pass
);
4548 tcg_gen_movi_i32(tmp2
, imm
);
4552 GEN_NEON_INTEGER_OP(shl
);
4556 GEN_NEON_INTEGER_OP(rshl
);
4561 GEN_NEON_INTEGER_OP(shl
);
4563 case 5: /* VSHL, VSLI */
4565 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4566 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4567 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4572 GEN_NEON_INTEGER_OP_ENV(qshl
);
4574 case 7: /* VQSHLU */
4576 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4577 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4578 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4585 if (op
== 1 || op
== 3) {
4587 tmp2
= neon_load_reg(rd
, pass
);
4588 gen_neon_add(size
, tmp2
, tmp
);
4590 } else if (op
== 4 || (op
== 5 && u
)) {
4595 imm
= 0xff >> -shift
;
4597 imm
= (uint8_t)(0xff << shift
);
4603 imm
= 0xffff >> -shift
;
4605 imm
= (uint16_t)(0xffff << shift
);
4610 imm
= 0xffffffffu
>> -shift
;
4612 imm
= 0xffffffffu
<< shift
;
4617 tmp2
= neon_load_reg(rd
, pass
);
4618 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4619 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4620 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4623 neon_store_reg(rd
, pass
, tmp
);
4626 } else if (op
< 10) {
4627 /* Shift by immediate and narrow:
4628 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4629 shift
= shift
- (1 << (size
+ 3));
4633 imm
= (uint16_t)shift
;
4635 tmp2
= tcg_const_i32(imm
);
4636 TCGV_UNUSED_I64(tmp64
);
4639 imm
= (uint32_t)shift
;
4640 tmp2
= tcg_const_i32(imm
);
4641 TCGV_UNUSED_I64(tmp64
);
4644 tmp64
= tcg_const_i64(shift
);
4651 for (pass
= 0; pass
< 2; pass
++) {
4653 neon_load_reg64(cpu_V0
, rm
+ pass
);
4656 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4658 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4661 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4663 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4666 tmp
= neon_load_reg(rm
+ pass
, 0);
4667 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4668 tmp3
= neon_load_reg(rm
+ pass
, 1);
4669 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4670 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4675 if (op
== 8 && !u
) {
4676 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4679 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4681 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4689 neon_store_reg(rd
, 0, tmp2
);
4690 neon_store_reg(rd
, 1, tmp
);
4694 tcg_temp_free_i64(tmp64
);
4696 } else if (op
== 10) {
4700 tmp
= neon_load_reg(rm
, 0);
4701 tmp2
= neon_load_reg(rm
, 1);
4702 for (pass
= 0; pass
< 2; pass
++) {
4706 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4709 /* The shift is less than the width of the source
4710 type, so we can just shift the whole register. */
4711 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4712 if (size
< 2 || !u
) {
4715 imm
= (0xffu
>> (8 - shift
));
4718 imm
= 0xffff >> (16 - shift
);
4720 imm64
= imm
| (((uint64_t)imm
) << 32);
4721 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4724 neon_store_reg64(cpu_V0
, rd
+ pass
);
4726 } else if (op
== 15 || op
== 16) {
4727 /* VCVT fixed-point. */
4728 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4729 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4732 gen_vfp_ulto(0, shift
);
4734 gen_vfp_slto(0, shift
);
4737 gen_vfp_toul(0, shift
);
4739 gen_vfp_tosl(0, shift
);
4741 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4746 } else { /* (insn & 0x00380080) == 0 */
4749 op
= (insn
>> 8) & 0xf;
4750 /* One register and immediate. */
4751 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4752 invert
= (insn
& (1 << 5)) != 0;
4770 imm
= (imm
<< 8) | (imm
<< 24);
4773 imm
= (imm
< 8) | 0xff;
4776 imm
= (imm
<< 16) | 0xffff;
4779 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4784 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4785 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4791 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4792 if (op
& 1 && op
< 12) {
4793 tmp
= neon_load_reg(rd
, pass
);
4795 /* The immediate value has already been inverted, so
4797 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4799 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4804 if (op
== 14 && invert
) {
4807 for (n
= 0; n
< 4; n
++) {
4808 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4809 val
|= 0xff << (n
* 8);
4811 tcg_gen_movi_i32(tmp
, val
);
4813 tcg_gen_movi_i32(tmp
, imm
);
4816 neon_store_reg(rd
, pass
, tmp
);
4819 } else { /* (insn & 0x00800010 == 0x00800000) */
4821 op
= (insn
>> 8) & 0xf;
4822 if ((insn
& (1 << 6)) == 0) {
4823 /* Three registers of different lengths. */
4827 /* prewiden, src1_wide, src2_wide */
4828 static const int neon_3reg_wide
[16][3] = {
4829 {1, 0, 0}, /* VADDL */
4830 {1, 1, 0}, /* VADDW */
4831 {1, 0, 0}, /* VSUBL */
4832 {1, 1, 0}, /* VSUBW */
4833 {0, 1, 1}, /* VADDHN */
4834 {0, 0, 0}, /* VABAL */
4835 {0, 1, 1}, /* VSUBHN */
4836 {0, 0, 0}, /* VABDL */
4837 {0, 0, 0}, /* VMLAL */
4838 {0, 0, 0}, /* VQDMLAL */
4839 {0, 0, 0}, /* VMLSL */
4840 {0, 0, 0}, /* VQDMLSL */
4841 {0, 0, 0}, /* Integer VMULL */
4842 {0, 0, 0}, /* VQDMULL */
4843 {0, 0, 0} /* Polynomial VMULL */
4846 prewiden
= neon_3reg_wide
[op
][0];
4847 src1_wide
= neon_3reg_wide
[op
][1];
4848 src2_wide
= neon_3reg_wide
[op
][2];
4850 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4853 /* Avoid overlapping operands. Wide source operands are
4854 always aligned so will never overlap with wide
4855 destinations in problematic ways. */
4856 if (rd
== rm
&& !src2_wide
) {
4857 tmp
= neon_load_reg(rm
, 1);
4858 neon_store_scratch(2, tmp
);
4859 } else if (rd
== rn
&& !src1_wide
) {
4860 tmp
= neon_load_reg(rn
, 1);
4861 neon_store_scratch(2, tmp
);
4864 for (pass
= 0; pass
< 2; pass
++) {
4866 neon_load_reg64(cpu_V0
, rn
+ pass
);
4869 if (pass
== 1 && rd
== rn
) {
4870 tmp
= neon_load_scratch(2);
4872 tmp
= neon_load_reg(rn
, pass
);
4875 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4879 neon_load_reg64(cpu_V1
, rm
+ pass
);
4882 if (pass
== 1 && rd
== rm
) {
4883 tmp2
= neon_load_scratch(2);
4885 tmp2
= neon_load_reg(rm
, pass
);
4888 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4892 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4893 gen_neon_addl(size
);
4895 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4896 gen_neon_subl(size
);
4898 case 5: case 7: /* VABAL, VABDL */
4899 switch ((size
<< 1) | u
) {
4901 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4904 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4907 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4910 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4913 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4916 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4923 case 8: case 9: case 10: case 11: case 12: case 13:
4924 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4925 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4929 case 14: /* Polynomial VMULL */
4930 cpu_abort(env
, "Polynomial VMULL not implemented");
4932 default: /* 15 is RESERVED. */
4935 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4937 if (op
== 10 || op
== 11) {
4938 gen_neon_negl(cpu_V0
, size
);
4942 neon_load_reg64(cpu_V1
, rd
+ pass
);
4946 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4947 gen_neon_addl(size
);
4949 case 9: case 11: /* VQDMLAL, VQDMLSL */
4950 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4951 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4954 case 13: /* VQDMULL */
4955 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4960 neon_store_reg64(cpu_V0
, rd
+ pass
);
4961 } else if (op
== 4 || op
== 6) {
4962 /* Narrowing operation. */
4967 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4970 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4973 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4974 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4981 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4984 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4987 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4988 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4989 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4997 neon_store_reg(rd
, 0, tmp3
);
4998 neon_store_reg(rd
, 1, tmp
);
5001 /* Write back the result. */
5002 neon_store_reg64(cpu_V0
, rd
+ pass
);
5006 /* Two registers and a scalar. */
5008 case 0: /* Integer VMLA scalar */
5009 case 1: /* Float VMLA scalar */
5010 case 4: /* Integer VMLS scalar */
5011 case 5: /* Floating point VMLS scalar */
5012 case 8: /* Integer VMUL scalar */
5013 case 9: /* Floating point VMUL scalar */
5014 case 12: /* VQDMULH scalar */
5015 case 13: /* VQRDMULH scalar */
5016 tmp
= neon_get_scalar(size
, rm
);
5017 neon_store_scratch(0, tmp
);
5018 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5019 tmp
= neon_load_scratch(0);
5020 tmp2
= neon_load_reg(rn
, pass
);
5023 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5025 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5027 } else if (op
== 13) {
5029 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5031 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5033 } else if (op
& 1) {
5034 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5037 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5038 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5039 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5046 tmp2
= neon_load_reg(rd
, pass
);
5049 gen_neon_add(size
, tmp
, tmp2
);
5052 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5055 gen_neon_rsb(size
, tmp
, tmp2
);
5058 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5065 neon_store_reg(rd
, pass
, tmp
);
5068 case 2: /* VMLAL sclar */
5069 case 3: /* VQDMLAL scalar */
5070 case 6: /* VMLSL scalar */
5071 case 7: /* VQDMLSL scalar */
5072 case 10: /* VMULL scalar */
5073 case 11: /* VQDMULL scalar */
5074 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5077 tmp2
= neon_get_scalar(size
, rm
);
5078 tmp3
= neon_load_reg(rn
, 1);
5080 for (pass
= 0; pass
< 2; pass
++) {
5082 tmp
= neon_load_reg(rn
, 0);
5086 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5088 if (op
== 6 || op
== 7) {
5089 gen_neon_negl(cpu_V0
, size
);
5092 neon_load_reg64(cpu_V1
, rd
+ pass
);
5096 gen_neon_addl(size
);
5099 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5100 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5106 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5111 neon_store_reg64(cpu_V0
, rd
+ pass
);
5117 default: /* 14 and 15 are RESERVED */
5121 } else { /* size == 3 */
5124 imm
= (insn
>> 8) & 0xf;
5131 neon_load_reg64(cpu_V0
, rn
);
5133 neon_load_reg64(cpu_V1
, rn
+ 1);
5135 } else if (imm
== 8) {
5136 neon_load_reg64(cpu_V0
, rn
+ 1);
5138 neon_load_reg64(cpu_V1
, rm
);
5141 tmp64
= tcg_temp_new_i64();
5143 neon_load_reg64(cpu_V0
, rn
);
5144 neon_load_reg64(tmp64
, rn
+ 1);
5146 neon_load_reg64(cpu_V0
, rn
+ 1);
5147 neon_load_reg64(tmp64
, rm
);
5149 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5150 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5151 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5153 neon_load_reg64(cpu_V1
, rm
);
5155 neon_load_reg64(cpu_V1
, rm
+ 1);
5158 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5159 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5160 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5161 tcg_temp_free_i64(tmp64
);
5164 neon_load_reg64(cpu_V0
, rn
);
5165 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5166 neon_load_reg64(cpu_V1
, rm
);
5167 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5168 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5170 neon_store_reg64(cpu_V0
, rd
);
5172 neon_store_reg64(cpu_V1
, rd
+ 1);
5174 } else if ((insn
& (1 << 11)) == 0) {
5175 /* Two register misc. */
5176 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5177 size
= (insn
>> 18) & 3;
5179 case 0: /* VREV64 */
5182 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5183 tmp
= neon_load_reg(rm
, pass
* 2);
5184 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5186 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5187 case 1: gen_swap_half(tmp
); break;
5188 case 2: /* no-op */ break;
5191 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5193 neon_store_reg(rd
, pass
* 2, tmp2
);
5196 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5197 case 1: gen_swap_half(tmp2
); break;
5200 neon_store_reg(rd
, pass
* 2, tmp2
);
5204 case 4: case 5: /* VPADDL */
5205 case 12: case 13: /* VPADAL */
5208 for (pass
= 0; pass
< q
+ 1; pass
++) {
5209 tmp
= neon_load_reg(rm
, pass
* 2);
5210 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5211 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5212 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5214 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5215 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5216 case 2: tcg_gen_add_i64(CPU_V001
); break;
5221 neon_load_reg64(cpu_V1
, rd
+ pass
);
5222 gen_neon_addl(size
);
5224 neon_store_reg64(cpu_V0
, rd
+ pass
);
5229 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5230 tmp
= neon_load_reg(rm
, n
);
5231 tmp2
= neon_load_reg(rd
, n
+ 1);
5232 neon_store_reg(rm
, n
, tmp2
);
5233 neon_store_reg(rd
, n
+ 1, tmp
);
5241 Rd A3 A2 A1 A0 B2 B0 A2 A0
5242 Rm B3 B2 B1 B0 B3 B1 A3 A1
5246 gen_neon_unzip(rd
, q
, 0, size
);
5247 gen_neon_unzip(rm
, q
, 4, size
);
5249 static int unzip_order_q
[8] =
5250 {0, 2, 4, 6, 1, 3, 5, 7};
5251 for (n
= 0; n
< 8; n
++) {
5252 int reg
= (n
< 4) ? rd
: rm
;
5253 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5254 neon_store_reg(reg
, n
% 4, tmp
);
5257 static int unzip_order
[4] =
5259 for (n
= 0; n
< 4; n
++) {
5260 int reg
= (n
< 2) ? rd
: rm
;
5261 tmp
= neon_load_scratch(unzip_order
[n
]);
5262 neon_store_reg(reg
, n
% 2, tmp
);
5268 Rd A3 A2 A1 A0 B1 A1 B0 A0
5269 Rm B3 B2 B1 B0 B3 A3 B2 A2
5273 count
= (q
? 4 : 2);
5274 for (n
= 0; n
< count
; n
++) {
5275 tmp
= neon_load_reg(rd
, n
);
5276 tmp2
= neon_load_reg(rd
, n
);
5278 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5279 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5280 case 2: /* no-op */; break;
5283 neon_store_scratch(n
* 2, tmp
);
5284 neon_store_scratch(n
* 2 + 1, tmp2
);
5286 for (n
= 0; n
< count
* 2; n
++) {
5287 int reg
= (n
< count
) ? rd
: rm
;
5288 tmp
= neon_load_scratch(n
);
5289 neon_store_reg(reg
, n
% count
, tmp
);
5292 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5296 for (pass
= 0; pass
< 2; pass
++) {
5297 neon_load_reg64(cpu_V0
, rm
+ pass
);
5299 if (op
== 36 && q
== 0) {
5300 gen_neon_narrow(size
, tmp
, cpu_V0
);
5302 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5304 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5309 neon_store_reg(rd
, 0, tmp2
);
5310 neon_store_reg(rd
, 1, tmp
);
5314 case 38: /* VSHLL */
5317 tmp
= neon_load_reg(rm
, 0);
5318 tmp2
= neon_load_reg(rm
, 1);
5319 for (pass
= 0; pass
< 2; pass
++) {
5322 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5323 neon_store_reg64(cpu_V0
, rd
+ pass
);
5328 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5329 if (op
== 30 || op
== 31 || op
>= 58) {
5330 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5331 neon_reg_offset(rm
, pass
));
5334 tmp
= neon_load_reg(rm
, pass
);
5337 case 1: /* VREV32 */
5339 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5340 case 1: gen_swap_half(tmp
); break;
5344 case 2: /* VREV16 */
5351 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5352 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5353 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5359 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5360 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5361 case 2: gen_helper_clz(tmp
, tmp
); break;
5368 gen_helper_neon_cnt_u8(tmp
, tmp
);
5373 tcg_gen_not_i32(tmp
, tmp
);
5375 case 14: /* VQABS */
5377 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5378 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5379 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5383 case 15: /* VQNEG */
5385 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5386 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5387 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5391 case 16: case 19: /* VCGT #0, VCLE #0 */
5392 tmp2
= tcg_const_i32(0);
5394 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5395 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5396 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5399 tcg_temp_free(tmp2
);
5401 tcg_gen_not_i32(tmp
, tmp
);
5403 case 17: case 20: /* VCGE #0, VCLT #0 */
5404 tmp2
= tcg_const_i32(0);
5406 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5407 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5408 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5411 tcg_temp_free(tmp2
);
5413 tcg_gen_not_i32(tmp
, tmp
);
5415 case 18: /* VCEQ #0 */
5416 tmp2
= tcg_const_i32(0);
5418 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5419 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5420 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5423 tcg_temp_free(tmp2
);
5427 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5428 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5429 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5436 tmp2
= tcg_const_i32(0);
5437 gen_neon_rsb(size
, tmp
, tmp2
);
5438 tcg_temp_free(tmp2
);
5440 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5441 tmp2
= tcg_const_i32(0);
5442 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5443 tcg_temp_free(tmp2
);
5445 tcg_gen_not_i32(tmp
, tmp
);
5447 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5448 tmp2
= tcg_const_i32(0);
5449 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5450 tcg_temp_free(tmp2
);
5452 tcg_gen_not_i32(tmp
, tmp
);
5454 case 26: /* Float VCEQ #0 */
5455 tmp2
= tcg_const_i32(0);
5456 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5457 tcg_temp_free(tmp2
);
5459 case 30: /* Float VABS */
5462 case 31: /* Float VNEG */
5466 tmp2
= neon_load_reg(rd
, pass
);
5467 neon_store_reg(rm
, pass
, tmp2
);
5470 tmp2
= neon_load_reg(rd
, pass
);
5472 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5473 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5477 neon_store_reg(rm
, pass
, tmp2
);
5479 case 56: /* Integer VRECPE */
5480 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5482 case 57: /* Integer VRSQRTE */
5483 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5485 case 58: /* Float VRECPE */
5486 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5488 case 59: /* Float VRSQRTE */
5489 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5491 case 60: /* VCVT.F32.S32 */
5494 case 61: /* VCVT.F32.U32 */
5497 case 62: /* VCVT.S32.F32 */
5500 case 63: /* VCVT.U32.F32 */
5504 /* Reserved: 21, 29, 39-56 */
5507 if (op
== 30 || op
== 31 || op
>= 58) {
5508 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5509 neon_reg_offset(rd
, pass
));
5511 neon_store_reg(rd
, pass
, tmp
);
5516 } else if ((insn
& (1 << 10)) == 0) {
5518 n
= ((insn
>> 5) & 0x18) + 8;
5519 if (insn
& (1 << 6)) {
5520 tmp
= neon_load_reg(rd
, 0);
5523 tcg_gen_movi_i32(tmp
, 0);
5525 tmp2
= neon_load_reg(rm
, 0);
5526 tmp4
= tcg_const_i32(rn
);
5527 tmp5
= tcg_const_i32(n
);
5528 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5530 if (insn
& (1 << 6)) {
5531 tmp
= neon_load_reg(rd
, 1);
5534 tcg_gen_movi_i32(tmp
, 0);
5536 tmp3
= neon_load_reg(rm
, 1);
5537 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5538 tcg_temp_free_i32(tmp5
);
5539 tcg_temp_free_i32(tmp4
);
5540 neon_store_reg(rd
, 0, tmp2
);
5541 neon_store_reg(rd
, 1, tmp3
);
5543 } else if ((insn
& 0x380) == 0) {
5545 if (insn
& (1 << 19)) {
5546 tmp
= neon_load_reg(rm
, 1);
5548 tmp
= neon_load_reg(rm
, 0);
5550 if (insn
& (1 << 16)) {
5551 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5552 } else if (insn
& (1 << 17)) {
5553 if ((insn
>> 18) & 1)
5554 gen_neon_dup_high16(tmp
);
5556 gen_neon_dup_low16(tmp
);
5558 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5560 tcg_gen_mov_i32(tmp2
, tmp
);
5561 neon_store_reg(rd
, pass
, tmp2
);
5572 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5574 int crn
= (insn
>> 16) & 0xf;
5575 int crm
= insn
& 0xf;
5576 int op1
= (insn
>> 21) & 7;
5577 int op2
= (insn
>> 5) & 7;
5578 int rt
= (insn
>> 12) & 0xf;
5581 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5582 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5586 tmp
= load_cpu_field(teecr
);
5587 store_reg(s
, rt
, tmp
);
5590 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5592 if (IS_USER(s
) && (env
->teecr
& 1))
5594 tmp
= load_cpu_field(teehbr
);
5595 store_reg(s
, rt
, tmp
);
5599 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5600 op1
, crn
, crm
, op2
);
5604 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5606 int crn
= (insn
>> 16) & 0xf;
5607 int crm
= insn
& 0xf;
5608 int op1
= (insn
>> 21) & 7;
5609 int op2
= (insn
>> 5) & 7;
5610 int rt
= (insn
>> 12) & 0xf;
5613 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5614 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5618 tmp
= load_reg(s
, rt
);
5619 gen_helper_set_teecr(cpu_env
, tmp
);
5623 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5625 if (IS_USER(s
) && (env
->teecr
& 1))
5627 tmp
= load_reg(s
, rt
);
5628 store_cpu_field(tmp
, teehbr
);
5632 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5633 op1
, crn
, crm
, op2
);
5637 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5641 cpnum
= (insn
>> 8) & 0xf;
5642 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5643 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5649 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5650 return disas_iwmmxt_insn(env
, s
, insn
);
5651 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5652 return disas_dsp_insn(env
, s
, insn
);
5657 return disas_vfp_insn (env
, s
, insn
);
5659 /* Coprocessors 7-15 are architecturally reserved by ARM.
5660 Unfortunately Intel decided to ignore this. */
5661 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5663 if (insn
& (1 << 20))
5664 return disas_cp14_read(env
, s
, insn
);
5666 return disas_cp14_write(env
, s
, insn
);
5668 return disas_cp15_insn (env
, s
, insn
);
5671 /* Unknown coprocessor. See if the board has hooked it. */
5672 return disas_cp_insn (env
, s
, insn
);
5677 /* Store a 64-bit value to a register pair. Clobbers val. */
5678 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5682 tcg_gen_trunc_i64_i32(tmp
, val
);
5683 store_reg(s
, rlow
, tmp
);
5685 tcg_gen_shri_i64(val
, val
, 32);
5686 tcg_gen_trunc_i64_i32(tmp
, val
);
5687 store_reg(s
, rhigh
, tmp
);
5690 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5691 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5696 /* Load value and extend to 64 bits. */
5697 tmp
= tcg_temp_new_i64();
5698 tmp2
= load_reg(s
, rlow
);
5699 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5701 tcg_gen_add_i64(val
, val
, tmp
);
5702 tcg_temp_free_i64(tmp
);
5705 /* load and add a 64-bit value from a register pair. */
5706 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5712 /* Load 64-bit value rd:rn. */
5713 tmpl
= load_reg(s
, rlow
);
5714 tmph
= load_reg(s
, rhigh
);
5715 tmp
= tcg_temp_new_i64();
5716 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5719 tcg_gen_add_i64(val
, val
, tmp
);
5720 tcg_temp_free_i64(tmp
);
5723 /* Set N and Z flags from a 64-bit value. */
5724 static void gen_logicq_cc(TCGv_i64 val
)
5726 TCGv tmp
= new_tmp();
5727 gen_helper_logicq_cc(tmp
, val
);
5732 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5734 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5741 insn
= ldl_code(s
->pc
);
5744 /* M variants do not implement ARM mode. */
5749 /* Unconditional instructions. */
5750 if (((insn
>> 25) & 7) == 1) {
5751 /* NEON Data processing. */
5752 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5755 if (disas_neon_data_insn(env
, s
, insn
))
5759 if ((insn
& 0x0f100000) == 0x04000000) {
5760 /* NEON load/store. */
5761 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5764 if (disas_neon_ls_insn(env
, s
, insn
))
5768 if ((insn
& 0x0d70f000) == 0x0550f000)
5770 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5773 if (insn
& (1 << 9)) {
5774 /* BE8 mode not implemented. */
5778 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5779 switch ((insn
>> 4) & 0xf) {
5782 gen_helper_clrex(cpu_env
);
5788 /* We don't emulate caches so these are a no-op. */
5793 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5799 op1
= (insn
& 0x1f);
5800 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5801 addr
= load_reg(s
, 13);
5804 tmp
= tcg_const_i32(op1
);
5805 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
5806 tcg_temp_free_i32(tmp
);
5808 i
= (insn
>> 23) & 3;
5810 case 0: offset
= -4; break; /* DA */
5811 case 1: offset
= 0; break; /* IA */
5812 case 2: offset
= -8; break; /* DB */
5813 case 3: offset
= 4; break; /* IB */
5817 tcg_gen_addi_i32(addr
, addr
, offset
);
5818 tmp
= load_reg(s
, 14);
5819 gen_st32(tmp
, addr
, 0);
5820 tmp
= load_cpu_field(spsr
);
5821 tcg_gen_addi_i32(addr
, addr
, 4);
5822 gen_st32(tmp
, addr
, 0);
5823 if (insn
& (1 << 21)) {
5824 /* Base writeback. */
5826 case 0: offset
= -8; break;
5827 case 1: offset
= 4; break;
5828 case 2: offset
= -4; break;
5829 case 3: offset
= 0; break;
5833 tcg_gen_addi_i32(addr
, addr
, offset
);
5834 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5835 store_reg(s
, 13, addr
);
5837 tmp
= tcg_const_i32(op1
);
5838 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
5839 tcg_temp_free_i32(tmp
);
5845 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5851 rn
= (insn
>> 16) & 0xf;
5852 addr
= load_reg(s
, rn
);
5853 i
= (insn
>> 23) & 3;
5855 case 0: offset
= -4; break; /* DA */
5856 case 1: offset
= 0; break; /* IA */
5857 case 2: offset
= -8; break; /* DB */
5858 case 3: offset
= 4; break; /* IB */
5862 tcg_gen_addi_i32(addr
, addr
, offset
);
5863 /* Load PC into tmp and CPSR into tmp2. */
5864 tmp
= gen_ld32(addr
, 0);
5865 tcg_gen_addi_i32(addr
, addr
, 4);
5866 tmp2
= gen_ld32(addr
, 0);
5867 if (insn
& (1 << 21)) {
5868 /* Base writeback. */
5870 case 0: offset
= -8; break;
5871 case 1: offset
= 4; break;
5872 case 2: offset
= -4; break;
5873 case 3: offset
= 0; break;
5877 tcg_gen_addi_i32(addr
, addr
, offset
);
5878 store_reg(s
, rn
, addr
);
5882 gen_rfe(s
, tmp
, tmp2
);
5884 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5885 /* branch link and change to thumb (blx <offset>) */
5888 val
= (uint32_t)s
->pc
;
5890 tcg_gen_movi_i32(tmp
, val
);
5891 store_reg(s
, 14, tmp
);
5892 /* Sign-extend the 24-bit offset */
5893 offset
= (((int32_t)insn
) << 8) >> 8;
5894 /* offset * 4 + bit24 * 2 + (thumb bit) */
5895 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5896 /* pipeline offset */
5900 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5901 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5902 /* iWMMXt register transfer. */
5903 if (env
->cp15
.c15_cpar
& (1 << 1))
5904 if (!disas_iwmmxt_insn(env
, s
, insn
))
5907 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5908 /* Coprocessor double register transfer. */
5909 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5910 /* Additional coprocessor register transfer. */
5911 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5914 /* cps (privileged) */
5918 if (insn
& (1 << 19)) {
5919 if (insn
& (1 << 8))
5921 if (insn
& (1 << 7))
5923 if (insn
& (1 << 6))
5925 if (insn
& (1 << 18))
5928 if (insn
& (1 << 17)) {
5930 val
|= (insn
& 0x1f);
5933 gen_set_psr_im(s
, mask
, 0, val
);
5940 /* if not always execute, we generate a conditional jump to
5942 s
->condlabel
= gen_new_label();
5943 gen_test_cc(cond
^ 1, s
->condlabel
);
5946 if ((insn
& 0x0f900000) == 0x03000000) {
5947 if ((insn
& (1 << 21)) == 0) {
5949 rd
= (insn
>> 12) & 0xf;
5950 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5951 if ((insn
& (1 << 22)) == 0) {
5954 tcg_gen_movi_i32(tmp
, val
);
5957 tmp
= load_reg(s
, rd
);
5958 tcg_gen_ext16u_i32(tmp
, tmp
);
5959 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5961 store_reg(s
, rd
, tmp
);
5963 if (((insn
>> 12) & 0xf) != 0xf)
5965 if (((insn
>> 16) & 0xf) == 0) {
5966 gen_nop_hint(s
, insn
& 0xff);
5968 /* CPSR = immediate */
5970 shift
= ((insn
>> 8) & 0xf) * 2;
5972 val
= (val
>> shift
) | (val
<< (32 - shift
));
5973 i
= ((insn
& (1 << 22)) != 0);
5974 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5978 } else if ((insn
& 0x0f900000) == 0x01000000
5979 && (insn
& 0x00000090) != 0x00000090) {
5980 /* miscellaneous instructions */
5981 op1
= (insn
>> 21) & 3;
5982 sh
= (insn
>> 4) & 0xf;
5985 case 0x0: /* move program status register */
5988 tmp
= load_reg(s
, rm
);
5989 i
= ((op1
& 2) != 0);
5990 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
5994 rd
= (insn
>> 12) & 0xf;
5998 tmp
= load_cpu_field(spsr
);
6001 gen_helper_cpsr_read(tmp
);
6003 store_reg(s
, rd
, tmp
);
6008 /* branch/exchange thumb (bx). */
6009 tmp
= load_reg(s
, rm
);
6011 } else if (op1
== 3) {
6013 rd
= (insn
>> 12) & 0xf;
6014 tmp
= load_reg(s
, rm
);
6015 gen_helper_clz(tmp
, tmp
);
6016 store_reg(s
, rd
, tmp
);
6024 /* Trivial implementation equivalent to bx. */
6025 tmp
= load_reg(s
, rm
);
6035 /* branch link/exchange thumb (blx) */
6036 tmp
= load_reg(s
, rm
);
6038 tcg_gen_movi_i32(tmp2
, s
->pc
);
6039 store_reg(s
, 14, tmp2
);
6042 case 0x5: /* saturating add/subtract */
6043 rd
= (insn
>> 12) & 0xf;
6044 rn
= (insn
>> 16) & 0xf;
6045 tmp
= load_reg(s
, rm
);
6046 tmp2
= load_reg(s
, rn
);
6048 gen_helper_double_saturate(tmp2
, tmp2
);
6050 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6052 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6054 store_reg(s
, rd
, tmp
);
6057 gen_set_condexec(s
);
6058 gen_set_pc_im(s
->pc
- 4);
6059 gen_exception(EXCP_BKPT
);
6060 s
->is_jmp
= DISAS_JUMP
;
6062 case 0x8: /* signed multiply */
6066 rs
= (insn
>> 8) & 0xf;
6067 rn
= (insn
>> 12) & 0xf;
6068 rd
= (insn
>> 16) & 0xf;
6070 /* (32 * 16) >> 16 */
6071 tmp
= load_reg(s
, rm
);
6072 tmp2
= load_reg(s
, rs
);
6074 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6077 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6078 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6080 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6081 tcg_temp_free_i64(tmp64
);
6082 if ((sh
& 2) == 0) {
6083 tmp2
= load_reg(s
, rn
);
6084 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6087 store_reg(s
, rd
, tmp
);
6090 tmp
= load_reg(s
, rm
);
6091 tmp2
= load_reg(s
, rs
);
6092 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6095 tmp64
= tcg_temp_new_i64();
6096 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6098 gen_addq(s
, tmp64
, rn
, rd
);
6099 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6100 tcg_temp_free_i64(tmp64
);
6103 tmp2
= load_reg(s
, rn
);
6104 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6107 store_reg(s
, rd
, tmp
);
6114 } else if (((insn
& 0x0e000000) == 0 &&
6115 (insn
& 0x00000090) != 0x90) ||
6116 ((insn
& 0x0e000000) == (1 << 25))) {
6117 int set_cc
, logic_cc
, shiftop
;
6119 op1
= (insn
>> 21) & 0xf;
6120 set_cc
= (insn
>> 20) & 1;
6121 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6123 /* data processing instruction */
6124 if (insn
& (1 << 25)) {
6125 /* immediate operand */
6127 shift
= ((insn
>> 8) & 0xf) * 2;
6129 val
= (val
>> shift
) | (val
<< (32 - shift
));
6132 tcg_gen_movi_i32(tmp2
, val
);
6133 if (logic_cc
&& shift
) {
6134 gen_set_CF_bit31(tmp2
);
6139 tmp2
= load_reg(s
, rm
);
6140 shiftop
= (insn
>> 5) & 3;
6141 if (!(insn
& (1 << 4))) {
6142 shift
= (insn
>> 7) & 0x1f;
6143 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6145 rs
= (insn
>> 8) & 0xf;
6146 tmp
= load_reg(s
, rs
);
6147 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6150 if (op1
!= 0x0f && op1
!= 0x0d) {
6151 rn
= (insn
>> 16) & 0xf;
6152 tmp
= load_reg(s
, rn
);
6156 rd
= (insn
>> 12) & 0xf;
6159 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6163 store_reg_bx(env
, s
, rd
, tmp
);
6166 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6170 store_reg_bx(env
, s
, rd
, tmp
);
6173 if (set_cc
&& rd
== 15) {
6174 /* SUBS r15, ... is used for exception return. */
6178 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6179 gen_exception_return(s
, tmp
);
6182 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6184 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6186 store_reg_bx(env
, s
, rd
, tmp
);
6191 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6193 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6195 store_reg_bx(env
, s
, rd
, tmp
);
6199 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6201 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6203 store_reg_bx(env
, s
, rd
, tmp
);
6207 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6209 gen_add_carry(tmp
, tmp
, tmp2
);
6211 store_reg_bx(env
, s
, rd
, tmp
);
6215 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6217 gen_sub_carry(tmp
, tmp
, tmp2
);
6219 store_reg_bx(env
, s
, rd
, tmp
);
6223 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6225 gen_sub_carry(tmp
, tmp2
, tmp
);
6227 store_reg_bx(env
, s
, rd
, tmp
);
6231 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6238 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6245 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6251 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6256 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6260 store_reg_bx(env
, s
, rd
, tmp
);
6263 if (logic_cc
&& rd
== 15) {
6264 /* MOVS r15, ... is used for exception return. */
6268 gen_exception_return(s
, tmp2
);
6273 store_reg_bx(env
, s
, rd
, tmp2
);
6277 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6281 store_reg_bx(env
, s
, rd
, tmp
);
6285 tcg_gen_not_i32(tmp2
, tmp2
);
6289 store_reg_bx(env
, s
, rd
, tmp2
);
6292 if (op1
!= 0x0f && op1
!= 0x0d) {
6296 /* other instructions */
6297 op1
= (insn
>> 24) & 0xf;
6301 /* multiplies, extra load/stores */
6302 sh
= (insn
>> 5) & 3;
6305 rd
= (insn
>> 16) & 0xf;
6306 rn
= (insn
>> 12) & 0xf;
6307 rs
= (insn
>> 8) & 0xf;
6309 op1
= (insn
>> 20) & 0xf;
6311 case 0: case 1: case 2: case 3: case 6:
6313 tmp
= load_reg(s
, rs
);
6314 tmp2
= load_reg(s
, rm
);
6315 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6317 if (insn
& (1 << 22)) {
6318 /* Subtract (mls) */
6320 tmp2
= load_reg(s
, rn
);
6321 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6323 } else if (insn
& (1 << 21)) {
6325 tmp2
= load_reg(s
, rn
);
6326 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6329 if (insn
& (1 << 20))
6331 store_reg(s
, rd
, tmp
);
6335 tmp
= load_reg(s
, rs
);
6336 tmp2
= load_reg(s
, rm
);
6337 if (insn
& (1 << 22))
6338 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6340 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6341 if (insn
& (1 << 21)) /* mult accumulate */
6342 gen_addq(s
, tmp64
, rn
, rd
);
6343 if (!(insn
& (1 << 23))) { /* double accumulate */
6345 gen_addq_lo(s
, tmp64
, rn
);
6346 gen_addq_lo(s
, tmp64
, rd
);
6348 if (insn
& (1 << 20))
6349 gen_logicq_cc(tmp64
);
6350 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6351 tcg_temp_free_i64(tmp64
);
6355 rn
= (insn
>> 16) & 0xf;
6356 rd
= (insn
>> 12) & 0xf;
6357 if (insn
& (1 << 23)) {
6358 /* load/store exclusive */
6359 op1
= (insn
>> 21) & 0x3;
6364 addr
= tcg_temp_local_new_i32();
6365 load_reg_var(s
, addr
, rn
);
6366 if (insn
& (1 << 20)) {
6367 gen_helper_mark_exclusive(cpu_env
, addr
);
6370 tmp
= gen_ld32(addr
, IS_USER(s
));
6372 case 1: /* ldrexd */
6373 tmp
= gen_ld32(addr
, IS_USER(s
));
6374 store_reg(s
, rd
, tmp
);
6375 tcg_gen_addi_i32(addr
, addr
, 4);
6376 tmp
= gen_ld32(addr
, IS_USER(s
));
6379 case 2: /* ldrexb */
6380 tmp
= gen_ld8u(addr
, IS_USER(s
));
6382 case 3: /* ldrexh */
6383 tmp
= gen_ld16u(addr
, IS_USER(s
));
6388 store_reg(s
, rd
, tmp
);
6390 int label
= gen_new_label();
6392 tmp2
= tcg_temp_local_new_i32();
6393 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6394 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6395 tmp
= load_reg(s
,rm
);
6398 gen_st32(tmp
, addr
, IS_USER(s
));
6400 case 1: /* strexd */
6401 gen_st32(tmp
, addr
, IS_USER(s
));
6402 tcg_gen_addi_i32(addr
, addr
, 4);
6403 tmp
= load_reg(s
, rm
+ 1);
6404 gen_st32(tmp
, addr
, IS_USER(s
));
6406 case 2: /* strexb */
6407 gen_st8(tmp
, addr
, IS_USER(s
));
6409 case 3: /* strexh */
6410 gen_st16(tmp
, addr
, IS_USER(s
));
6415 gen_set_label(label
);
6416 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6417 tcg_temp_free(tmp2
);
6419 tcg_temp_free(addr
);
6421 /* SWP instruction */
6424 /* ??? This is not really atomic. However we know
6425 we never have multiple CPUs running in parallel,
6426 so it is good enough. */
6427 addr
= load_reg(s
, rn
);
6428 tmp
= load_reg(s
, rm
);
6429 if (insn
& (1 << 22)) {
6430 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6431 gen_st8(tmp
, addr
, IS_USER(s
));
6433 tmp2
= gen_ld32(addr
, IS_USER(s
));
6434 gen_st32(tmp
, addr
, IS_USER(s
));
6437 store_reg(s
, rd
, tmp2
);
6443 /* Misc load/store */
6444 rn
= (insn
>> 16) & 0xf;
6445 rd
= (insn
>> 12) & 0xf;
6446 addr
= load_reg(s
, rn
);
6447 if (insn
& (1 << 24))
6448 gen_add_datah_offset(s
, insn
, 0, addr
);
6450 if (insn
& (1 << 20)) {
6454 tmp
= gen_ld16u(addr
, IS_USER(s
));
6457 tmp
= gen_ld8s(addr
, IS_USER(s
));
6461 tmp
= gen_ld16s(addr
, IS_USER(s
));
6465 } else if (sh
& 2) {
6469 tmp
= load_reg(s
, rd
);
6470 gen_st32(tmp
, addr
, IS_USER(s
));
6471 tcg_gen_addi_i32(addr
, addr
, 4);
6472 tmp
= load_reg(s
, rd
+ 1);
6473 gen_st32(tmp
, addr
, IS_USER(s
));
6477 tmp
= gen_ld32(addr
, IS_USER(s
));
6478 store_reg(s
, rd
, tmp
);
6479 tcg_gen_addi_i32(addr
, addr
, 4);
6480 tmp
= gen_ld32(addr
, IS_USER(s
));
6484 address_offset
= -4;
6487 tmp
= load_reg(s
, rd
);
6488 gen_st16(tmp
, addr
, IS_USER(s
));
6491 /* Perform base writeback before the loaded value to
6492 ensure correct behavior with overlapping index registers.
6493 ldrd with base writeback is is undefined if the
6494 destination and index registers overlap. */
6495 if (!(insn
& (1 << 24))) {
6496 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6497 store_reg(s
, rn
, addr
);
6498 } else if (insn
& (1 << 21)) {
6500 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6501 store_reg(s
, rn
, addr
);
6506 /* Complete the load. */
6507 store_reg(s
, rd
, tmp
);
6516 if (insn
& (1 << 4)) {
6518 /* Armv6 Media instructions. */
6520 rn
= (insn
>> 16) & 0xf;
6521 rd
= (insn
>> 12) & 0xf;
6522 rs
= (insn
>> 8) & 0xf;
6523 switch ((insn
>> 23) & 3) {
6524 case 0: /* Parallel add/subtract. */
6525 op1
= (insn
>> 20) & 7;
6526 tmp
= load_reg(s
, rn
);
6527 tmp2
= load_reg(s
, rm
);
6528 sh
= (insn
>> 5) & 7;
6529 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6531 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6533 store_reg(s
, rd
, tmp
);
6536 if ((insn
& 0x00700020) == 0) {
6537 /* Halfword pack. */
6538 tmp
= load_reg(s
, rn
);
6539 tmp2
= load_reg(s
, rm
);
6540 shift
= (insn
>> 7) & 0x1f;
6541 if (insn
& (1 << 6)) {
6545 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6546 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6547 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6551 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6552 tcg_gen_ext16u_i32(tmp
, tmp
);
6553 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6555 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6557 store_reg(s
, rd
, tmp
);
6558 } else if ((insn
& 0x00200020) == 0x00200000) {
6560 tmp
= load_reg(s
, rm
);
6561 shift
= (insn
>> 7) & 0x1f;
6562 if (insn
& (1 << 6)) {
6565 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6567 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6569 sh
= (insn
>> 16) & 0x1f;
6571 tmp2
= tcg_const_i32(sh
);
6572 if (insn
& (1 << 22))
6573 gen_helper_usat(tmp
, tmp
, tmp2
);
6575 gen_helper_ssat(tmp
, tmp
, tmp2
);
6576 tcg_temp_free_i32(tmp2
);
6578 store_reg(s
, rd
, tmp
);
6579 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6581 tmp
= load_reg(s
, rm
);
6582 sh
= (insn
>> 16) & 0x1f;
6584 tmp2
= tcg_const_i32(sh
);
6585 if (insn
& (1 << 22))
6586 gen_helper_usat16(tmp
, tmp
, tmp2
);
6588 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6589 tcg_temp_free_i32(tmp2
);
6591 store_reg(s
, rd
, tmp
);
6592 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6594 tmp
= load_reg(s
, rn
);
6595 tmp2
= load_reg(s
, rm
);
6597 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6598 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6601 store_reg(s
, rd
, tmp
);
6602 } else if ((insn
& 0x000003e0) == 0x00000060) {
6603 tmp
= load_reg(s
, rm
);
6604 shift
= (insn
>> 10) & 3;
6605 /* ??? In many cases it's not neccessary to do a
6606 rotate, a shift is sufficient. */
6608 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6609 op1
= (insn
>> 20) & 7;
6611 case 0: gen_sxtb16(tmp
); break;
6612 case 2: gen_sxtb(tmp
); break;
6613 case 3: gen_sxth(tmp
); break;
6614 case 4: gen_uxtb16(tmp
); break;
6615 case 6: gen_uxtb(tmp
); break;
6616 case 7: gen_uxth(tmp
); break;
6617 default: goto illegal_op
;
6620 tmp2
= load_reg(s
, rn
);
6621 if ((op1
& 3) == 0) {
6622 gen_add16(tmp
, tmp2
);
6624 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6628 store_reg(s
, rd
, tmp
);
6629 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6631 tmp
= load_reg(s
, rm
);
6632 if (insn
& (1 << 22)) {
6633 if (insn
& (1 << 7)) {
6637 gen_helper_rbit(tmp
, tmp
);
6640 if (insn
& (1 << 7))
6643 tcg_gen_bswap32_i32(tmp
, tmp
);
6645 store_reg(s
, rd
, tmp
);
6650 case 2: /* Multiplies (Type 3). */
6651 tmp
= load_reg(s
, rm
);
6652 tmp2
= load_reg(s
, rs
);
6653 if (insn
& (1 << 20)) {
6654 /* Signed multiply most significant [accumulate]. */
6655 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6656 if (insn
& (1 << 5))
6657 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6658 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6660 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6661 tcg_temp_free_i64(tmp64
);
6663 tmp2
= load_reg(s
, rd
);
6664 if (insn
& (1 << 6)) {
6665 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6667 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6671 store_reg(s
, rn
, tmp
);
6673 if (insn
& (1 << 5))
6674 gen_swap_half(tmp2
);
6675 gen_smul_dual(tmp
, tmp2
);
6676 /* This addition cannot overflow. */
6677 if (insn
& (1 << 6)) {
6678 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6680 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6683 if (insn
& (1 << 22)) {
6684 /* smlald, smlsld */
6685 tmp64
= tcg_temp_new_i64();
6686 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6688 gen_addq(s
, tmp64
, rd
, rn
);
6689 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6690 tcg_temp_free_i64(tmp64
);
6692 /* smuad, smusd, smlad, smlsd */
6695 tmp2
= load_reg(s
, rd
);
6696 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6699 store_reg(s
, rn
, tmp
);
6704 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6706 case 0: /* Unsigned sum of absolute differences. */
6708 tmp
= load_reg(s
, rm
);
6709 tmp2
= load_reg(s
, rs
);
6710 gen_helper_usad8(tmp
, tmp
, tmp2
);
6713 tmp2
= load_reg(s
, rd
);
6714 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6717 store_reg(s
, rn
, tmp
);
6719 case 0x20: case 0x24: case 0x28: case 0x2c:
6720 /* Bitfield insert/clear. */
6722 shift
= (insn
>> 7) & 0x1f;
6723 i
= (insn
>> 16) & 0x1f;
6727 tcg_gen_movi_i32(tmp
, 0);
6729 tmp
= load_reg(s
, rm
);
6732 tmp2
= load_reg(s
, rd
);
6733 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6736 store_reg(s
, rd
, tmp
);
6738 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6739 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6741 tmp
= load_reg(s
, rm
);
6742 shift
= (insn
>> 7) & 0x1f;
6743 i
= ((insn
>> 16) & 0x1f) + 1;
6748 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6750 gen_sbfx(tmp
, shift
, i
);
6753 store_reg(s
, rd
, tmp
);
6763 /* Check for undefined extension instructions
6764 * per the ARM Bible IE:
6765 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6767 sh
= (0xf << 20) | (0xf << 4);
6768 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6772 /* load/store byte/word */
6773 rn
= (insn
>> 16) & 0xf;
6774 rd
= (insn
>> 12) & 0xf;
6775 tmp2
= load_reg(s
, rn
);
6776 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6777 if (insn
& (1 << 24))
6778 gen_add_data_offset(s
, insn
, tmp2
);
6779 if (insn
& (1 << 20)) {
6781 if (insn
& (1 << 22)) {
6782 tmp
= gen_ld8u(tmp2
, i
);
6784 tmp
= gen_ld32(tmp2
, i
);
6788 tmp
= load_reg(s
, rd
);
6789 if (insn
& (1 << 22))
6790 gen_st8(tmp
, tmp2
, i
);
6792 gen_st32(tmp
, tmp2
, i
);
6794 if (!(insn
& (1 << 24))) {
6795 gen_add_data_offset(s
, insn
, tmp2
);
6796 store_reg(s
, rn
, tmp2
);
6797 } else if (insn
& (1 << 21)) {
6798 store_reg(s
, rn
, tmp2
);
6802 if (insn
& (1 << 20)) {
6803 /* Complete the load. */
6807 store_reg(s
, rd
, tmp
);
6813 int j
, n
, user
, loaded_base
;
6815 /* load/store multiple words */
6816 /* XXX: store correct base if write back */
6818 if (insn
& (1 << 22)) {
6820 goto illegal_op
; /* only usable in supervisor mode */
6822 if ((insn
& (1 << 15)) == 0)
6825 rn
= (insn
>> 16) & 0xf;
6826 addr
= load_reg(s
, rn
);
6828 /* compute total size */
6830 TCGV_UNUSED(loaded_var
);
6833 if (insn
& (1 << i
))
6836 /* XXX: test invalid n == 0 case ? */
6837 if (insn
& (1 << 23)) {
6838 if (insn
& (1 << 24)) {
6840 tcg_gen_addi_i32(addr
, addr
, 4);
6842 /* post increment */
6845 if (insn
& (1 << 24)) {
6847 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6849 /* post decrement */
6851 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6856 if (insn
& (1 << i
)) {
6857 if (insn
& (1 << 20)) {
6859 tmp
= gen_ld32(addr
, IS_USER(s
));
6863 tmp2
= tcg_const_i32(i
);
6864 gen_helper_set_user_reg(tmp2
, tmp
);
6865 tcg_temp_free_i32(tmp2
);
6867 } else if (i
== rn
) {
6871 store_reg(s
, i
, tmp
);
6876 /* special case: r15 = PC + 8 */
6877 val
= (long)s
->pc
+ 4;
6879 tcg_gen_movi_i32(tmp
, val
);
6882 tmp2
= tcg_const_i32(i
);
6883 gen_helper_get_user_reg(tmp
, tmp2
);
6884 tcg_temp_free_i32(tmp2
);
6886 tmp
= load_reg(s
, i
);
6888 gen_st32(tmp
, addr
, IS_USER(s
));
6891 /* no need to add after the last transfer */
6893 tcg_gen_addi_i32(addr
, addr
, 4);
6896 if (insn
& (1 << 21)) {
6898 if (insn
& (1 << 23)) {
6899 if (insn
& (1 << 24)) {
6902 /* post increment */
6903 tcg_gen_addi_i32(addr
, addr
, 4);
6906 if (insn
& (1 << 24)) {
6909 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6911 /* post decrement */
6912 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6915 store_reg(s
, rn
, addr
);
6920 store_reg(s
, rn
, loaded_var
);
6922 if ((insn
& (1 << 22)) && !user
) {
6923 /* Restore CPSR from SPSR. */
6924 tmp
= load_cpu_field(spsr
);
6925 gen_set_cpsr(tmp
, 0xffffffff);
6927 s
->is_jmp
= DISAS_UPDATE
;
6936 /* branch (and link) */
6937 val
= (int32_t)s
->pc
;
6938 if (insn
& (1 << 24)) {
6940 tcg_gen_movi_i32(tmp
, val
);
6941 store_reg(s
, 14, tmp
);
6943 offset
= (((int32_t)insn
<< 8) >> 8);
6944 val
+= (offset
<< 2) + 4;
6952 if (disas_coproc_insn(env
, s
, insn
))
6957 gen_set_pc_im(s
->pc
);
6958 s
->is_jmp
= DISAS_SWI
;
6962 gen_set_condexec(s
);
6963 gen_set_pc_im(s
->pc
- 4);
6964 gen_exception(EXCP_UDEF
);
6965 s
->is_jmp
= DISAS_JUMP
;
6971 /* Return true if this is a Thumb-2 logical op. */
6973 thumb2_logic_op(int op
)
6978 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6979 then set condition code flags based on the result of the operation.
6980 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6981 to the high bit of T1.
6982 Returns zero if the opcode is valid. */
6985 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
6992 tcg_gen_and_i32(t0
, t0
, t1
);
6996 tcg_gen_bic_i32(t0
, t0
, t1
);
7000 tcg_gen_or_i32(t0
, t0
, t1
);
7004 tcg_gen_not_i32(t1
, t1
);
7005 tcg_gen_or_i32(t0
, t0
, t1
);
7009 tcg_gen_xor_i32(t0
, t0
, t1
);
7014 gen_helper_add_cc(t0
, t0
, t1
);
7016 tcg_gen_add_i32(t0
, t0
, t1
);
7020 gen_helper_adc_cc(t0
, t0
, t1
);
7026 gen_helper_sbc_cc(t0
, t0
, t1
);
7028 gen_sub_carry(t0
, t0
, t1
);
7032 gen_helper_sub_cc(t0
, t0
, t1
);
7034 tcg_gen_sub_i32(t0
, t0
, t1
);
7038 gen_helper_sub_cc(t0
, t1
, t0
);
7040 tcg_gen_sub_i32(t0
, t1
, t0
);
7042 default: /* 5, 6, 7, 9, 12, 15. */
7048 gen_set_CF_bit31(t1
);
7053 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7055 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7057 uint32_t insn
, imm
, shift
, offset
;
7058 uint32_t rd
, rn
, rm
, rs
;
7069 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7070 || arm_feature (env
, ARM_FEATURE_M
))) {
7071 /* Thumb-1 cores may need to treat bl and blx as a pair of
7072 16-bit instructions to get correct prefetch abort behavior. */
7074 if ((insn
& (1 << 12)) == 0) {
7075 /* Second half of blx. */
7076 offset
= ((insn
& 0x7ff) << 1);
7077 tmp
= load_reg(s
, 14);
7078 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7079 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7082 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7083 store_reg(s
, 14, tmp2
);
7087 if (insn
& (1 << 11)) {
7088 /* Second half of bl. */
7089 offset
= ((insn
& 0x7ff) << 1) | 1;
7090 tmp
= load_reg(s
, 14);
7091 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7094 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7095 store_reg(s
, 14, tmp2
);
7099 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7100 /* Instruction spans a page boundary. Implement it as two
7101 16-bit instructions in case the second half causes an
7103 offset
= ((int32_t)insn
<< 21) >> 9;
7104 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7107 /* Fall through to 32-bit decode. */
7110 insn
= lduw_code(s
->pc
);
7112 insn
|= (uint32_t)insn_hw1
<< 16;
7114 if ((insn
& 0xf800e800) != 0xf000e800) {
7118 rn
= (insn
>> 16) & 0xf;
7119 rs
= (insn
>> 12) & 0xf;
7120 rd
= (insn
>> 8) & 0xf;
7122 switch ((insn
>> 25) & 0xf) {
7123 case 0: case 1: case 2: case 3:
7124 /* 16-bit instructions. Should never happen. */
7127 if (insn
& (1 << 22)) {
7128 /* Other load/store, table branch. */
7129 if (insn
& 0x01200000) {
7130 /* Load/store doubleword. */
7133 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7135 addr
= load_reg(s
, rn
);
7137 offset
= (insn
& 0xff) * 4;
7138 if ((insn
& (1 << 23)) == 0)
7140 if (insn
& (1 << 24)) {
7141 tcg_gen_addi_i32(addr
, addr
, offset
);
7144 if (insn
& (1 << 20)) {
7146 tmp
= gen_ld32(addr
, IS_USER(s
));
7147 store_reg(s
, rs
, tmp
);
7148 tcg_gen_addi_i32(addr
, addr
, 4);
7149 tmp
= gen_ld32(addr
, IS_USER(s
));
7150 store_reg(s
, rd
, tmp
);
7153 tmp
= load_reg(s
, rs
);
7154 gen_st32(tmp
, addr
, IS_USER(s
));
7155 tcg_gen_addi_i32(addr
, addr
, 4);
7156 tmp
= load_reg(s
, rd
);
7157 gen_st32(tmp
, addr
, IS_USER(s
));
7159 if (insn
& (1 << 21)) {
7160 /* Base writeback. */
7163 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7164 store_reg(s
, rn
, addr
);
7168 } else if ((insn
& (1 << 23)) == 0) {
7169 /* Load/store exclusive word. */
7170 addr
= tcg_temp_local_new();
7171 load_reg_var(s
, addr
, rn
);
7172 if (insn
& (1 << 20)) {
7173 gen_helper_mark_exclusive(cpu_env
, addr
);
7174 tmp
= gen_ld32(addr
, IS_USER(s
));
7175 store_reg(s
, rd
, tmp
);
7177 int label
= gen_new_label();
7178 tmp2
= tcg_temp_local_new();
7179 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7180 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7181 tmp
= load_reg(s
, rs
);
7182 gen_st32(tmp
, addr
, IS_USER(s
));
7183 gen_set_label(label
);
7184 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7185 tcg_temp_free(tmp2
);
7187 tcg_temp_free(addr
);
7188 } else if ((insn
& (1 << 6)) == 0) {
7192 tcg_gen_movi_i32(addr
, s
->pc
);
7194 addr
= load_reg(s
, rn
);
7196 tmp
= load_reg(s
, rm
);
7197 tcg_gen_add_i32(addr
, addr
, tmp
);
7198 if (insn
& (1 << 4)) {
7200 tcg_gen_add_i32(addr
, addr
, tmp
);
7202 tmp
= gen_ld16u(addr
, IS_USER(s
));
7205 tmp
= gen_ld8u(addr
, IS_USER(s
));
7208 tcg_gen_shli_i32(tmp
, tmp
, 1);
7209 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7210 store_reg(s
, 15, tmp
);
7212 /* Load/store exclusive byte/halfword/doubleword. */
7213 /* ??? These are not really atomic. However we know
7214 we never have multiple CPUs running in parallel,
7215 so it is good enough. */
7216 op
= (insn
>> 4) & 0x3;
7217 addr
= tcg_temp_local_new();
7218 load_reg_var(s
, addr
, rn
);
7219 if (insn
& (1 << 20)) {
7220 gen_helper_mark_exclusive(cpu_env
, addr
);
7223 tmp
= gen_ld8u(addr
, IS_USER(s
));
7226 tmp
= gen_ld16u(addr
, IS_USER(s
));
7229 tmp
= gen_ld32(addr
, IS_USER(s
));
7230 tcg_gen_addi_i32(addr
, addr
, 4);
7231 tmp2
= gen_ld32(addr
, IS_USER(s
));
7232 store_reg(s
, rd
, tmp2
);
7237 store_reg(s
, rs
, tmp
);
7239 int label
= gen_new_label();
7240 tmp2
= tcg_temp_local_new();
7241 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7242 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7243 tmp
= load_reg(s
, rs
);
7246 gen_st8(tmp
, addr
, IS_USER(s
));
7249 gen_st16(tmp
, addr
, IS_USER(s
));
7252 gen_st32(tmp
, addr
, IS_USER(s
));
7253 tcg_gen_addi_i32(addr
, addr
, 4);
7254 tmp
= load_reg(s
, rd
);
7255 gen_st32(tmp
, addr
, IS_USER(s
));
7260 gen_set_label(label
);
7261 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7262 tcg_temp_free(tmp2
);
7264 tcg_temp_free(addr
);
7267 /* Load/store multiple, RFE, SRS. */
7268 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7269 /* Not available in user mode. */
7272 if (insn
& (1 << 20)) {
7274 addr
= load_reg(s
, rn
);
7275 if ((insn
& (1 << 24)) == 0)
7276 tcg_gen_addi_i32(addr
, addr
, -8);
7277 /* Load PC into tmp and CPSR into tmp2. */
7278 tmp
= gen_ld32(addr
, 0);
7279 tcg_gen_addi_i32(addr
, addr
, 4);
7280 tmp2
= gen_ld32(addr
, 0);
7281 if (insn
& (1 << 21)) {
7282 /* Base writeback. */
7283 if (insn
& (1 << 24)) {
7284 tcg_gen_addi_i32(addr
, addr
, 4);
7286 tcg_gen_addi_i32(addr
, addr
, -4);
7288 store_reg(s
, rn
, addr
);
7292 gen_rfe(s
, tmp
, tmp2
);
7296 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7297 addr
= load_reg(s
, 13);
7300 tmp
= tcg_const_i32(op
);
7301 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7302 tcg_temp_free_i32(tmp
);
7304 if ((insn
& (1 << 24)) == 0) {
7305 tcg_gen_addi_i32(addr
, addr
, -8);
7307 tmp
= load_reg(s
, 14);
7308 gen_st32(tmp
, addr
, 0);
7309 tcg_gen_addi_i32(addr
, addr
, 4);
7311 gen_helper_cpsr_read(tmp
);
7312 gen_st32(tmp
, addr
, 0);
7313 if (insn
& (1 << 21)) {
7314 if ((insn
& (1 << 24)) == 0) {
7315 tcg_gen_addi_i32(addr
, addr
, -4);
7317 tcg_gen_addi_i32(addr
, addr
, 4);
7319 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7320 store_reg(s
, 13, addr
);
7322 tmp
= tcg_const_i32(op
);
7323 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7324 tcg_temp_free_i32(tmp
);
7332 /* Load/store multiple. */
7333 addr
= load_reg(s
, rn
);
7335 for (i
= 0; i
< 16; i
++) {
7336 if (insn
& (1 << i
))
7339 if (insn
& (1 << 24)) {
7340 tcg_gen_addi_i32(addr
, addr
, -offset
);
7343 for (i
= 0; i
< 16; i
++) {
7344 if ((insn
& (1 << i
)) == 0)
7346 if (insn
& (1 << 20)) {
7348 tmp
= gen_ld32(addr
, IS_USER(s
));
7352 store_reg(s
, i
, tmp
);
7356 tmp
= load_reg(s
, i
);
7357 gen_st32(tmp
, addr
, IS_USER(s
));
7359 tcg_gen_addi_i32(addr
, addr
, 4);
7361 if (insn
& (1 << 21)) {
7362 /* Base register writeback. */
7363 if (insn
& (1 << 24)) {
7364 tcg_gen_addi_i32(addr
, addr
, -offset
);
7366 /* Fault if writeback register is in register list. */
7367 if (insn
& (1 << rn
))
7369 store_reg(s
, rn
, addr
);
7376 case 5: /* Data processing register constant shift. */
7379 tcg_gen_movi_i32(tmp
, 0);
7381 tmp
= load_reg(s
, rn
);
7383 tmp2
= load_reg(s
, rm
);
7384 op
= (insn
>> 21) & 0xf;
7385 shiftop
= (insn
>> 4) & 3;
7386 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7387 conds
= (insn
& (1 << 20)) != 0;
7388 logic_cc
= (conds
&& thumb2_logic_op(op
));
7389 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7390 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7394 store_reg(s
, rd
, tmp
);
7399 case 13: /* Misc data processing. */
7400 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7401 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7404 case 0: /* Register controlled shift. */
7405 tmp
= load_reg(s
, rn
);
7406 tmp2
= load_reg(s
, rm
);
7407 if ((insn
& 0x70) != 0)
7409 op
= (insn
>> 21) & 3;
7410 logic_cc
= (insn
& (1 << 20)) != 0;
7411 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7414 store_reg_bx(env
, s
, rd
, tmp
);
7416 case 1: /* Sign/zero extend. */
7417 tmp
= load_reg(s
, rm
);
7418 shift
= (insn
>> 4) & 3;
7419 /* ??? In many cases it's not neccessary to do a
7420 rotate, a shift is sufficient. */
7422 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7423 op
= (insn
>> 20) & 7;
7425 case 0: gen_sxth(tmp
); break;
7426 case 1: gen_uxth(tmp
); break;
7427 case 2: gen_sxtb16(tmp
); break;
7428 case 3: gen_uxtb16(tmp
); break;
7429 case 4: gen_sxtb(tmp
); break;
7430 case 5: gen_uxtb(tmp
); break;
7431 default: goto illegal_op
;
7434 tmp2
= load_reg(s
, rn
);
7435 if ((op
>> 1) == 1) {
7436 gen_add16(tmp
, tmp2
);
7438 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7442 store_reg(s
, rd
, tmp
);
7444 case 2: /* SIMD add/subtract. */
7445 op
= (insn
>> 20) & 7;
7446 shift
= (insn
>> 4) & 7;
7447 if ((op
& 3) == 3 || (shift
& 3) == 3)
7449 tmp
= load_reg(s
, rn
);
7450 tmp2
= load_reg(s
, rm
);
7451 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7453 store_reg(s
, rd
, tmp
);
7455 case 3: /* Other data processing. */
7456 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7458 /* Saturating add/subtract. */
7459 tmp
= load_reg(s
, rn
);
7460 tmp2
= load_reg(s
, rm
);
7462 gen_helper_double_saturate(tmp
, tmp
);
7464 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7466 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7469 tmp
= load_reg(s
, rn
);
7471 case 0x0a: /* rbit */
7472 gen_helper_rbit(tmp
, tmp
);
7474 case 0x08: /* rev */
7475 tcg_gen_bswap32_i32(tmp
, tmp
);
7477 case 0x09: /* rev16 */
7480 case 0x0b: /* revsh */
7483 case 0x10: /* sel */
7484 tmp2
= load_reg(s
, rm
);
7486 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7487 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7491 case 0x18: /* clz */
7492 gen_helper_clz(tmp
, tmp
);
7498 store_reg(s
, rd
, tmp
);
7500 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7501 op
= (insn
>> 4) & 0xf;
7502 tmp
= load_reg(s
, rn
);
7503 tmp2
= load_reg(s
, rm
);
7504 switch ((insn
>> 20) & 7) {
7505 case 0: /* 32 x 32 -> 32 */
7506 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7509 tmp2
= load_reg(s
, rs
);
7511 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7513 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7517 case 1: /* 16 x 16 -> 32 */
7518 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7521 tmp2
= load_reg(s
, rs
);
7522 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7526 case 2: /* Dual multiply add. */
7527 case 4: /* Dual multiply subtract. */
7529 gen_swap_half(tmp2
);
7530 gen_smul_dual(tmp
, tmp2
);
7531 /* This addition cannot overflow. */
7532 if (insn
& (1 << 22)) {
7533 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7535 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7540 tmp2
= load_reg(s
, rs
);
7541 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7545 case 3: /* 32 * 16 -> 32msb */
7547 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7550 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7551 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7553 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7554 tcg_temp_free_i64(tmp64
);
7557 tmp2
= load_reg(s
, rs
);
7558 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7562 case 5: case 6: /* 32 * 32 -> 32msb */
7563 gen_imull(tmp
, tmp2
);
7564 if (insn
& (1 << 5)) {
7565 gen_roundqd(tmp
, tmp2
);
7572 tmp2
= load_reg(s
, rs
);
7573 if (insn
& (1 << 21)) {
7574 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7576 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7581 case 7: /* Unsigned sum of absolute differences. */
7582 gen_helper_usad8(tmp
, tmp
, tmp2
);
7585 tmp2
= load_reg(s
, rs
);
7586 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7591 store_reg(s
, rd
, tmp
);
7593 case 6: case 7: /* 64-bit multiply, Divide. */
7594 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7595 tmp
= load_reg(s
, rn
);
7596 tmp2
= load_reg(s
, rm
);
7597 if ((op
& 0x50) == 0x10) {
7599 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7602 gen_helper_udiv(tmp
, tmp
, tmp2
);
7604 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7606 store_reg(s
, rd
, tmp
);
7607 } else if ((op
& 0xe) == 0xc) {
7608 /* Dual multiply accumulate long. */
7610 gen_swap_half(tmp2
);
7611 gen_smul_dual(tmp
, tmp2
);
7613 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7615 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7619 tmp64
= tcg_temp_new_i64();
7620 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7622 gen_addq(s
, tmp64
, rs
, rd
);
7623 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7624 tcg_temp_free_i64(tmp64
);
7627 /* Unsigned 64-bit multiply */
7628 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7632 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7634 tmp64
= tcg_temp_new_i64();
7635 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7638 /* Signed 64-bit multiply */
7639 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7644 gen_addq_lo(s
, tmp64
, rs
);
7645 gen_addq_lo(s
, tmp64
, rd
);
7646 } else if (op
& 0x40) {
7647 /* 64-bit accumulate. */
7648 gen_addq(s
, tmp64
, rs
, rd
);
7650 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7651 tcg_temp_free_i64(tmp64
);
7656 case 6: case 7: case 14: case 15:
7658 if (((insn
>> 24) & 3) == 3) {
7659 /* Translate into the equivalent ARM encoding. */
7660 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7661 if (disas_neon_data_insn(env
, s
, insn
))
7664 if (insn
& (1 << 28))
7666 if (disas_coproc_insn (env
, s
, insn
))
7670 case 8: case 9: case 10: case 11:
7671 if (insn
& (1 << 15)) {
7672 /* Branches, misc control. */
7673 if (insn
& 0x5000) {
7674 /* Unconditional branch. */
7675 /* signextend(hw1[10:0]) -> offset[:12]. */
7676 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7677 /* hw1[10:0] -> offset[11:1]. */
7678 offset
|= (insn
& 0x7ff) << 1;
7679 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7680 offset[24:22] already have the same value because of the
7681 sign extension above. */
7682 offset
^= ((~insn
) & (1 << 13)) << 10;
7683 offset
^= ((~insn
) & (1 << 11)) << 11;
7685 if (insn
& (1 << 14)) {
7686 /* Branch and link. */
7687 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7691 if (insn
& (1 << 12)) {
7696 offset
&= ~(uint32_t)2;
7697 gen_bx_im(s
, offset
);
7699 } else if (((insn
>> 23) & 7) == 7) {
7701 if (insn
& (1 << 13))
7704 if (insn
& (1 << 26)) {
7705 /* Secure monitor call (v6Z) */
7706 goto illegal_op
; /* not implemented. */
7708 op
= (insn
>> 20) & 7;
7710 case 0: /* msr cpsr. */
7712 tmp
= load_reg(s
, rn
);
7713 addr
= tcg_const_i32(insn
& 0xff);
7714 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7715 tcg_temp_free_i32(addr
);
7721 case 1: /* msr spsr. */
7724 tmp
= load_reg(s
, rn
);
7726 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7730 case 2: /* cps, nop-hint. */
7731 if (((insn
>> 8) & 7) == 0) {
7732 gen_nop_hint(s
, insn
& 0xff);
7734 /* Implemented as NOP in user mode. */
7739 if (insn
& (1 << 10)) {
7740 if (insn
& (1 << 7))
7742 if (insn
& (1 << 6))
7744 if (insn
& (1 << 5))
7746 if (insn
& (1 << 9))
7747 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7749 if (insn
& (1 << 8)) {
7751 imm
|= (insn
& 0x1f);
7754 gen_set_psr_im(s
, offset
, 0, imm
);
7757 case 3: /* Special control operations. */
7758 op
= (insn
>> 4) & 0xf;
7761 gen_helper_clrex(cpu_env
);
7766 /* These execute as NOPs. */
7774 /* Trivial implementation equivalent to bx. */
7775 tmp
= load_reg(s
, rn
);
7778 case 5: /* Exception return. */
7779 /* Unpredictable in user mode. */
7781 case 6: /* mrs cpsr. */
7784 addr
= tcg_const_i32(insn
& 0xff);
7785 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7786 tcg_temp_free_i32(addr
);
7788 gen_helper_cpsr_read(tmp
);
7790 store_reg(s
, rd
, tmp
);
7792 case 7: /* mrs spsr. */
7793 /* Not accessible in user mode. */
7794 if (IS_USER(s
) || IS_M(env
))
7796 tmp
= load_cpu_field(spsr
);
7797 store_reg(s
, rd
, tmp
);
7802 /* Conditional branch. */
7803 op
= (insn
>> 22) & 0xf;
7804 /* Generate a conditional jump to next instruction. */
7805 s
->condlabel
= gen_new_label();
7806 gen_test_cc(op
^ 1, s
->condlabel
);
7809 /* offset[11:1] = insn[10:0] */
7810 offset
= (insn
& 0x7ff) << 1;
7811 /* offset[17:12] = insn[21:16]. */
7812 offset
|= (insn
& 0x003f0000) >> 4;
7813 /* offset[31:20] = insn[26]. */
7814 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7815 /* offset[18] = insn[13]. */
7816 offset
|= (insn
& (1 << 13)) << 5;
7817 /* offset[19] = insn[11]. */
7818 offset
|= (insn
& (1 << 11)) << 8;
7820 /* jump to the offset */
7821 gen_jmp(s
, s
->pc
+ offset
);
7824 /* Data processing immediate. */
7825 if (insn
& (1 << 25)) {
7826 if (insn
& (1 << 24)) {
7827 if (insn
& (1 << 20))
7829 /* Bitfield/Saturate. */
7830 op
= (insn
>> 21) & 7;
7832 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7835 tcg_gen_movi_i32(tmp
, 0);
7837 tmp
= load_reg(s
, rn
);
7840 case 2: /* Signed bitfield extract. */
7842 if (shift
+ imm
> 32)
7845 gen_sbfx(tmp
, shift
, imm
);
7847 case 6: /* Unsigned bitfield extract. */
7849 if (shift
+ imm
> 32)
7852 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7854 case 3: /* Bitfield insert/clear. */
7857 imm
= imm
+ 1 - shift
;
7859 tmp2
= load_reg(s
, rd
);
7860 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7866 default: /* Saturate. */
7869 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7871 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7873 tmp2
= tcg_const_i32(imm
);
7876 if ((op
& 1) && shift
== 0)
7877 gen_helper_usat16(tmp
, tmp
, tmp2
);
7879 gen_helper_usat(tmp
, tmp
, tmp2
);
7882 if ((op
& 1) && shift
== 0)
7883 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7885 gen_helper_ssat(tmp
, tmp
, tmp2
);
7887 tcg_temp_free_i32(tmp2
);
7890 store_reg(s
, rd
, tmp
);
7892 imm
= ((insn
& 0x04000000) >> 15)
7893 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7894 if (insn
& (1 << 22)) {
7895 /* 16-bit immediate. */
7896 imm
|= (insn
>> 4) & 0xf000;
7897 if (insn
& (1 << 23)) {
7899 tmp
= load_reg(s
, rd
);
7900 tcg_gen_ext16u_i32(tmp
, tmp
);
7901 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7905 tcg_gen_movi_i32(tmp
, imm
);
7908 /* Add/sub 12-bit immediate. */
7910 offset
= s
->pc
& ~(uint32_t)3;
7911 if (insn
& (1 << 23))
7916 tcg_gen_movi_i32(tmp
, offset
);
7918 tmp
= load_reg(s
, rn
);
7919 if (insn
& (1 << 23))
7920 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7922 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7925 store_reg(s
, rd
, tmp
);
7928 int shifter_out
= 0;
7929 /* modified 12-bit immediate. */
7930 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7931 imm
= (insn
& 0xff);
7934 /* Nothing to do. */
7936 case 1: /* 00XY00XY */
7939 case 2: /* XY00XY00 */
7943 case 3: /* XYXYXYXY */
7947 default: /* Rotated constant. */
7948 shift
= (shift
<< 1) | (imm
>> 7);
7950 imm
= imm
<< (32 - shift
);
7955 tcg_gen_movi_i32(tmp2
, imm
);
7956 rn
= (insn
>> 16) & 0xf;
7959 tcg_gen_movi_i32(tmp
, 0);
7961 tmp
= load_reg(s
, rn
);
7963 op
= (insn
>> 21) & 0xf;
7964 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7965 shifter_out
, tmp
, tmp2
))
7968 rd
= (insn
>> 8) & 0xf;
7970 store_reg(s
, rd
, tmp
);
7977 case 12: /* Load/store single data item. */
7982 if ((insn
& 0x01100000) == 0x01000000) {
7983 if (disas_neon_ls_insn(env
, s
, insn
))
7991 /* s->pc has already been incremented by 4. */
7992 imm
= s
->pc
& 0xfffffffc;
7993 if (insn
& (1 << 23))
7994 imm
+= insn
& 0xfff;
7996 imm
-= insn
& 0xfff;
7997 tcg_gen_movi_i32(addr
, imm
);
7999 addr
= load_reg(s
, rn
);
8000 if (insn
& (1 << 23)) {
8001 /* Positive offset. */
8003 tcg_gen_addi_i32(addr
, addr
, imm
);
8005 op
= (insn
>> 8) & 7;
8008 case 0: case 8: /* Shifted Register. */
8009 shift
= (insn
>> 4) & 0xf;
8012 tmp
= load_reg(s
, rm
);
8014 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8015 tcg_gen_add_i32(addr
, addr
, tmp
);
8018 case 4: /* Negative offset. */
8019 tcg_gen_addi_i32(addr
, addr
, -imm
);
8021 case 6: /* User privilege. */
8022 tcg_gen_addi_i32(addr
, addr
, imm
);
8025 case 1: /* Post-decrement. */
8028 case 3: /* Post-increment. */
8032 case 5: /* Pre-decrement. */
8035 case 7: /* Pre-increment. */
8036 tcg_gen_addi_i32(addr
, addr
, imm
);
8044 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8045 if (insn
& (1 << 20)) {
8047 if (rs
== 15 && op
!= 2) {
8050 /* Memory hint. Implemented as NOP. */
8053 case 0: tmp
= gen_ld8u(addr
, user
); break;
8054 case 4: tmp
= gen_ld8s(addr
, user
); break;
8055 case 1: tmp
= gen_ld16u(addr
, user
); break;
8056 case 5: tmp
= gen_ld16s(addr
, user
); break;
8057 case 2: tmp
= gen_ld32(addr
, user
); break;
8058 default: goto illegal_op
;
8063 store_reg(s
, rs
, tmp
);
8070 tmp
= load_reg(s
, rs
);
8072 case 0: gen_st8(tmp
, addr
, user
); break;
8073 case 1: gen_st16(tmp
, addr
, user
); break;
8074 case 2: gen_st32(tmp
, addr
, user
); break;
8075 default: goto illegal_op
;
8079 tcg_gen_addi_i32(addr
, addr
, imm
);
8081 store_reg(s
, rn
, addr
);
8095 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8097 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8104 if (s
->condexec_mask
) {
8105 cond
= s
->condexec_cond
;
8106 s
->condlabel
= gen_new_label();
8107 gen_test_cc(cond
^ 1, s
->condlabel
);
8111 insn
= lduw_code(s
->pc
);
8114 switch (insn
>> 12) {
8118 op
= (insn
>> 11) & 3;
8121 rn
= (insn
>> 3) & 7;
8122 tmp
= load_reg(s
, rn
);
8123 if (insn
& (1 << 10)) {
8126 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8129 rm
= (insn
>> 6) & 7;
8130 tmp2
= load_reg(s
, rm
);
8132 if (insn
& (1 << 9)) {
8133 if (s
->condexec_mask
)
8134 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8136 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8138 if (s
->condexec_mask
)
8139 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8141 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8144 store_reg(s
, rd
, tmp
);
8146 /* shift immediate */
8147 rm
= (insn
>> 3) & 7;
8148 shift
= (insn
>> 6) & 0x1f;
8149 tmp
= load_reg(s
, rm
);
8150 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8151 if (!s
->condexec_mask
)
8153 store_reg(s
, rd
, tmp
);
8157 /* arithmetic large immediate */
8158 op
= (insn
>> 11) & 3;
8159 rd
= (insn
>> 8) & 0x7;
8160 if (op
== 0) { /* mov */
8162 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8163 if (!s
->condexec_mask
)
8165 store_reg(s
, rd
, tmp
);
8167 tmp
= load_reg(s
, rd
);
8169 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8172 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8177 if (s
->condexec_mask
)
8178 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8180 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8182 store_reg(s
, rd
, tmp
);
8185 if (s
->condexec_mask
)
8186 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8188 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8190 store_reg(s
, rd
, tmp
);
8196 if (insn
& (1 << 11)) {
8197 rd
= (insn
>> 8) & 7;
8198 /* load pc-relative. Bit 1 of PC is ignored. */
8199 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8200 val
&= ~(uint32_t)2;
8202 tcg_gen_movi_i32(addr
, val
);
8203 tmp
= gen_ld32(addr
, IS_USER(s
));
8205 store_reg(s
, rd
, tmp
);
8208 if (insn
& (1 << 10)) {
8209 /* data processing extended or blx */
8210 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8211 rm
= (insn
>> 3) & 0xf;
8212 op
= (insn
>> 8) & 3;
8215 tmp
= load_reg(s
, rd
);
8216 tmp2
= load_reg(s
, rm
);
8217 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8219 store_reg(s
, rd
, tmp
);
8222 tmp
= load_reg(s
, rd
);
8223 tmp2
= load_reg(s
, rm
);
8224 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8228 case 2: /* mov/cpy */
8229 tmp
= load_reg(s
, rm
);
8230 store_reg(s
, rd
, tmp
);
8232 case 3:/* branch [and link] exchange thumb register */
8233 tmp
= load_reg(s
, rm
);
8234 if (insn
& (1 << 7)) {
8235 val
= (uint32_t)s
->pc
| 1;
8237 tcg_gen_movi_i32(tmp2
, val
);
8238 store_reg(s
, 14, tmp2
);
8246 /* data processing register */
8248 rm
= (insn
>> 3) & 7;
8249 op
= (insn
>> 6) & 0xf;
8250 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8251 /* the shift/rotate ops want the operands backwards */
8260 if (op
== 9) { /* neg */
8262 tcg_gen_movi_i32(tmp
, 0);
8263 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8264 tmp
= load_reg(s
, rd
);
8269 tmp2
= load_reg(s
, rm
);
8272 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8273 if (!s
->condexec_mask
)
8277 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8278 if (!s
->condexec_mask
)
8282 if (s
->condexec_mask
) {
8283 gen_helper_shl(tmp2
, tmp2
, tmp
);
8285 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8290 if (s
->condexec_mask
) {
8291 gen_helper_shr(tmp2
, tmp2
, tmp
);
8293 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8298 if (s
->condexec_mask
) {
8299 gen_helper_sar(tmp2
, tmp2
, tmp
);
8301 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8306 if (s
->condexec_mask
)
8309 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8312 if (s
->condexec_mask
)
8313 gen_sub_carry(tmp
, tmp
, tmp2
);
8315 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8318 if (s
->condexec_mask
) {
8319 gen_helper_ror(tmp2
, tmp2
, tmp
);
8321 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8326 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8331 if (s
->condexec_mask
)
8332 tcg_gen_neg_i32(tmp
, tmp2
);
8334 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8337 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8341 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8345 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8346 if (!s
->condexec_mask
)
8350 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8351 if (!s
->condexec_mask
)
8355 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8356 if (!s
->condexec_mask
)
8360 tcg_gen_not_i32(tmp2
, tmp2
);
8361 if (!s
->condexec_mask
)
8369 store_reg(s
, rm
, tmp2
);
8373 store_reg(s
, rd
, tmp
);
8383 /* load/store register offset. */
8385 rn
= (insn
>> 3) & 7;
8386 rm
= (insn
>> 6) & 7;
8387 op
= (insn
>> 9) & 7;
8388 addr
= load_reg(s
, rn
);
8389 tmp
= load_reg(s
, rm
);
8390 tcg_gen_add_i32(addr
, addr
, tmp
);
8393 if (op
< 3) /* store */
8394 tmp
= load_reg(s
, rd
);
8398 gen_st32(tmp
, addr
, IS_USER(s
));
8401 gen_st16(tmp
, addr
, IS_USER(s
));
8404 gen_st8(tmp
, addr
, IS_USER(s
));
8407 tmp
= gen_ld8s(addr
, IS_USER(s
));
8410 tmp
= gen_ld32(addr
, IS_USER(s
));
8413 tmp
= gen_ld16u(addr
, IS_USER(s
));
8416 tmp
= gen_ld8u(addr
, IS_USER(s
));
8419 tmp
= gen_ld16s(addr
, IS_USER(s
));
8422 if (op
>= 3) /* load */
8423 store_reg(s
, rd
, tmp
);
8428 /* load/store word immediate offset */
8430 rn
= (insn
>> 3) & 7;
8431 addr
= load_reg(s
, rn
);
8432 val
= (insn
>> 4) & 0x7c;
8433 tcg_gen_addi_i32(addr
, addr
, val
);
8435 if (insn
& (1 << 11)) {
8437 tmp
= gen_ld32(addr
, IS_USER(s
));
8438 store_reg(s
, rd
, tmp
);
8441 tmp
= load_reg(s
, rd
);
8442 gen_st32(tmp
, addr
, IS_USER(s
));
8448 /* load/store byte immediate offset */
8450 rn
= (insn
>> 3) & 7;
8451 addr
= load_reg(s
, rn
);
8452 val
= (insn
>> 6) & 0x1f;
8453 tcg_gen_addi_i32(addr
, addr
, val
);
8455 if (insn
& (1 << 11)) {
8457 tmp
= gen_ld8u(addr
, IS_USER(s
));
8458 store_reg(s
, rd
, tmp
);
8461 tmp
= load_reg(s
, rd
);
8462 gen_st8(tmp
, addr
, IS_USER(s
));
8468 /* load/store halfword immediate offset */
8470 rn
= (insn
>> 3) & 7;
8471 addr
= load_reg(s
, rn
);
8472 val
= (insn
>> 5) & 0x3e;
8473 tcg_gen_addi_i32(addr
, addr
, val
);
8475 if (insn
& (1 << 11)) {
8477 tmp
= gen_ld16u(addr
, IS_USER(s
));
8478 store_reg(s
, rd
, tmp
);
8481 tmp
= load_reg(s
, rd
);
8482 gen_st16(tmp
, addr
, IS_USER(s
));
8488 /* load/store from stack */
8489 rd
= (insn
>> 8) & 7;
8490 addr
= load_reg(s
, 13);
8491 val
= (insn
& 0xff) * 4;
8492 tcg_gen_addi_i32(addr
, addr
, val
);
8494 if (insn
& (1 << 11)) {
8496 tmp
= gen_ld32(addr
, IS_USER(s
));
8497 store_reg(s
, rd
, tmp
);
8500 tmp
= load_reg(s
, rd
);
8501 gen_st32(tmp
, addr
, IS_USER(s
));
8507 /* add to high reg */
8508 rd
= (insn
>> 8) & 7;
8509 if (insn
& (1 << 11)) {
8511 tmp
= load_reg(s
, 13);
8513 /* PC. bit 1 is ignored. */
8515 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8517 val
= (insn
& 0xff) * 4;
8518 tcg_gen_addi_i32(tmp
, tmp
, val
);
8519 store_reg(s
, rd
, tmp
);
8524 op
= (insn
>> 8) & 0xf;
8527 /* adjust stack pointer */
8528 tmp
= load_reg(s
, 13);
8529 val
= (insn
& 0x7f) * 4;
8530 if (insn
& (1 << 7))
8531 val
= -(int32_t)val
;
8532 tcg_gen_addi_i32(tmp
, tmp
, val
);
8533 store_reg(s
, 13, tmp
);
8536 case 2: /* sign/zero extend. */
8539 rm
= (insn
>> 3) & 7;
8540 tmp
= load_reg(s
, rm
);
8541 switch ((insn
>> 6) & 3) {
8542 case 0: gen_sxth(tmp
); break;
8543 case 1: gen_sxtb(tmp
); break;
8544 case 2: gen_uxth(tmp
); break;
8545 case 3: gen_uxtb(tmp
); break;
8547 store_reg(s
, rd
, tmp
);
8549 case 4: case 5: case 0xc: case 0xd:
8551 addr
= load_reg(s
, 13);
8552 if (insn
& (1 << 8))
8556 for (i
= 0; i
< 8; i
++) {
8557 if (insn
& (1 << i
))
8560 if ((insn
& (1 << 11)) == 0) {
8561 tcg_gen_addi_i32(addr
, addr
, -offset
);
8563 for (i
= 0; i
< 8; i
++) {
8564 if (insn
& (1 << i
)) {
8565 if (insn
& (1 << 11)) {
8567 tmp
= gen_ld32(addr
, IS_USER(s
));
8568 store_reg(s
, i
, tmp
);
8571 tmp
= load_reg(s
, i
);
8572 gen_st32(tmp
, addr
, IS_USER(s
));
8574 /* advance to the next address. */
8575 tcg_gen_addi_i32(addr
, addr
, 4);
8579 if (insn
& (1 << 8)) {
8580 if (insn
& (1 << 11)) {
8582 tmp
= gen_ld32(addr
, IS_USER(s
));
8583 /* don't set the pc until the rest of the instruction
8587 tmp
= load_reg(s
, 14);
8588 gen_st32(tmp
, addr
, IS_USER(s
));
8590 tcg_gen_addi_i32(addr
, addr
, 4);
8592 if ((insn
& (1 << 11)) == 0) {
8593 tcg_gen_addi_i32(addr
, addr
, -offset
);
8595 /* write back the new stack pointer */
8596 store_reg(s
, 13, addr
);
8597 /* set the new PC value */
8598 if ((insn
& 0x0900) == 0x0900)
8602 case 1: case 3: case 9: case 11: /* czb */
8604 tmp
= load_reg(s
, rm
);
8605 s
->condlabel
= gen_new_label();
8607 if (insn
& (1 << 11))
8608 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8610 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8612 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8613 val
= (uint32_t)s
->pc
+ 2;
8618 case 15: /* IT, nop-hint. */
8619 if ((insn
& 0xf) == 0) {
8620 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8624 s
->condexec_cond
= (insn
>> 4) & 0xe;
8625 s
->condexec_mask
= insn
& 0x1f;
8626 /* No actual code generated for this insn, just setup state. */
8629 case 0xe: /* bkpt */
8630 gen_set_condexec(s
);
8631 gen_set_pc_im(s
->pc
- 2);
8632 gen_exception(EXCP_BKPT
);
8633 s
->is_jmp
= DISAS_JUMP
;
8638 rn
= (insn
>> 3) & 0x7;
8640 tmp
= load_reg(s
, rn
);
8641 switch ((insn
>> 6) & 3) {
8642 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8643 case 1: gen_rev16(tmp
); break;
8644 case 3: gen_revsh(tmp
); break;
8645 default: goto illegal_op
;
8647 store_reg(s
, rd
, tmp
);
8655 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8658 addr
= tcg_const_i32(16);
8659 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8660 tcg_temp_free_i32(addr
);
8664 addr
= tcg_const_i32(17);
8665 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8666 tcg_temp_free_i32(addr
);
8668 tcg_temp_free_i32(tmp
);
8671 if (insn
& (1 << 4))
8672 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8675 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8685 /* load/store multiple */
8686 rn
= (insn
>> 8) & 0x7;
8687 addr
= load_reg(s
, rn
);
8688 for (i
= 0; i
< 8; i
++) {
8689 if (insn
& (1 << i
)) {
8690 if (insn
& (1 << 11)) {
8692 tmp
= gen_ld32(addr
, IS_USER(s
));
8693 store_reg(s
, i
, tmp
);
8696 tmp
= load_reg(s
, i
);
8697 gen_st32(tmp
, addr
, IS_USER(s
));
8699 /* advance to the next address */
8700 tcg_gen_addi_i32(addr
, addr
, 4);
8703 /* Base register writeback. */
8704 if ((insn
& (1 << rn
)) == 0) {
8705 store_reg(s
, rn
, addr
);
8712 /* conditional branch or swi */
8713 cond
= (insn
>> 8) & 0xf;
8719 gen_set_condexec(s
);
8720 gen_set_pc_im(s
->pc
);
8721 s
->is_jmp
= DISAS_SWI
;
8724 /* generate a conditional jump to next instruction */
8725 s
->condlabel
= gen_new_label();
8726 gen_test_cc(cond
^ 1, s
->condlabel
);
8729 /* jump to the offset */
8730 val
= (uint32_t)s
->pc
+ 2;
8731 offset
= ((int32_t)insn
<< 24) >> 24;
8737 if (insn
& (1 << 11)) {
8738 if (disas_thumb2_insn(env
, s
, insn
))
8742 /* unconditional branch */
8743 val
= (uint32_t)s
->pc
;
8744 offset
= ((int32_t)insn
<< 21) >> 21;
8745 val
+= (offset
<< 1) + 2;
8750 if (disas_thumb2_insn(env
, s
, insn
))
8756 gen_set_condexec(s
);
8757 gen_set_pc_im(s
->pc
- 4);
8758 gen_exception(EXCP_UDEF
);
8759 s
->is_jmp
= DISAS_JUMP
;
8763 gen_set_condexec(s
);
8764 gen_set_pc_im(s
->pc
- 2);
8765 gen_exception(EXCP_UDEF
);
8766 s
->is_jmp
= DISAS_JUMP
;
8769 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8770 basic block 'tb'. If search_pc is TRUE, also generate PC
8771 information for each intermediate instruction. */
8772 static inline void gen_intermediate_code_internal(CPUState
*env
,
8773 TranslationBlock
*tb
,
8776 DisasContext dc1
, *dc
= &dc1
;
8778 uint16_t *gen_opc_end
;
8780 target_ulong pc_start
;
8781 uint32_t next_page_start
;
8785 /* generate intermediate code */
8792 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8794 dc
->is_jmp
= DISAS_NEXT
;
8796 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8798 dc
->thumb
= env
->thumb
;
8799 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8800 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8801 #if !defined(CONFIG_USER_ONLY)
8803 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8805 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8808 cpu_F0s
= tcg_temp_new_i32();
8809 cpu_F1s
= tcg_temp_new_i32();
8810 cpu_F0d
= tcg_temp_new_i64();
8811 cpu_F1d
= tcg_temp_new_i64();
8814 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8815 cpu_M0
= tcg_temp_new_i64();
8816 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8819 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8821 max_insns
= CF_COUNT_MASK
;
8824 /* Reset the conditional execution bits immediately. This avoids
8825 complications trying to do it at the end of the block. */
8826 if (env
->condexec_bits
)
8828 TCGv tmp
= new_tmp();
8829 tcg_gen_movi_i32(tmp
, 0);
8830 store_cpu_field(tmp
, condexec_bits
);
8833 #ifdef CONFIG_USER_ONLY
8834 /* Intercept jump to the magic kernel page. */
8835 if (dc
->pc
>= 0xffff0000) {
8836 /* We always get here via a jump, so know we are not in a
8837 conditional execution block. */
8838 gen_exception(EXCP_KERNEL_TRAP
);
8839 dc
->is_jmp
= DISAS_UPDATE
;
8843 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8844 /* We always get here via a jump, so know we are not in a
8845 conditional execution block. */
8846 gen_exception(EXCP_EXCEPTION_EXIT
);
8847 dc
->is_jmp
= DISAS_UPDATE
;
8852 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8853 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8854 if (bp
->pc
== dc
->pc
) {
8855 gen_set_condexec(dc
);
8856 gen_set_pc_im(dc
->pc
);
8857 gen_exception(EXCP_DEBUG
);
8858 dc
->is_jmp
= DISAS_JUMP
;
8859 /* Advance PC so that clearing the breakpoint will
8860 invalidate this TB. */
8862 goto done_generating
;
8868 j
= gen_opc_ptr
- gen_opc_buf
;
8872 gen_opc_instr_start
[lj
++] = 0;
8874 gen_opc_pc
[lj
] = dc
->pc
;
8875 gen_opc_instr_start
[lj
] = 1;
8876 gen_opc_icount
[lj
] = num_insns
;
8879 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8883 disas_thumb_insn(env
, dc
);
8884 if (dc
->condexec_mask
) {
8885 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8886 | ((dc
->condexec_mask
>> 4) & 1);
8887 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8888 if (dc
->condexec_mask
== 0) {
8889 dc
->condexec_cond
= 0;
8893 disas_arm_insn(env
, dc
);
8896 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8900 if (dc
->condjmp
&& !dc
->is_jmp
) {
8901 gen_set_label(dc
->condlabel
);
8904 /* Translation stops when a conditional branch is encountered.
8905 * Otherwise the subsequent code could get translated several times.
8906 * Also stop translation when a page boundary is reached. This
8907 * ensures prefetch aborts occur at the right place. */
8909 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8910 !env
->singlestep_enabled
&&
8912 dc
->pc
< next_page_start
&&
8913 num_insns
< max_insns
);
8915 if (tb
->cflags
& CF_LAST_IO
) {
8917 /* FIXME: This can theoretically happen with self-modifying
8919 cpu_abort(env
, "IO on conditional branch instruction");
8924 /* At this stage dc->condjmp will only be set when the skipped
8925 instruction was a conditional branch or trap, and the PC has
8926 already been written. */
8927 if (unlikely(env
->singlestep_enabled
)) {
8928 /* Make sure the pc is updated, and raise a debug exception. */
8930 gen_set_condexec(dc
);
8931 if (dc
->is_jmp
== DISAS_SWI
) {
8932 gen_exception(EXCP_SWI
);
8934 gen_exception(EXCP_DEBUG
);
8936 gen_set_label(dc
->condlabel
);
8938 if (dc
->condjmp
|| !dc
->is_jmp
) {
8939 gen_set_pc_im(dc
->pc
);
8942 gen_set_condexec(dc
);
8943 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8944 gen_exception(EXCP_SWI
);
8946 /* FIXME: Single stepping a WFI insn will not halt
8948 gen_exception(EXCP_DEBUG
);
8951 /* While branches must always occur at the end of an IT block,
8952 there are a few other things that can cause us to terminate
8953 the TB in the middel of an IT block:
8954 - Exception generating instructions (bkpt, swi, undefined).
8956 - Hardware watchpoints.
8957 Hardware breakpoints have already been handled and skip this code.
8959 gen_set_condexec(dc
);
8960 switch(dc
->is_jmp
) {
8962 gen_goto_tb(dc
, 1, dc
->pc
);
8967 /* indicate that the hash table must be used to find the next TB */
8971 /* nothing more to generate */
8977 gen_exception(EXCP_SWI
);
8981 gen_set_label(dc
->condlabel
);
8982 gen_set_condexec(dc
);
8983 gen_goto_tb(dc
, 1, dc
->pc
);
8989 gen_icount_end(tb
, num_insns
);
8990 *gen_opc_ptr
= INDEX_op_end
;
8993 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8994 qemu_log("----------------\n");
8995 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8996 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9001 j
= gen_opc_ptr
- gen_opc_buf
;
9004 gen_opc_instr_start
[lj
++] = 0;
9006 tb
->size
= dc
->pc
- pc_start
;
9007 tb
->icount
= num_insns
;
9011 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9013 gen_intermediate_code_internal(env
, tb
, 0);
9016 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9018 gen_intermediate_code_internal(env
, tb
, 1);
9021 static const char *cpu_mode_names
[16] = {
9022 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9023 "???", "???", "???", "und", "???", "???", "???", "sys"
9026 void cpu_dump_state(CPUState
*env
, FILE *f
,
9027 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9037 /* ??? This assumes float64 and double have the same layout.
9038 Oh well, it's only debug dumps. */
9047 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9049 cpu_fprintf(f
, "\n");
9051 cpu_fprintf(f
, " ");
9053 psr
= cpsr_read(env
);
9054 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9056 psr
& (1 << 31) ? 'N' : '-',
9057 psr
& (1 << 30) ? 'Z' : '-',
9058 psr
& (1 << 29) ? 'C' : '-',
9059 psr
& (1 << 28) ? 'V' : '-',
9060 psr
& CPSR_T
? 'T' : 'A',
9061 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9064 for (i
= 0; i
< 16; i
++) {
9065 d
.d
= env
->vfp
.regs
[i
];
9069 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9070 i
* 2, (int)s0
.i
, s0
.s
,
9071 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9072 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9075 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9079 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9080 unsigned long searched_pc
, int pc_pos
, void *puc
)
9082 env
->regs
[15] = gen_opc_pc
[pc_pos
];