]>
git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s
, cpu_F1s
;
82 static TCGv_i64 cpu_F0d
, cpu_F1d
;
84 #include "gen-icount.h"
86 static const char *regnames
[] =
87 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
88 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
90 /* initialize TCG globals. */
91 void arm_translate_init(void)
95 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
97 for (i
= 0; i
< 16; i
++) {
98 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
99 offsetof(CPUState
, regs
[i
]),
107 static int num_temps
;
109 /* Allocate a temporary variable. */
110 static TCGv_i32
new_tmp(void)
113 return tcg_temp_new_i32();
116 /* Release a temporary variable. */
117 static void dead_tmp(TCGv tmp
)
123 static inline TCGv
load_cpu_offset(int offset
)
125 TCGv tmp
= new_tmp();
126 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
130 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
132 static inline void store_cpu_offset(TCGv var
, int offset
)
134 tcg_gen_st_i32(var
, cpu_env
, offset
);
138 #define store_cpu_field(var, name) \
139 store_cpu_offset(var, offsetof(CPUState, name))
141 /* Set a variable to the value of a CPU register. */
142 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
146 /* normaly, since we updated PC, we need only to add one insn */
148 addr
= (long)s
->pc
+ 2;
150 addr
= (long)s
->pc
+ 4;
151 tcg_gen_movi_i32(var
, addr
);
153 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
157 /* Create a new temporary and set it to the value of a CPU register. */
158 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
160 TCGv tmp
= new_tmp();
161 load_reg_var(s
, tmp
, reg
);
165 /* Set a CPU register. The source must be a temporary and will be
167 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
170 tcg_gen_andi_i32(var
, var
, ~1);
171 s
->is_jmp
= DISAS_JUMP
;
173 tcg_gen_mov_i32(cpu_R
[reg
], var
);
177 /* Value extensions. */
178 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
179 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
180 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
181 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
183 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
184 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
187 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
189 TCGv tmp_mask
= tcg_const_i32(mask
);
190 gen_helper_cpsr_write(var
, tmp_mask
);
191 tcg_temp_free_i32(tmp_mask
);
193 /* Set NZCV flags from the high 4 bits of var. */
194 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
196 static void gen_exception(int excp
)
198 TCGv tmp
= new_tmp();
199 tcg_gen_movi_i32(tmp
, excp
);
200 gen_helper_exception(tmp
);
204 static void gen_smul_dual(TCGv a
, TCGv b
)
206 TCGv tmp1
= new_tmp();
207 TCGv tmp2
= new_tmp();
208 tcg_gen_ext16s_i32(tmp1
, a
);
209 tcg_gen_ext16s_i32(tmp2
, b
);
210 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
212 tcg_gen_sari_i32(a
, a
, 16);
213 tcg_gen_sari_i32(b
, b
, 16);
214 tcg_gen_mul_i32(b
, b
, a
);
215 tcg_gen_mov_i32(a
, tmp1
);
219 /* Byteswap each halfword. */
220 static void gen_rev16(TCGv var
)
222 TCGv tmp
= new_tmp();
223 tcg_gen_shri_i32(tmp
, var
, 8);
224 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
225 tcg_gen_shli_i32(var
, var
, 8);
226 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
227 tcg_gen_or_i32(var
, var
, tmp
);
231 /* Byteswap low halfword and sign extend. */
232 static void gen_revsh(TCGv var
)
234 TCGv tmp
= new_tmp();
235 tcg_gen_shri_i32(tmp
, var
, 8);
236 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
237 tcg_gen_shli_i32(var
, var
, 8);
238 tcg_gen_ext8s_i32(var
, var
);
239 tcg_gen_or_i32(var
, var
, tmp
);
243 /* Unsigned bitfield extract. */
244 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
247 tcg_gen_shri_i32(var
, var
, shift
);
248 tcg_gen_andi_i32(var
, var
, mask
);
251 /* Signed bitfield extract. */
252 static void gen_sbfx(TCGv var
, int shift
, int width
)
257 tcg_gen_sari_i32(var
, var
, shift
);
258 if (shift
+ width
< 32) {
259 signbit
= 1u << (width
- 1);
260 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
261 tcg_gen_xori_i32(var
, var
, signbit
);
262 tcg_gen_subi_i32(var
, var
, signbit
);
266 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
267 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
269 tcg_gen_andi_i32(val
, val
, mask
);
270 tcg_gen_shli_i32(val
, val
, shift
);
271 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
272 tcg_gen_or_i32(dest
, base
, val
);
275 /* Round the top 32 bits of a 64-bit value. */
276 static void gen_roundqd(TCGv a
, TCGv b
)
278 tcg_gen_shri_i32(a
, a
, 31);
279 tcg_gen_add_i32(a
, a
, b
);
282 /* FIXME: Most targets have native widening multiplication.
283 It would be good to use that instead of a full wide multiply. */
284 /* 32x32->64 multiply. Marks inputs as dead. */
285 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
287 TCGv_i64 tmp1
= tcg_temp_new_i64();
288 TCGv_i64 tmp2
= tcg_temp_new_i64();
290 tcg_gen_extu_i32_i64(tmp1
, a
);
292 tcg_gen_extu_i32_i64(tmp2
, b
);
294 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
295 tcg_temp_free_i64(tmp2
);
299 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
301 TCGv_i64 tmp1
= tcg_temp_new_i64();
302 TCGv_i64 tmp2
= tcg_temp_new_i64();
304 tcg_gen_ext_i32_i64(tmp1
, a
);
306 tcg_gen_ext_i32_i64(tmp2
, b
);
308 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
309 tcg_temp_free_i64(tmp2
);
313 /* Signed 32x32->64 multiply. */
314 static void gen_imull(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1
, a
);
320 tcg_gen_ext_i32_i64(tmp2
, b
);
321 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
322 tcg_temp_free_i64(tmp2
);
323 tcg_gen_trunc_i64_i32(a
, tmp1
);
324 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
325 tcg_gen_trunc_i64_i32(b
, tmp1
);
326 tcg_temp_free_i64(tmp1
);
329 /* Swap low and high halfwords. */
330 static void gen_swap_half(TCGv var
)
332 TCGv tmp
= new_tmp();
333 tcg_gen_shri_i32(tmp
, var
, 16);
334 tcg_gen_shli_i32(var
, var
, 16);
335 tcg_gen_or_i32(var
, var
, tmp
);
339 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
340 tmp = (t0 ^ t1) & 0x8000;
343 t0 = (t0 + t1) ^ tmp;
346 static void gen_add16(TCGv t0
, TCGv t1
)
348 TCGv tmp
= new_tmp();
349 tcg_gen_xor_i32(tmp
, t0
, t1
);
350 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
351 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
352 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
353 tcg_gen_add_i32(t0
, t0
, t1
);
354 tcg_gen_xor_i32(t0
, t0
, tmp
);
359 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
361 /* Set CF to the top bit of var. */
362 static void gen_set_CF_bit31(TCGv var
)
364 TCGv tmp
= new_tmp();
365 tcg_gen_shri_i32(tmp
, var
, 31);
370 /* Set N and Z flags from var. */
371 static inline void gen_logic_CC(TCGv var
)
373 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
374 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
378 static void gen_adc(TCGv t0
, TCGv t1
)
381 tcg_gen_add_i32(t0
, t0
, t1
);
382 tmp
= load_cpu_field(CF
);
383 tcg_gen_add_i32(t0
, t0
, tmp
);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
391 tcg_gen_add_i32(dest
, t0
, t1
);
392 tmp
= load_cpu_field(CF
);
393 tcg_gen_add_i32(dest
, dest
, tmp
);
397 /* dest = T0 - T1 + CF - 1. */
398 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
401 tcg_gen_sub_i32(dest
, t0
, t1
);
402 tmp
= load_cpu_field(CF
);
403 tcg_gen_add_i32(dest
, dest
, tmp
);
404 tcg_gen_subi_i32(dest
, dest
, 1);
408 /* 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
);
4683 neon_store_reg(rd
, pass
, tmp
);
4686 tcg_temp_free_i64(tmp64
);
4690 } else if (op
== 10) {
4694 tmp
= neon_load_reg(rm
, 0);
4695 tmp2
= neon_load_reg(rm
, 1);
4696 for (pass
= 0; pass
< 2; pass
++) {
4700 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4703 /* The shift is less than the width of the source
4704 type, so we can just shift the whole register. */
4705 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4706 if (size
< 2 || !u
) {
4709 imm
= (0xffu
>> (8 - shift
));
4712 imm
= 0xffff >> (16 - shift
);
4714 imm64
= imm
| (((uint64_t)imm
) << 32);
4715 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4718 neon_store_reg64(cpu_V0
, rd
+ pass
);
4720 } else if (op
== 15 || op
== 16) {
4721 /* VCVT fixed-point. */
4722 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4723 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4726 gen_vfp_ulto(0, shift
);
4728 gen_vfp_slto(0, shift
);
4731 gen_vfp_toul(0, shift
);
4733 gen_vfp_tosl(0, shift
);
4735 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4740 } else { /* (insn & 0x00380080) == 0 */
4743 op
= (insn
>> 8) & 0xf;
4744 /* One register and immediate. */
4745 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4746 invert
= (insn
& (1 << 5)) != 0;
4764 imm
= (imm
<< 8) | (imm
<< 24);
4767 imm
= (imm
< 8) | 0xff;
4770 imm
= (imm
<< 16) | 0xffff;
4773 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4778 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4779 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4785 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4786 if (op
& 1 && op
< 12) {
4787 tmp
= neon_load_reg(rd
, pass
);
4789 /* The immediate value has already been inverted, so
4791 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4793 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4798 if (op
== 14 && invert
) {
4801 for (n
= 0; n
< 4; n
++) {
4802 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4803 val
|= 0xff << (n
* 8);
4805 tcg_gen_movi_i32(tmp
, val
);
4807 tcg_gen_movi_i32(tmp
, imm
);
4810 neon_store_reg(rd
, pass
, tmp
);
4813 } else { /* (insn & 0x00800010 == 0x00800000) */
4815 op
= (insn
>> 8) & 0xf;
4816 if ((insn
& (1 << 6)) == 0) {
4817 /* Three registers of different lengths. */
4821 /* prewiden, src1_wide, src2_wide */
4822 static const int neon_3reg_wide
[16][3] = {
4823 {1, 0, 0}, /* VADDL */
4824 {1, 1, 0}, /* VADDW */
4825 {1, 0, 0}, /* VSUBL */
4826 {1, 1, 0}, /* VSUBW */
4827 {0, 1, 1}, /* VADDHN */
4828 {0, 0, 0}, /* VABAL */
4829 {0, 1, 1}, /* VSUBHN */
4830 {0, 0, 0}, /* VABDL */
4831 {0, 0, 0}, /* VMLAL */
4832 {0, 0, 0}, /* VQDMLAL */
4833 {0, 0, 0}, /* VMLSL */
4834 {0, 0, 0}, /* VQDMLSL */
4835 {0, 0, 0}, /* Integer VMULL */
4836 {0, 0, 0}, /* VQDMULL */
4837 {0, 0, 0} /* Polynomial VMULL */
4840 prewiden
= neon_3reg_wide
[op
][0];
4841 src1_wide
= neon_3reg_wide
[op
][1];
4842 src2_wide
= neon_3reg_wide
[op
][2];
4844 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4847 /* Avoid overlapping operands. Wide source operands are
4848 always aligned so will never overlap with wide
4849 destinations in problematic ways. */
4850 if (rd
== rm
&& !src2_wide
) {
4851 tmp
= neon_load_reg(rm
, 1);
4852 neon_store_scratch(2, tmp
);
4853 } else if (rd
== rn
&& !src1_wide
) {
4854 tmp
= neon_load_reg(rn
, 1);
4855 neon_store_scratch(2, tmp
);
4858 for (pass
= 0; pass
< 2; pass
++) {
4860 neon_load_reg64(cpu_V0
, rn
+ pass
);
4863 if (pass
== 1 && rd
== rn
) {
4864 tmp
= neon_load_scratch(2);
4866 tmp
= neon_load_reg(rn
, pass
);
4869 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4873 neon_load_reg64(cpu_V1
, rm
+ pass
);
4876 if (pass
== 1 && rd
== rm
) {
4877 tmp2
= neon_load_scratch(2);
4879 tmp2
= neon_load_reg(rm
, pass
);
4882 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4886 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4887 gen_neon_addl(size
);
4889 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4890 gen_neon_subl(size
);
4892 case 5: case 7: /* VABAL, VABDL */
4893 switch ((size
<< 1) | u
) {
4895 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4898 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4901 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4904 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4907 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4910 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4917 case 8: case 9: case 10: case 11: case 12: case 13:
4918 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4919 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4923 case 14: /* Polynomial VMULL */
4924 cpu_abort(env
, "Polynomial VMULL not implemented");
4926 default: /* 15 is RESERVED. */
4929 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4931 if (op
== 10 || op
== 11) {
4932 gen_neon_negl(cpu_V0
, size
);
4936 neon_load_reg64(cpu_V1
, rd
+ pass
);
4940 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4941 gen_neon_addl(size
);
4943 case 9: case 11: /* VQDMLAL, VQDMLSL */
4944 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4945 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4948 case 13: /* VQDMULL */
4949 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4954 neon_store_reg64(cpu_V0
, rd
+ pass
);
4955 } else if (op
== 4 || op
== 6) {
4956 /* Narrowing operation. */
4961 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4964 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4967 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4968 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4975 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4978 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4981 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4982 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4983 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4991 neon_store_reg(rd
, 0, tmp3
);
4992 neon_store_reg(rd
, 1, tmp
);
4995 /* Write back the result. */
4996 neon_store_reg64(cpu_V0
, rd
+ pass
);
5000 /* Two registers and a scalar. */
5002 case 0: /* Integer VMLA scalar */
5003 case 1: /* Float VMLA scalar */
5004 case 4: /* Integer VMLS scalar */
5005 case 5: /* Floating point VMLS scalar */
5006 case 8: /* Integer VMUL scalar */
5007 case 9: /* Floating point VMUL scalar */
5008 case 12: /* VQDMULH scalar */
5009 case 13: /* VQRDMULH scalar */
5010 tmp
= neon_get_scalar(size
, rm
);
5011 neon_store_scratch(0, tmp
);
5012 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5013 tmp
= neon_load_scratch(0);
5014 tmp2
= neon_load_reg(rn
, pass
);
5017 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5019 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5021 } else if (op
== 13) {
5023 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5025 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5027 } else if (op
& 1) {
5028 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5031 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5032 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5033 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5040 tmp2
= neon_load_reg(rd
, pass
);
5043 gen_neon_add(size
, tmp
, tmp2
);
5046 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5049 gen_neon_rsb(size
, tmp
, tmp2
);
5052 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5059 neon_store_reg(rd
, pass
, tmp
);
5062 case 2: /* VMLAL sclar */
5063 case 3: /* VQDMLAL scalar */
5064 case 6: /* VMLSL scalar */
5065 case 7: /* VQDMLSL scalar */
5066 case 10: /* VMULL scalar */
5067 case 11: /* VQDMULL scalar */
5068 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5071 tmp2
= neon_get_scalar(size
, rm
);
5072 tmp3
= neon_load_reg(rn
, 1);
5074 for (pass
= 0; pass
< 2; pass
++) {
5076 tmp
= neon_load_reg(rn
, 0);
5080 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5082 if (op
== 6 || op
== 7) {
5083 gen_neon_negl(cpu_V0
, size
);
5086 neon_load_reg64(cpu_V1
, rd
+ pass
);
5090 gen_neon_addl(size
);
5093 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5094 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5100 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5105 neon_store_reg64(cpu_V0
, rd
+ pass
);
5111 default: /* 14 and 15 are RESERVED */
5115 } else { /* size == 3 */
5118 imm
= (insn
>> 8) & 0xf;
5125 neon_load_reg64(cpu_V0
, rn
);
5127 neon_load_reg64(cpu_V1
, rn
+ 1);
5129 } else if (imm
== 8) {
5130 neon_load_reg64(cpu_V0
, rn
+ 1);
5132 neon_load_reg64(cpu_V1
, rm
);
5135 tmp64
= tcg_temp_new_i64();
5137 neon_load_reg64(cpu_V0
, rn
);
5138 neon_load_reg64(tmp64
, rn
+ 1);
5140 neon_load_reg64(cpu_V0
, rn
+ 1);
5141 neon_load_reg64(tmp64
, rm
);
5143 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5144 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5145 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5147 neon_load_reg64(cpu_V1
, rm
);
5149 neon_load_reg64(cpu_V1
, rm
+ 1);
5152 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5153 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5154 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5155 tcg_temp_free_i64(tmp64
);
5158 neon_load_reg64(cpu_V0
, rn
);
5159 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5160 neon_load_reg64(cpu_V1
, rm
);
5161 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5162 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5164 neon_store_reg64(cpu_V0
, rd
);
5166 neon_store_reg64(cpu_V1
, rd
+ 1);
5168 } else if ((insn
& (1 << 11)) == 0) {
5169 /* Two register misc. */
5170 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5171 size
= (insn
>> 18) & 3;
5173 case 0: /* VREV64 */
5176 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5177 tmp
= neon_load_reg(rm
, pass
* 2);
5178 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5180 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5181 case 1: gen_swap_half(tmp
); break;
5182 case 2: /* no-op */ break;
5185 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5187 neon_store_reg(rd
, pass
* 2, tmp2
);
5190 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5191 case 1: gen_swap_half(tmp2
); break;
5194 neon_store_reg(rd
, pass
* 2, tmp2
);
5198 case 4: case 5: /* VPADDL */
5199 case 12: case 13: /* VPADAL */
5202 for (pass
= 0; pass
< q
+ 1; pass
++) {
5203 tmp
= neon_load_reg(rm
, pass
* 2);
5204 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5205 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5206 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5208 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5209 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5210 case 2: tcg_gen_add_i64(CPU_V001
); break;
5215 neon_load_reg64(cpu_V1
, rd
+ pass
);
5216 gen_neon_addl(size
);
5218 neon_store_reg64(cpu_V0
, rd
+ pass
);
5223 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5224 tmp
= neon_load_reg(rm
, n
);
5225 tmp2
= neon_load_reg(rd
, n
+ 1);
5226 neon_store_reg(rm
, n
, tmp2
);
5227 neon_store_reg(rd
, n
+ 1, tmp
);
5235 Rd A3 A2 A1 A0 B2 B0 A2 A0
5236 Rm B3 B2 B1 B0 B3 B1 A3 A1
5240 gen_neon_unzip(rd
, q
, 0, size
);
5241 gen_neon_unzip(rm
, q
, 4, size
);
5243 static int unzip_order_q
[8] =
5244 {0, 2, 4, 6, 1, 3, 5, 7};
5245 for (n
= 0; n
< 8; n
++) {
5246 int reg
= (n
< 4) ? rd
: rm
;
5247 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5248 neon_store_reg(reg
, n
% 4, tmp
);
5251 static int unzip_order
[4] =
5253 for (n
= 0; n
< 4; n
++) {
5254 int reg
= (n
< 2) ? rd
: rm
;
5255 tmp
= neon_load_scratch(unzip_order
[n
]);
5256 neon_store_reg(reg
, n
% 2, tmp
);
5262 Rd A3 A2 A1 A0 B1 A1 B0 A0
5263 Rm B3 B2 B1 B0 B3 A3 B2 A2
5267 count
= (q
? 4 : 2);
5268 for (n
= 0; n
< count
; n
++) {
5269 tmp
= neon_load_reg(rd
, n
);
5270 tmp2
= neon_load_reg(rd
, n
);
5272 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5273 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5274 case 2: /* no-op */; break;
5277 neon_store_scratch(n
* 2, tmp
);
5278 neon_store_scratch(n
* 2 + 1, tmp2
);
5280 for (n
= 0; n
< count
* 2; n
++) {
5281 int reg
= (n
< count
) ? rd
: rm
;
5282 tmp
= neon_load_scratch(n
);
5283 neon_store_reg(reg
, n
% count
, tmp
);
5286 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5290 for (pass
= 0; pass
< 2; pass
++) {
5291 neon_load_reg64(cpu_V0
, rm
+ pass
);
5293 if (op
== 36 && q
== 0) {
5294 gen_neon_narrow(size
, tmp
, cpu_V0
);
5296 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5298 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5303 neon_store_reg(rd
, 0, tmp2
);
5304 neon_store_reg(rd
, 1, tmp
);
5308 case 38: /* VSHLL */
5311 tmp
= neon_load_reg(rm
, 0);
5312 tmp2
= neon_load_reg(rm
, 1);
5313 for (pass
= 0; pass
< 2; pass
++) {
5316 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5317 neon_store_reg64(cpu_V0
, rd
+ pass
);
5322 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5323 if (op
== 30 || op
== 31 || op
>= 58) {
5324 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5325 neon_reg_offset(rm
, pass
));
5328 tmp
= neon_load_reg(rm
, pass
);
5331 case 1: /* VREV32 */
5333 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5334 case 1: gen_swap_half(tmp
); break;
5338 case 2: /* VREV16 */
5345 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5346 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5347 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5353 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5354 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5355 case 2: gen_helper_clz(tmp
, tmp
); break;
5362 gen_helper_neon_cnt_u8(tmp
, tmp
);
5367 tcg_gen_not_i32(tmp
, tmp
);
5369 case 14: /* VQABS */
5371 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5372 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5373 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5377 case 15: /* VQNEG */
5379 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5380 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5381 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5385 case 16: case 19: /* VCGT #0, VCLE #0 */
5386 tmp2
= tcg_const_i32(0);
5388 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5389 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5390 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5393 tcg_temp_free(tmp2
);
5395 tcg_gen_not_i32(tmp
, tmp
);
5397 case 17: case 20: /* VCGE #0, VCLT #0 */
5398 tmp2
= tcg_const_i32(0);
5400 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5401 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5402 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5405 tcg_temp_free(tmp2
);
5407 tcg_gen_not_i32(tmp
, tmp
);
5409 case 18: /* VCEQ #0 */
5410 tmp2
= tcg_const_i32(0);
5412 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5413 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5414 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5417 tcg_temp_free(tmp2
);
5421 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5422 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5423 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5430 tmp2
= tcg_const_i32(0);
5431 gen_neon_rsb(size
, tmp
, tmp2
);
5432 tcg_temp_free(tmp2
);
5434 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5435 tmp2
= tcg_const_i32(0);
5436 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5437 tcg_temp_free(tmp2
);
5439 tcg_gen_not_i32(tmp
, tmp
);
5441 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5442 tmp2
= tcg_const_i32(0);
5443 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5444 tcg_temp_free(tmp2
);
5446 tcg_gen_not_i32(tmp
, tmp
);
5448 case 26: /* Float VCEQ #0 */
5449 tmp2
= tcg_const_i32(0);
5450 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5451 tcg_temp_free(tmp2
);
5453 case 30: /* Float VABS */
5456 case 31: /* Float VNEG */
5460 tmp2
= neon_load_reg(rd
, pass
);
5461 neon_store_reg(rm
, pass
, tmp2
);
5464 tmp2
= neon_load_reg(rd
, pass
);
5466 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5467 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5471 neon_store_reg(rm
, pass
, tmp2
);
5473 case 56: /* Integer VRECPE */
5474 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5476 case 57: /* Integer VRSQRTE */
5477 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5479 case 58: /* Float VRECPE */
5480 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5482 case 59: /* Float VRSQRTE */
5483 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5485 case 60: /* VCVT.F32.S32 */
5488 case 61: /* VCVT.F32.U32 */
5491 case 62: /* VCVT.S32.F32 */
5494 case 63: /* VCVT.U32.F32 */
5498 /* Reserved: 21, 29, 39-56 */
5501 if (op
== 30 || op
== 31 || op
>= 58) {
5502 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5503 neon_reg_offset(rd
, pass
));
5505 neon_store_reg(rd
, pass
, tmp
);
5510 } else if ((insn
& (1 << 10)) == 0) {
5512 n
= ((insn
>> 5) & 0x18) + 8;
5513 if (insn
& (1 << 6)) {
5514 tmp
= neon_load_reg(rd
, 0);
5517 tcg_gen_movi_i32(tmp
, 0);
5519 tmp2
= neon_load_reg(rm
, 0);
5520 tmp4
= tcg_const_i32(rn
);
5521 tmp5
= tcg_const_i32(n
);
5522 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5524 if (insn
& (1 << 6)) {
5525 tmp
= neon_load_reg(rd
, 1);
5528 tcg_gen_movi_i32(tmp
, 0);
5530 tmp3
= neon_load_reg(rm
, 1);
5531 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5532 tcg_temp_free_i32(tmp5
);
5533 tcg_temp_free_i32(tmp4
);
5534 neon_store_reg(rd
, 0, tmp2
);
5535 neon_store_reg(rd
, 1, tmp3
);
5537 } else if ((insn
& 0x380) == 0) {
5539 if (insn
& (1 << 19)) {
5540 tmp
= neon_load_reg(rm
, 1);
5542 tmp
= neon_load_reg(rm
, 0);
5544 if (insn
& (1 << 16)) {
5545 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5546 } else if (insn
& (1 << 17)) {
5547 if ((insn
>> 18) & 1)
5548 gen_neon_dup_high16(tmp
);
5550 gen_neon_dup_low16(tmp
);
5552 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5554 tcg_gen_mov_i32(tmp2
, tmp
);
5555 neon_store_reg(rd
, pass
, tmp2
);
5566 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5568 int crn
= (insn
>> 16) & 0xf;
5569 int crm
= insn
& 0xf;
5570 int op1
= (insn
>> 21) & 7;
5571 int op2
= (insn
>> 5) & 7;
5572 int rt
= (insn
>> 12) & 0xf;
5575 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5576 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5580 tmp
= load_cpu_field(teecr
);
5581 store_reg(s
, rt
, tmp
);
5584 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5586 if (IS_USER(s
) && (env
->teecr
& 1))
5588 tmp
= load_cpu_field(teehbr
);
5589 store_reg(s
, rt
, tmp
);
5593 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5594 op1
, crn
, crm
, op2
);
5598 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5600 int crn
= (insn
>> 16) & 0xf;
5601 int crm
= insn
& 0xf;
5602 int op1
= (insn
>> 21) & 7;
5603 int op2
= (insn
>> 5) & 7;
5604 int rt
= (insn
>> 12) & 0xf;
5607 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5608 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5612 tmp
= load_reg(s
, rt
);
5613 gen_helper_set_teecr(cpu_env
, tmp
);
5617 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5619 if (IS_USER(s
) && (env
->teecr
& 1))
5621 tmp
= load_reg(s
, rt
);
5622 store_cpu_field(tmp
, teehbr
);
5626 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5627 op1
, crn
, crm
, op2
);
5631 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5635 cpnum
= (insn
>> 8) & 0xf;
5636 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5637 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5643 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5644 return disas_iwmmxt_insn(env
, s
, insn
);
5645 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5646 return disas_dsp_insn(env
, s
, insn
);
5651 return disas_vfp_insn (env
, s
, insn
);
5653 /* Coprocessors 7-15 are architecturally reserved by ARM.
5654 Unfortunately Intel decided to ignore this. */
5655 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5657 if (insn
& (1 << 20))
5658 return disas_cp14_read(env
, s
, insn
);
5660 return disas_cp14_write(env
, s
, insn
);
5662 return disas_cp15_insn (env
, s
, insn
);
5665 /* Unknown coprocessor. See if the board has hooked it. */
5666 return disas_cp_insn (env
, s
, insn
);
5671 /* Store a 64-bit value to a register pair. Clobbers val. */
5672 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5676 tcg_gen_trunc_i64_i32(tmp
, val
);
5677 store_reg(s
, rlow
, tmp
);
5679 tcg_gen_shri_i64(val
, val
, 32);
5680 tcg_gen_trunc_i64_i32(tmp
, val
);
5681 store_reg(s
, rhigh
, tmp
);
5684 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5685 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5690 /* Load value and extend to 64 bits. */
5691 tmp
= tcg_temp_new_i64();
5692 tmp2
= load_reg(s
, rlow
);
5693 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5695 tcg_gen_add_i64(val
, val
, tmp
);
5696 tcg_temp_free_i64(tmp
);
5699 /* load and add a 64-bit value from a register pair. */
5700 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5706 /* Load 64-bit value rd:rn. */
5707 tmpl
= load_reg(s
, rlow
);
5708 tmph
= load_reg(s
, rhigh
);
5709 tmp
= tcg_temp_new_i64();
5710 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5713 tcg_gen_add_i64(val
, val
, tmp
);
5714 tcg_temp_free_i64(tmp
);
5717 /* Set N and Z flags from a 64-bit value. */
5718 static void gen_logicq_cc(TCGv_i64 val
)
5720 TCGv tmp
= new_tmp();
5721 gen_helper_logicq_cc(tmp
, val
);
5726 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5728 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5735 insn
= ldl_code(s
->pc
);
5738 /* M variants do not implement ARM mode. */
5743 /* Unconditional instructions. */
5744 if (((insn
>> 25) & 7) == 1) {
5745 /* NEON Data processing. */
5746 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5749 if (disas_neon_data_insn(env
, s
, insn
))
5753 if ((insn
& 0x0f100000) == 0x04000000) {
5754 /* NEON load/store. */
5755 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5758 if (disas_neon_ls_insn(env
, s
, insn
))
5762 if ((insn
& 0x0d70f000) == 0x0550f000)
5764 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5767 if (insn
& (1 << 9)) {
5768 /* BE8 mode not implemented. */
5772 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5773 switch ((insn
>> 4) & 0xf) {
5776 gen_helper_clrex(cpu_env
);
5782 /* We don't emulate caches so these are a no-op. */
5787 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5793 op1
= (insn
& 0x1f);
5794 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5795 addr
= load_reg(s
, 13);
5798 tmp
= tcg_const_i32(op1
);
5799 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
5800 tcg_temp_free_i32(tmp
);
5802 i
= (insn
>> 23) & 3;
5804 case 0: offset
= -4; break; /* DA */
5805 case 1: offset
= 0; break; /* IA */
5806 case 2: offset
= -8; break; /* DB */
5807 case 3: offset
= 4; break; /* IB */
5811 tcg_gen_addi_i32(addr
, addr
, offset
);
5812 tmp
= load_reg(s
, 14);
5813 gen_st32(tmp
, addr
, 0);
5814 tmp
= load_cpu_field(spsr
);
5815 tcg_gen_addi_i32(addr
, addr
, 4);
5816 gen_st32(tmp
, addr
, 0);
5817 if (insn
& (1 << 21)) {
5818 /* Base writeback. */
5820 case 0: offset
= -8; break;
5821 case 1: offset
= 4; break;
5822 case 2: offset
= -4; break;
5823 case 3: offset
= 0; break;
5827 tcg_gen_addi_i32(addr
, addr
, offset
);
5828 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5829 store_reg(s
, 13, addr
);
5831 tmp
= tcg_const_i32(op1
);
5832 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
5833 tcg_temp_free_i32(tmp
);
5839 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5845 rn
= (insn
>> 16) & 0xf;
5846 addr
= load_reg(s
, rn
);
5847 i
= (insn
>> 23) & 3;
5849 case 0: offset
= -4; break; /* DA */
5850 case 1: offset
= 0; break; /* IA */
5851 case 2: offset
= -8; break; /* DB */
5852 case 3: offset
= 4; break; /* IB */
5856 tcg_gen_addi_i32(addr
, addr
, offset
);
5857 /* Load PC into tmp and CPSR into tmp2. */
5858 tmp
= gen_ld32(addr
, 0);
5859 tcg_gen_addi_i32(addr
, addr
, 4);
5860 tmp2
= gen_ld32(addr
, 0);
5861 if (insn
& (1 << 21)) {
5862 /* Base writeback. */
5864 case 0: offset
= -8; break;
5865 case 1: offset
= 4; break;
5866 case 2: offset
= -4; break;
5867 case 3: offset
= 0; break;
5871 tcg_gen_addi_i32(addr
, addr
, offset
);
5872 store_reg(s
, rn
, addr
);
5876 gen_rfe(s
, tmp
, tmp2
);
5878 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5879 /* branch link and change to thumb (blx <offset>) */
5882 val
= (uint32_t)s
->pc
;
5884 tcg_gen_movi_i32(tmp
, val
);
5885 store_reg(s
, 14, tmp
);
5886 /* Sign-extend the 24-bit offset */
5887 offset
= (((int32_t)insn
) << 8) >> 8;
5888 /* offset * 4 + bit24 * 2 + (thumb bit) */
5889 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5890 /* pipeline offset */
5894 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5895 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5896 /* iWMMXt register transfer. */
5897 if (env
->cp15
.c15_cpar
& (1 << 1))
5898 if (!disas_iwmmxt_insn(env
, s
, insn
))
5901 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5902 /* Coprocessor double register transfer. */
5903 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5904 /* Additional coprocessor register transfer. */
5905 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5908 /* cps (privileged) */
5912 if (insn
& (1 << 19)) {
5913 if (insn
& (1 << 8))
5915 if (insn
& (1 << 7))
5917 if (insn
& (1 << 6))
5919 if (insn
& (1 << 18))
5922 if (insn
& (1 << 17)) {
5924 val
|= (insn
& 0x1f);
5927 gen_set_psr_im(s
, mask
, 0, val
);
5934 /* if not always execute, we generate a conditional jump to
5936 s
->condlabel
= gen_new_label();
5937 gen_test_cc(cond
^ 1, s
->condlabel
);
5940 if ((insn
& 0x0f900000) == 0x03000000) {
5941 if ((insn
& (1 << 21)) == 0) {
5943 rd
= (insn
>> 12) & 0xf;
5944 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5945 if ((insn
& (1 << 22)) == 0) {
5948 tcg_gen_movi_i32(tmp
, val
);
5951 tmp
= load_reg(s
, rd
);
5952 tcg_gen_ext16u_i32(tmp
, tmp
);
5953 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5955 store_reg(s
, rd
, tmp
);
5957 if (((insn
>> 12) & 0xf) != 0xf)
5959 if (((insn
>> 16) & 0xf) == 0) {
5960 gen_nop_hint(s
, insn
& 0xff);
5962 /* CPSR = immediate */
5964 shift
= ((insn
>> 8) & 0xf) * 2;
5966 val
= (val
>> shift
) | (val
<< (32 - shift
));
5967 i
= ((insn
& (1 << 22)) != 0);
5968 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5972 } else if ((insn
& 0x0f900000) == 0x01000000
5973 && (insn
& 0x00000090) != 0x00000090) {
5974 /* miscellaneous instructions */
5975 op1
= (insn
>> 21) & 3;
5976 sh
= (insn
>> 4) & 0xf;
5979 case 0x0: /* move program status register */
5982 tmp
= load_reg(s
, rm
);
5983 i
= ((op1
& 2) != 0);
5984 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
5988 rd
= (insn
>> 12) & 0xf;
5992 tmp
= load_cpu_field(spsr
);
5995 gen_helper_cpsr_read(tmp
);
5997 store_reg(s
, rd
, tmp
);
6002 /* branch/exchange thumb (bx). */
6003 tmp
= load_reg(s
, rm
);
6005 } else if (op1
== 3) {
6007 rd
= (insn
>> 12) & 0xf;
6008 tmp
= load_reg(s
, rm
);
6009 gen_helper_clz(tmp
, tmp
);
6010 store_reg(s
, rd
, tmp
);
6018 /* Trivial implementation equivalent to bx. */
6019 tmp
= load_reg(s
, rm
);
6029 /* branch link/exchange thumb (blx) */
6030 tmp
= load_reg(s
, rm
);
6032 tcg_gen_movi_i32(tmp2
, s
->pc
);
6033 store_reg(s
, 14, tmp2
);
6036 case 0x5: /* saturating add/subtract */
6037 rd
= (insn
>> 12) & 0xf;
6038 rn
= (insn
>> 16) & 0xf;
6039 tmp
= load_reg(s
, rm
);
6040 tmp2
= load_reg(s
, rn
);
6042 gen_helper_double_saturate(tmp2
, tmp2
);
6044 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6046 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6048 store_reg(s
, rd
, tmp
);
6051 gen_set_condexec(s
);
6052 gen_set_pc_im(s
->pc
- 4);
6053 gen_exception(EXCP_BKPT
);
6054 s
->is_jmp
= DISAS_JUMP
;
6056 case 0x8: /* signed multiply */
6060 rs
= (insn
>> 8) & 0xf;
6061 rn
= (insn
>> 12) & 0xf;
6062 rd
= (insn
>> 16) & 0xf;
6064 /* (32 * 16) >> 16 */
6065 tmp
= load_reg(s
, rm
);
6066 tmp2
= load_reg(s
, rs
);
6068 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6071 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6072 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6074 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6075 tcg_temp_free_i64(tmp64
);
6076 if ((sh
& 2) == 0) {
6077 tmp2
= load_reg(s
, rn
);
6078 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6081 store_reg(s
, rd
, tmp
);
6084 tmp
= load_reg(s
, rm
);
6085 tmp2
= load_reg(s
, rs
);
6086 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6089 tmp64
= tcg_temp_new_i64();
6090 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6092 gen_addq(s
, tmp64
, rn
, rd
);
6093 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6094 tcg_temp_free_i64(tmp64
);
6097 tmp2
= load_reg(s
, rn
);
6098 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6101 store_reg(s
, rd
, tmp
);
6108 } else if (((insn
& 0x0e000000) == 0 &&
6109 (insn
& 0x00000090) != 0x90) ||
6110 ((insn
& 0x0e000000) == (1 << 25))) {
6111 int set_cc
, logic_cc
, shiftop
;
6113 op1
= (insn
>> 21) & 0xf;
6114 set_cc
= (insn
>> 20) & 1;
6115 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6117 /* data processing instruction */
6118 if (insn
& (1 << 25)) {
6119 /* immediate operand */
6121 shift
= ((insn
>> 8) & 0xf) * 2;
6123 val
= (val
>> shift
) | (val
<< (32 - shift
));
6126 tcg_gen_movi_i32(tmp2
, val
);
6127 if (logic_cc
&& shift
) {
6128 gen_set_CF_bit31(tmp2
);
6133 tmp2
= load_reg(s
, rm
);
6134 shiftop
= (insn
>> 5) & 3;
6135 if (!(insn
& (1 << 4))) {
6136 shift
= (insn
>> 7) & 0x1f;
6137 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6139 rs
= (insn
>> 8) & 0xf;
6140 tmp
= load_reg(s
, rs
);
6141 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6144 if (op1
!= 0x0f && op1
!= 0x0d) {
6145 rn
= (insn
>> 16) & 0xf;
6146 tmp
= load_reg(s
, rn
);
6150 rd
= (insn
>> 12) & 0xf;
6153 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6157 store_reg_bx(env
, s
, rd
, tmp
);
6160 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6164 store_reg_bx(env
, s
, rd
, tmp
);
6167 if (set_cc
&& rd
== 15) {
6168 /* SUBS r15, ... is used for exception return. */
6172 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6173 gen_exception_return(s
, tmp
);
6176 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6178 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6180 store_reg_bx(env
, s
, rd
, tmp
);
6185 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6187 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6189 store_reg_bx(env
, s
, rd
, tmp
);
6193 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6195 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6197 store_reg_bx(env
, s
, rd
, tmp
);
6201 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6203 gen_add_carry(tmp
, tmp
, tmp2
);
6205 store_reg_bx(env
, s
, rd
, tmp
);
6209 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6211 gen_sub_carry(tmp
, tmp
, tmp2
);
6213 store_reg_bx(env
, s
, rd
, tmp
);
6217 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6219 gen_sub_carry(tmp
, tmp2
, tmp
);
6221 store_reg_bx(env
, s
, rd
, tmp
);
6225 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6232 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6239 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6245 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6250 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6254 store_reg_bx(env
, s
, rd
, tmp
);
6257 if (logic_cc
&& rd
== 15) {
6258 /* MOVS r15, ... is used for exception return. */
6262 gen_exception_return(s
, tmp2
);
6267 store_reg_bx(env
, s
, rd
, tmp2
);
6271 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6275 store_reg_bx(env
, s
, rd
, tmp
);
6279 tcg_gen_not_i32(tmp2
, tmp2
);
6283 store_reg_bx(env
, s
, rd
, tmp2
);
6286 if (op1
!= 0x0f && op1
!= 0x0d) {
6290 /* other instructions */
6291 op1
= (insn
>> 24) & 0xf;
6295 /* multiplies, extra load/stores */
6296 sh
= (insn
>> 5) & 3;
6299 rd
= (insn
>> 16) & 0xf;
6300 rn
= (insn
>> 12) & 0xf;
6301 rs
= (insn
>> 8) & 0xf;
6303 op1
= (insn
>> 20) & 0xf;
6305 case 0: case 1: case 2: case 3: case 6:
6307 tmp
= load_reg(s
, rs
);
6308 tmp2
= load_reg(s
, rm
);
6309 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6311 if (insn
& (1 << 22)) {
6312 /* Subtract (mls) */
6314 tmp2
= load_reg(s
, rn
);
6315 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6317 } else if (insn
& (1 << 21)) {
6319 tmp2
= load_reg(s
, rn
);
6320 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6323 if (insn
& (1 << 20))
6325 store_reg(s
, rd
, tmp
);
6329 tmp
= load_reg(s
, rs
);
6330 tmp2
= load_reg(s
, rm
);
6331 if (insn
& (1 << 22))
6332 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6334 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6335 if (insn
& (1 << 21)) /* mult accumulate */
6336 gen_addq(s
, tmp64
, rn
, rd
);
6337 if (!(insn
& (1 << 23))) { /* double accumulate */
6339 gen_addq_lo(s
, tmp64
, rn
);
6340 gen_addq_lo(s
, tmp64
, rd
);
6342 if (insn
& (1 << 20))
6343 gen_logicq_cc(tmp64
);
6344 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6345 tcg_temp_free_i64(tmp64
);
6349 rn
= (insn
>> 16) & 0xf;
6350 rd
= (insn
>> 12) & 0xf;
6351 if (insn
& (1 << 23)) {
6352 /* load/store exclusive */
6353 op1
= (insn
>> 21) & 0x3;
6358 addr
= tcg_temp_local_new_i32();
6359 load_reg_var(s
, addr
, rn
);
6360 if (insn
& (1 << 20)) {
6361 gen_helper_mark_exclusive(cpu_env
, addr
);
6364 tmp
= gen_ld32(addr
, IS_USER(s
));
6366 case 1: /* ldrexd */
6367 tmp
= gen_ld32(addr
, IS_USER(s
));
6368 store_reg(s
, rd
, tmp
);
6369 tcg_gen_addi_i32(addr
, addr
, 4);
6370 tmp
= gen_ld32(addr
, IS_USER(s
));
6373 case 2: /* ldrexb */
6374 tmp
= gen_ld8u(addr
, IS_USER(s
));
6376 case 3: /* ldrexh */
6377 tmp
= gen_ld16u(addr
, IS_USER(s
));
6382 store_reg(s
, rd
, tmp
);
6384 int label
= gen_new_label();
6386 tmp2
= tcg_temp_local_new_i32();
6387 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6388 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6389 tmp
= load_reg(s
,rm
);
6392 gen_st32(tmp
, addr
, IS_USER(s
));
6394 case 1: /* strexd */
6395 gen_st32(tmp
, addr
, IS_USER(s
));
6396 tcg_gen_addi_i32(addr
, addr
, 4);
6397 tmp
= load_reg(s
, rm
+ 1);
6398 gen_st32(tmp
, addr
, IS_USER(s
));
6400 case 2: /* strexb */
6401 gen_st8(tmp
, addr
, IS_USER(s
));
6403 case 3: /* strexh */
6404 gen_st16(tmp
, addr
, IS_USER(s
));
6409 gen_set_label(label
);
6410 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6411 tcg_temp_free(tmp2
);
6413 tcg_temp_free(addr
);
6415 /* SWP instruction */
6418 /* ??? This is not really atomic. However we know
6419 we never have multiple CPUs running in parallel,
6420 so it is good enough. */
6421 addr
= load_reg(s
, rn
);
6422 tmp
= load_reg(s
, rm
);
6423 if (insn
& (1 << 22)) {
6424 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6425 gen_st8(tmp
, addr
, IS_USER(s
));
6427 tmp2
= gen_ld32(addr
, IS_USER(s
));
6428 gen_st32(tmp
, addr
, IS_USER(s
));
6431 store_reg(s
, rd
, tmp2
);
6437 /* Misc load/store */
6438 rn
= (insn
>> 16) & 0xf;
6439 rd
= (insn
>> 12) & 0xf;
6440 addr
= load_reg(s
, rn
);
6441 if (insn
& (1 << 24))
6442 gen_add_datah_offset(s
, insn
, 0, addr
);
6444 if (insn
& (1 << 20)) {
6448 tmp
= gen_ld16u(addr
, IS_USER(s
));
6451 tmp
= gen_ld8s(addr
, IS_USER(s
));
6455 tmp
= gen_ld16s(addr
, IS_USER(s
));
6459 } else if (sh
& 2) {
6463 tmp
= load_reg(s
, rd
);
6464 gen_st32(tmp
, addr
, IS_USER(s
));
6465 tcg_gen_addi_i32(addr
, addr
, 4);
6466 tmp
= load_reg(s
, rd
+ 1);
6467 gen_st32(tmp
, addr
, IS_USER(s
));
6471 tmp
= gen_ld32(addr
, IS_USER(s
));
6472 store_reg(s
, rd
, tmp
);
6473 tcg_gen_addi_i32(addr
, addr
, 4);
6474 tmp
= gen_ld32(addr
, IS_USER(s
));
6478 address_offset
= -4;
6481 tmp
= load_reg(s
, rd
);
6482 gen_st16(tmp
, addr
, IS_USER(s
));
6485 /* Perform base writeback before the loaded value to
6486 ensure correct behavior with overlapping index registers.
6487 ldrd with base writeback is is undefined if the
6488 destination and index registers overlap. */
6489 if (!(insn
& (1 << 24))) {
6490 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6491 store_reg(s
, rn
, addr
);
6492 } else if (insn
& (1 << 21)) {
6494 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6495 store_reg(s
, rn
, addr
);
6500 /* Complete the load. */
6501 store_reg(s
, rd
, tmp
);
6510 if (insn
& (1 << 4)) {
6512 /* Armv6 Media instructions. */
6514 rn
= (insn
>> 16) & 0xf;
6515 rd
= (insn
>> 12) & 0xf;
6516 rs
= (insn
>> 8) & 0xf;
6517 switch ((insn
>> 23) & 3) {
6518 case 0: /* Parallel add/subtract. */
6519 op1
= (insn
>> 20) & 7;
6520 tmp
= load_reg(s
, rn
);
6521 tmp2
= load_reg(s
, rm
);
6522 sh
= (insn
>> 5) & 7;
6523 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6525 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6527 store_reg(s
, rd
, tmp
);
6530 if ((insn
& 0x00700020) == 0) {
6531 /* Halfword pack. */
6532 tmp
= load_reg(s
, rn
);
6533 tmp2
= load_reg(s
, rm
);
6534 shift
= (insn
>> 7) & 0x1f;
6535 if (insn
& (1 << 6)) {
6539 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6540 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6541 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6545 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6546 tcg_gen_ext16u_i32(tmp
, tmp
);
6547 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6549 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6551 store_reg(s
, rd
, tmp
);
6552 } else if ((insn
& 0x00200020) == 0x00200000) {
6554 tmp
= load_reg(s
, rm
);
6555 shift
= (insn
>> 7) & 0x1f;
6556 if (insn
& (1 << 6)) {
6559 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6561 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6563 sh
= (insn
>> 16) & 0x1f;
6565 tmp2
= tcg_const_i32(sh
);
6566 if (insn
& (1 << 22))
6567 gen_helper_usat(tmp
, tmp
, tmp2
);
6569 gen_helper_ssat(tmp
, tmp
, tmp2
);
6570 tcg_temp_free_i32(tmp2
);
6572 store_reg(s
, rd
, tmp
);
6573 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6575 tmp
= load_reg(s
, rm
);
6576 sh
= (insn
>> 16) & 0x1f;
6578 tmp2
= tcg_const_i32(sh
);
6579 if (insn
& (1 << 22))
6580 gen_helper_usat16(tmp
, tmp
, tmp2
);
6582 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6583 tcg_temp_free_i32(tmp2
);
6585 store_reg(s
, rd
, tmp
);
6586 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6588 tmp
= load_reg(s
, rn
);
6589 tmp2
= load_reg(s
, rm
);
6591 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6592 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6595 store_reg(s
, rd
, tmp
);
6596 } else if ((insn
& 0x000003e0) == 0x00000060) {
6597 tmp
= load_reg(s
, rm
);
6598 shift
= (insn
>> 10) & 3;
6599 /* ??? In many cases it's not neccessary to do a
6600 rotate, a shift is sufficient. */
6602 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6603 op1
= (insn
>> 20) & 7;
6605 case 0: gen_sxtb16(tmp
); break;
6606 case 2: gen_sxtb(tmp
); break;
6607 case 3: gen_sxth(tmp
); break;
6608 case 4: gen_uxtb16(tmp
); break;
6609 case 6: gen_uxtb(tmp
); break;
6610 case 7: gen_uxth(tmp
); break;
6611 default: goto illegal_op
;
6614 tmp2
= load_reg(s
, rn
);
6615 if ((op1
& 3) == 0) {
6616 gen_add16(tmp
, tmp2
);
6618 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6622 store_reg(s
, rd
, tmp
);
6623 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6625 tmp
= load_reg(s
, rm
);
6626 if (insn
& (1 << 22)) {
6627 if (insn
& (1 << 7)) {
6631 gen_helper_rbit(tmp
, tmp
);
6634 if (insn
& (1 << 7))
6637 tcg_gen_bswap32_i32(tmp
, tmp
);
6639 store_reg(s
, rd
, tmp
);
6644 case 2: /* Multiplies (Type 3). */
6645 tmp
= load_reg(s
, rm
);
6646 tmp2
= load_reg(s
, rs
);
6647 if (insn
& (1 << 20)) {
6648 /* Signed multiply most significant [accumulate]. */
6649 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6650 if (insn
& (1 << 5))
6651 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6652 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6654 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6655 tcg_temp_free_i64(tmp64
);
6657 tmp2
= load_reg(s
, rd
);
6658 if (insn
& (1 << 6)) {
6659 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6661 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6665 store_reg(s
, rn
, tmp
);
6667 if (insn
& (1 << 5))
6668 gen_swap_half(tmp2
);
6669 gen_smul_dual(tmp
, tmp2
);
6670 /* This addition cannot overflow. */
6671 if (insn
& (1 << 6)) {
6672 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6674 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6677 if (insn
& (1 << 22)) {
6678 /* smlald, smlsld */
6679 tmp64
= tcg_temp_new_i64();
6680 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6682 gen_addq(s
, tmp64
, rd
, rn
);
6683 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6684 tcg_temp_free_i64(tmp64
);
6686 /* smuad, smusd, smlad, smlsd */
6689 tmp2
= load_reg(s
, rd
);
6690 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6693 store_reg(s
, rn
, tmp
);
6698 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6700 case 0: /* Unsigned sum of absolute differences. */
6702 tmp
= load_reg(s
, rm
);
6703 tmp2
= load_reg(s
, rs
);
6704 gen_helper_usad8(tmp
, tmp
, tmp2
);
6707 tmp2
= load_reg(s
, rd
);
6708 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6711 store_reg(s
, rn
, tmp
);
6713 case 0x20: case 0x24: case 0x28: case 0x2c:
6714 /* Bitfield insert/clear. */
6716 shift
= (insn
>> 7) & 0x1f;
6717 i
= (insn
>> 16) & 0x1f;
6721 tcg_gen_movi_i32(tmp
, 0);
6723 tmp
= load_reg(s
, rm
);
6726 tmp2
= load_reg(s
, rd
);
6727 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6730 store_reg(s
, rd
, tmp
);
6732 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6733 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6735 tmp
= load_reg(s
, rm
);
6736 shift
= (insn
>> 7) & 0x1f;
6737 i
= ((insn
>> 16) & 0x1f) + 1;
6742 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6744 gen_sbfx(tmp
, shift
, i
);
6747 store_reg(s
, rd
, tmp
);
6757 /* Check for undefined extension instructions
6758 * per the ARM Bible IE:
6759 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6761 sh
= (0xf << 20) | (0xf << 4);
6762 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6766 /* load/store byte/word */
6767 rn
= (insn
>> 16) & 0xf;
6768 rd
= (insn
>> 12) & 0xf;
6769 tmp2
= load_reg(s
, rn
);
6770 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6771 if (insn
& (1 << 24))
6772 gen_add_data_offset(s
, insn
, tmp2
);
6773 if (insn
& (1 << 20)) {
6775 if (insn
& (1 << 22)) {
6776 tmp
= gen_ld8u(tmp2
, i
);
6778 tmp
= gen_ld32(tmp2
, i
);
6782 tmp
= load_reg(s
, rd
);
6783 if (insn
& (1 << 22))
6784 gen_st8(tmp
, tmp2
, i
);
6786 gen_st32(tmp
, tmp2
, i
);
6788 if (!(insn
& (1 << 24))) {
6789 gen_add_data_offset(s
, insn
, tmp2
);
6790 store_reg(s
, rn
, tmp2
);
6791 } else if (insn
& (1 << 21)) {
6792 store_reg(s
, rn
, tmp2
);
6796 if (insn
& (1 << 20)) {
6797 /* Complete the load. */
6801 store_reg(s
, rd
, tmp
);
6807 int j
, n
, user
, loaded_base
;
6809 /* load/store multiple words */
6810 /* XXX: store correct base if write back */
6812 if (insn
& (1 << 22)) {
6814 goto illegal_op
; /* only usable in supervisor mode */
6816 if ((insn
& (1 << 15)) == 0)
6819 rn
= (insn
>> 16) & 0xf;
6820 addr
= load_reg(s
, rn
);
6822 /* compute total size */
6824 TCGV_UNUSED(loaded_var
);
6827 if (insn
& (1 << i
))
6830 /* XXX: test invalid n == 0 case ? */
6831 if (insn
& (1 << 23)) {
6832 if (insn
& (1 << 24)) {
6834 tcg_gen_addi_i32(addr
, addr
, 4);
6836 /* post increment */
6839 if (insn
& (1 << 24)) {
6841 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6843 /* post decrement */
6845 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6850 if (insn
& (1 << i
)) {
6851 if (insn
& (1 << 20)) {
6853 tmp
= gen_ld32(addr
, IS_USER(s
));
6857 tmp2
= tcg_const_i32(i
);
6858 gen_helper_set_user_reg(tmp2
, tmp
);
6859 tcg_temp_free_i32(tmp2
);
6861 } else if (i
== rn
) {
6865 store_reg(s
, i
, tmp
);
6870 /* special case: r15 = PC + 8 */
6871 val
= (long)s
->pc
+ 4;
6873 tcg_gen_movi_i32(tmp
, val
);
6876 tmp2
= tcg_const_i32(i
);
6877 gen_helper_get_user_reg(tmp
, tmp2
);
6878 tcg_temp_free_i32(tmp2
);
6880 tmp
= load_reg(s
, i
);
6882 gen_st32(tmp
, addr
, IS_USER(s
));
6885 /* no need to add after the last transfer */
6887 tcg_gen_addi_i32(addr
, addr
, 4);
6890 if (insn
& (1 << 21)) {
6892 if (insn
& (1 << 23)) {
6893 if (insn
& (1 << 24)) {
6896 /* post increment */
6897 tcg_gen_addi_i32(addr
, addr
, 4);
6900 if (insn
& (1 << 24)) {
6903 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6905 /* post decrement */
6906 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6909 store_reg(s
, rn
, addr
);
6914 store_reg(s
, rn
, loaded_var
);
6916 if ((insn
& (1 << 22)) && !user
) {
6917 /* Restore CPSR from SPSR. */
6918 tmp
= load_cpu_field(spsr
);
6919 gen_set_cpsr(tmp
, 0xffffffff);
6921 s
->is_jmp
= DISAS_UPDATE
;
6930 /* branch (and link) */
6931 val
= (int32_t)s
->pc
;
6932 if (insn
& (1 << 24)) {
6934 tcg_gen_movi_i32(tmp
, val
);
6935 store_reg(s
, 14, tmp
);
6937 offset
= (((int32_t)insn
<< 8) >> 8);
6938 val
+= (offset
<< 2) + 4;
6946 if (disas_coproc_insn(env
, s
, insn
))
6951 gen_set_pc_im(s
->pc
);
6952 s
->is_jmp
= DISAS_SWI
;
6956 gen_set_condexec(s
);
6957 gen_set_pc_im(s
->pc
- 4);
6958 gen_exception(EXCP_UDEF
);
6959 s
->is_jmp
= DISAS_JUMP
;
6965 /* Return true if this is a Thumb-2 logical op. */
6967 thumb2_logic_op(int op
)
6972 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6973 then set condition code flags based on the result of the operation.
6974 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6975 to the high bit of T1.
6976 Returns zero if the opcode is valid. */
6979 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
6986 tcg_gen_and_i32(t0
, t0
, t1
);
6990 tcg_gen_bic_i32(t0
, t0
, t1
);
6994 tcg_gen_or_i32(t0
, t0
, t1
);
6998 tcg_gen_not_i32(t1
, t1
);
6999 tcg_gen_or_i32(t0
, t0
, t1
);
7003 tcg_gen_xor_i32(t0
, t0
, t1
);
7008 gen_helper_add_cc(t0
, t0
, t1
);
7010 tcg_gen_add_i32(t0
, t0
, t1
);
7014 gen_helper_adc_cc(t0
, t0
, t1
);
7020 gen_helper_sbc_cc(t0
, t0
, t1
);
7022 gen_sub_carry(t0
, t0
, t1
);
7026 gen_helper_sub_cc(t0
, t0
, t1
);
7028 tcg_gen_sub_i32(t0
, t0
, t1
);
7032 gen_helper_sub_cc(t0
, t1
, t0
);
7034 tcg_gen_sub_i32(t0
, t1
, t0
);
7036 default: /* 5, 6, 7, 9, 12, 15. */
7042 gen_set_CF_bit31(t1
);
7047 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7049 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7051 uint32_t insn
, imm
, shift
, offset
;
7052 uint32_t rd
, rn
, rm
, rs
;
7063 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7064 || arm_feature (env
, ARM_FEATURE_M
))) {
7065 /* Thumb-1 cores may need to treat bl and blx as a pair of
7066 16-bit instructions to get correct prefetch abort behavior. */
7068 if ((insn
& (1 << 12)) == 0) {
7069 /* Second half of blx. */
7070 offset
= ((insn
& 0x7ff) << 1);
7071 tmp
= load_reg(s
, 14);
7072 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7073 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7076 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7077 store_reg(s
, 14, tmp2
);
7081 if (insn
& (1 << 11)) {
7082 /* Second half of bl. */
7083 offset
= ((insn
& 0x7ff) << 1) | 1;
7084 tmp
= load_reg(s
, 14);
7085 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7088 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7089 store_reg(s
, 14, tmp2
);
7093 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7094 /* Instruction spans a page boundary. Implement it as two
7095 16-bit instructions in case the second half causes an
7097 offset
= ((int32_t)insn
<< 21) >> 9;
7098 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7101 /* Fall through to 32-bit decode. */
7104 insn
= lduw_code(s
->pc
);
7106 insn
|= (uint32_t)insn_hw1
<< 16;
7108 if ((insn
& 0xf800e800) != 0xf000e800) {
7112 rn
= (insn
>> 16) & 0xf;
7113 rs
= (insn
>> 12) & 0xf;
7114 rd
= (insn
>> 8) & 0xf;
7116 switch ((insn
>> 25) & 0xf) {
7117 case 0: case 1: case 2: case 3:
7118 /* 16-bit instructions. Should never happen. */
7121 if (insn
& (1 << 22)) {
7122 /* Other load/store, table branch. */
7123 if (insn
& 0x01200000) {
7124 /* Load/store doubleword. */
7127 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7129 addr
= load_reg(s
, rn
);
7131 offset
= (insn
& 0xff) * 4;
7132 if ((insn
& (1 << 23)) == 0)
7134 if (insn
& (1 << 24)) {
7135 tcg_gen_addi_i32(addr
, addr
, offset
);
7138 if (insn
& (1 << 20)) {
7140 tmp
= gen_ld32(addr
, IS_USER(s
));
7141 store_reg(s
, rs
, tmp
);
7142 tcg_gen_addi_i32(addr
, addr
, 4);
7143 tmp
= gen_ld32(addr
, IS_USER(s
));
7144 store_reg(s
, rd
, tmp
);
7147 tmp
= load_reg(s
, rs
);
7148 gen_st32(tmp
, addr
, IS_USER(s
));
7149 tcg_gen_addi_i32(addr
, addr
, 4);
7150 tmp
= load_reg(s
, rd
);
7151 gen_st32(tmp
, addr
, IS_USER(s
));
7153 if (insn
& (1 << 21)) {
7154 /* Base writeback. */
7157 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7158 store_reg(s
, rn
, addr
);
7162 } else if ((insn
& (1 << 23)) == 0) {
7163 /* Load/store exclusive word. */
7164 addr
= tcg_temp_local_new();
7165 load_reg_var(s
, addr
, rn
);
7166 if (insn
& (1 << 20)) {
7167 gen_helper_mark_exclusive(cpu_env
, addr
);
7168 tmp
= gen_ld32(addr
, IS_USER(s
));
7169 store_reg(s
, rd
, tmp
);
7171 int label
= gen_new_label();
7172 tmp2
= tcg_temp_local_new();
7173 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7174 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7175 tmp
= load_reg(s
, rs
);
7176 gen_st32(tmp
, addr
, IS_USER(s
));
7177 gen_set_label(label
);
7178 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7179 tcg_temp_free(tmp2
);
7181 tcg_temp_free(addr
);
7182 } else if ((insn
& (1 << 6)) == 0) {
7186 tcg_gen_movi_i32(addr
, s
->pc
);
7188 addr
= load_reg(s
, rn
);
7190 tmp
= load_reg(s
, rm
);
7191 tcg_gen_add_i32(addr
, addr
, tmp
);
7192 if (insn
& (1 << 4)) {
7194 tcg_gen_add_i32(addr
, addr
, tmp
);
7196 tmp
= gen_ld16u(addr
, IS_USER(s
));
7199 tmp
= gen_ld8u(addr
, IS_USER(s
));
7202 tcg_gen_shli_i32(tmp
, tmp
, 1);
7203 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7204 store_reg(s
, 15, tmp
);
7206 /* Load/store exclusive byte/halfword/doubleword. */
7207 /* ??? These are not really atomic. However we know
7208 we never have multiple CPUs running in parallel,
7209 so it is good enough. */
7210 op
= (insn
>> 4) & 0x3;
7211 addr
= tcg_temp_local_new();
7212 load_reg_var(s
, addr
, rn
);
7213 if (insn
& (1 << 20)) {
7214 gen_helper_mark_exclusive(cpu_env
, addr
);
7217 tmp
= gen_ld8u(addr
, IS_USER(s
));
7220 tmp
= gen_ld16u(addr
, IS_USER(s
));
7223 tmp
= gen_ld32(addr
, IS_USER(s
));
7224 tcg_gen_addi_i32(addr
, addr
, 4);
7225 tmp2
= gen_ld32(addr
, IS_USER(s
));
7226 store_reg(s
, rd
, tmp2
);
7231 store_reg(s
, rs
, tmp
);
7233 int label
= gen_new_label();
7234 tmp2
= tcg_temp_local_new();
7235 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7236 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7237 tmp
= load_reg(s
, rs
);
7240 gen_st8(tmp
, addr
, IS_USER(s
));
7243 gen_st16(tmp
, addr
, IS_USER(s
));
7246 gen_st32(tmp
, addr
, IS_USER(s
));
7247 tcg_gen_addi_i32(addr
, addr
, 4);
7248 tmp
= load_reg(s
, rd
);
7249 gen_st32(tmp
, addr
, IS_USER(s
));
7254 gen_set_label(label
);
7255 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7256 tcg_temp_free(tmp2
);
7258 tcg_temp_free(addr
);
7261 /* Load/store multiple, RFE, SRS. */
7262 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7263 /* Not available in user mode. */
7266 if (insn
& (1 << 20)) {
7268 addr
= load_reg(s
, rn
);
7269 if ((insn
& (1 << 24)) == 0)
7270 tcg_gen_addi_i32(addr
, addr
, -8);
7271 /* Load PC into tmp and CPSR into tmp2. */
7272 tmp
= gen_ld32(addr
, 0);
7273 tcg_gen_addi_i32(addr
, addr
, 4);
7274 tmp2
= gen_ld32(addr
, 0);
7275 if (insn
& (1 << 21)) {
7276 /* Base writeback. */
7277 if (insn
& (1 << 24)) {
7278 tcg_gen_addi_i32(addr
, addr
, 4);
7280 tcg_gen_addi_i32(addr
, addr
, -4);
7282 store_reg(s
, rn
, addr
);
7286 gen_rfe(s
, tmp
, tmp2
);
7290 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7291 addr
= load_reg(s
, 13);
7294 tmp
= tcg_const_i32(op
);
7295 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7296 tcg_temp_free_i32(tmp
);
7298 if ((insn
& (1 << 24)) == 0) {
7299 tcg_gen_addi_i32(addr
, addr
, -8);
7301 tmp
= load_reg(s
, 14);
7302 gen_st32(tmp
, addr
, 0);
7303 tcg_gen_addi_i32(addr
, addr
, 4);
7305 gen_helper_cpsr_read(tmp
);
7306 gen_st32(tmp
, addr
, 0);
7307 if (insn
& (1 << 21)) {
7308 if ((insn
& (1 << 24)) == 0) {
7309 tcg_gen_addi_i32(addr
, addr
, -4);
7311 tcg_gen_addi_i32(addr
, addr
, 4);
7313 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7314 store_reg(s
, 13, addr
);
7316 tmp
= tcg_const_i32(op
);
7317 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7318 tcg_temp_free_i32(tmp
);
7326 /* Load/store multiple. */
7327 addr
= load_reg(s
, rn
);
7329 for (i
= 0; i
< 16; i
++) {
7330 if (insn
& (1 << i
))
7333 if (insn
& (1 << 24)) {
7334 tcg_gen_addi_i32(addr
, addr
, -offset
);
7337 for (i
= 0; i
< 16; i
++) {
7338 if ((insn
& (1 << i
)) == 0)
7340 if (insn
& (1 << 20)) {
7342 tmp
= gen_ld32(addr
, IS_USER(s
));
7346 store_reg(s
, i
, tmp
);
7350 tmp
= load_reg(s
, i
);
7351 gen_st32(tmp
, addr
, IS_USER(s
));
7353 tcg_gen_addi_i32(addr
, addr
, 4);
7355 if (insn
& (1 << 21)) {
7356 /* Base register writeback. */
7357 if (insn
& (1 << 24)) {
7358 tcg_gen_addi_i32(addr
, addr
, -offset
);
7360 /* Fault if writeback register is in register list. */
7361 if (insn
& (1 << rn
))
7363 store_reg(s
, rn
, addr
);
7370 case 5: /* Data processing register constant shift. */
7373 tcg_gen_movi_i32(tmp
, 0);
7375 tmp
= load_reg(s
, rn
);
7377 tmp2
= load_reg(s
, rm
);
7378 op
= (insn
>> 21) & 0xf;
7379 shiftop
= (insn
>> 4) & 3;
7380 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7381 conds
= (insn
& (1 << 20)) != 0;
7382 logic_cc
= (conds
&& thumb2_logic_op(op
));
7383 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7384 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7388 store_reg(s
, rd
, tmp
);
7393 case 13: /* Misc data processing. */
7394 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7395 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7398 case 0: /* Register controlled shift. */
7399 tmp
= load_reg(s
, rn
);
7400 tmp2
= load_reg(s
, rm
);
7401 if ((insn
& 0x70) != 0)
7403 op
= (insn
>> 21) & 3;
7404 logic_cc
= (insn
& (1 << 20)) != 0;
7405 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7408 store_reg_bx(env
, s
, rd
, tmp
);
7410 case 1: /* Sign/zero extend. */
7411 tmp
= load_reg(s
, rm
);
7412 shift
= (insn
>> 4) & 3;
7413 /* ??? In many cases it's not neccessary to do a
7414 rotate, a shift is sufficient. */
7416 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7417 op
= (insn
>> 20) & 7;
7419 case 0: gen_sxth(tmp
); break;
7420 case 1: gen_uxth(tmp
); break;
7421 case 2: gen_sxtb16(tmp
); break;
7422 case 3: gen_uxtb16(tmp
); break;
7423 case 4: gen_sxtb(tmp
); break;
7424 case 5: gen_uxtb(tmp
); break;
7425 default: goto illegal_op
;
7428 tmp2
= load_reg(s
, rn
);
7429 if ((op
>> 1) == 1) {
7430 gen_add16(tmp
, tmp2
);
7432 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7436 store_reg(s
, rd
, tmp
);
7438 case 2: /* SIMD add/subtract. */
7439 op
= (insn
>> 20) & 7;
7440 shift
= (insn
>> 4) & 7;
7441 if ((op
& 3) == 3 || (shift
& 3) == 3)
7443 tmp
= load_reg(s
, rn
);
7444 tmp2
= load_reg(s
, rm
);
7445 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7447 store_reg(s
, rd
, tmp
);
7449 case 3: /* Other data processing. */
7450 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7452 /* Saturating add/subtract. */
7453 tmp
= load_reg(s
, rn
);
7454 tmp2
= load_reg(s
, rm
);
7456 gen_helper_double_saturate(tmp
, tmp
);
7458 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7460 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7463 tmp
= load_reg(s
, rn
);
7465 case 0x0a: /* rbit */
7466 gen_helper_rbit(tmp
, tmp
);
7468 case 0x08: /* rev */
7469 tcg_gen_bswap32_i32(tmp
, tmp
);
7471 case 0x09: /* rev16 */
7474 case 0x0b: /* revsh */
7477 case 0x10: /* sel */
7478 tmp2
= load_reg(s
, rm
);
7480 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7481 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7485 case 0x18: /* clz */
7486 gen_helper_clz(tmp
, tmp
);
7492 store_reg(s
, rd
, tmp
);
7494 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7495 op
= (insn
>> 4) & 0xf;
7496 tmp
= load_reg(s
, rn
);
7497 tmp2
= load_reg(s
, rm
);
7498 switch ((insn
>> 20) & 7) {
7499 case 0: /* 32 x 32 -> 32 */
7500 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7503 tmp2
= load_reg(s
, rs
);
7505 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7507 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7511 case 1: /* 16 x 16 -> 32 */
7512 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7515 tmp2
= load_reg(s
, rs
);
7516 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7520 case 2: /* Dual multiply add. */
7521 case 4: /* Dual multiply subtract. */
7523 gen_swap_half(tmp2
);
7524 gen_smul_dual(tmp
, tmp2
);
7525 /* This addition cannot overflow. */
7526 if (insn
& (1 << 22)) {
7527 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7529 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7534 tmp2
= load_reg(s
, rs
);
7535 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7539 case 3: /* 32 * 16 -> 32msb */
7541 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7544 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7545 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7547 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7548 tcg_temp_free_i64(tmp64
);
7551 tmp2
= load_reg(s
, rs
);
7552 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7556 case 5: case 6: /* 32 * 32 -> 32msb */
7557 gen_imull(tmp
, tmp2
);
7558 if (insn
& (1 << 5)) {
7559 gen_roundqd(tmp
, tmp2
);
7566 tmp2
= load_reg(s
, rs
);
7567 if (insn
& (1 << 21)) {
7568 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7570 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7575 case 7: /* Unsigned sum of absolute differences. */
7576 gen_helper_usad8(tmp
, tmp
, tmp2
);
7579 tmp2
= load_reg(s
, rs
);
7580 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7585 store_reg(s
, rd
, tmp
);
7587 case 6: case 7: /* 64-bit multiply, Divide. */
7588 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7589 tmp
= load_reg(s
, rn
);
7590 tmp2
= load_reg(s
, rm
);
7591 if ((op
& 0x50) == 0x10) {
7593 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7596 gen_helper_udiv(tmp
, tmp
, tmp2
);
7598 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7600 store_reg(s
, rd
, tmp
);
7601 } else if ((op
& 0xe) == 0xc) {
7602 /* Dual multiply accumulate long. */
7604 gen_swap_half(tmp2
);
7605 gen_smul_dual(tmp
, tmp2
);
7607 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7609 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7613 tmp64
= tcg_temp_new_i64();
7614 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7616 gen_addq(s
, tmp64
, rs
, rd
);
7617 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7618 tcg_temp_free_i64(tmp64
);
7621 /* Unsigned 64-bit multiply */
7622 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7626 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7628 tmp64
= tcg_temp_new_i64();
7629 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7632 /* Signed 64-bit multiply */
7633 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7638 gen_addq_lo(s
, tmp64
, rs
);
7639 gen_addq_lo(s
, tmp64
, rd
);
7640 } else if (op
& 0x40) {
7641 /* 64-bit accumulate. */
7642 gen_addq(s
, tmp64
, rs
, rd
);
7644 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7645 tcg_temp_free_i64(tmp64
);
7650 case 6: case 7: case 14: case 15:
7652 if (((insn
>> 24) & 3) == 3) {
7653 /* Translate into the equivalent ARM encoding. */
7654 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7655 if (disas_neon_data_insn(env
, s
, insn
))
7658 if (insn
& (1 << 28))
7660 if (disas_coproc_insn (env
, s
, insn
))
7664 case 8: case 9: case 10: case 11:
7665 if (insn
& (1 << 15)) {
7666 /* Branches, misc control. */
7667 if (insn
& 0x5000) {
7668 /* Unconditional branch. */
7669 /* signextend(hw1[10:0]) -> offset[:12]. */
7670 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7671 /* hw1[10:0] -> offset[11:1]. */
7672 offset
|= (insn
& 0x7ff) << 1;
7673 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7674 offset[24:22] already have the same value because of the
7675 sign extension above. */
7676 offset
^= ((~insn
) & (1 << 13)) << 10;
7677 offset
^= ((~insn
) & (1 << 11)) << 11;
7679 if (insn
& (1 << 14)) {
7680 /* Branch and link. */
7681 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7685 if (insn
& (1 << 12)) {
7690 offset
&= ~(uint32_t)2;
7691 gen_bx_im(s
, offset
);
7693 } else if (((insn
>> 23) & 7) == 7) {
7695 if (insn
& (1 << 13))
7698 if (insn
& (1 << 26)) {
7699 /* Secure monitor call (v6Z) */
7700 goto illegal_op
; /* not implemented. */
7702 op
= (insn
>> 20) & 7;
7704 case 0: /* msr cpsr. */
7706 tmp
= load_reg(s
, rn
);
7707 addr
= tcg_const_i32(insn
& 0xff);
7708 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7709 tcg_temp_free_i32(addr
);
7715 case 1: /* msr spsr. */
7718 tmp
= load_reg(s
, rn
);
7720 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7724 case 2: /* cps, nop-hint. */
7725 if (((insn
>> 8) & 7) == 0) {
7726 gen_nop_hint(s
, insn
& 0xff);
7728 /* Implemented as NOP in user mode. */
7733 if (insn
& (1 << 10)) {
7734 if (insn
& (1 << 7))
7736 if (insn
& (1 << 6))
7738 if (insn
& (1 << 5))
7740 if (insn
& (1 << 9))
7741 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7743 if (insn
& (1 << 8)) {
7745 imm
|= (insn
& 0x1f);
7748 gen_set_psr_im(s
, offset
, 0, imm
);
7751 case 3: /* Special control operations. */
7752 op
= (insn
>> 4) & 0xf;
7755 gen_helper_clrex(cpu_env
);
7760 /* These execute as NOPs. */
7768 /* Trivial implementation equivalent to bx. */
7769 tmp
= load_reg(s
, rn
);
7772 case 5: /* Exception return. */
7773 /* Unpredictable in user mode. */
7775 case 6: /* mrs cpsr. */
7778 addr
= tcg_const_i32(insn
& 0xff);
7779 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7780 tcg_temp_free_i32(addr
);
7782 gen_helper_cpsr_read(tmp
);
7784 store_reg(s
, rd
, tmp
);
7786 case 7: /* mrs spsr. */
7787 /* Not accessible in user mode. */
7788 if (IS_USER(s
) || IS_M(env
))
7790 tmp
= load_cpu_field(spsr
);
7791 store_reg(s
, rd
, tmp
);
7796 /* Conditional branch. */
7797 op
= (insn
>> 22) & 0xf;
7798 /* Generate a conditional jump to next instruction. */
7799 s
->condlabel
= gen_new_label();
7800 gen_test_cc(op
^ 1, s
->condlabel
);
7803 /* offset[11:1] = insn[10:0] */
7804 offset
= (insn
& 0x7ff) << 1;
7805 /* offset[17:12] = insn[21:16]. */
7806 offset
|= (insn
& 0x003f0000) >> 4;
7807 /* offset[31:20] = insn[26]. */
7808 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7809 /* offset[18] = insn[13]. */
7810 offset
|= (insn
& (1 << 13)) << 5;
7811 /* offset[19] = insn[11]. */
7812 offset
|= (insn
& (1 << 11)) << 8;
7814 /* jump to the offset */
7815 gen_jmp(s
, s
->pc
+ offset
);
7818 /* Data processing immediate. */
7819 if (insn
& (1 << 25)) {
7820 if (insn
& (1 << 24)) {
7821 if (insn
& (1 << 20))
7823 /* Bitfield/Saturate. */
7824 op
= (insn
>> 21) & 7;
7826 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7829 tcg_gen_movi_i32(tmp
, 0);
7831 tmp
= load_reg(s
, rn
);
7834 case 2: /* Signed bitfield extract. */
7836 if (shift
+ imm
> 32)
7839 gen_sbfx(tmp
, shift
, imm
);
7841 case 6: /* Unsigned bitfield extract. */
7843 if (shift
+ imm
> 32)
7846 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7848 case 3: /* Bitfield insert/clear. */
7851 imm
= imm
+ 1 - shift
;
7853 tmp2
= load_reg(s
, rd
);
7854 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7860 default: /* Saturate. */
7863 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7865 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7867 tmp2
= tcg_const_i32(imm
);
7870 if ((op
& 1) && shift
== 0)
7871 gen_helper_usat16(tmp
, tmp
, tmp2
);
7873 gen_helper_usat(tmp
, tmp
, tmp2
);
7876 if ((op
& 1) && shift
== 0)
7877 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7879 gen_helper_ssat(tmp
, tmp
, tmp2
);
7881 tcg_temp_free_i32(tmp2
);
7884 store_reg(s
, rd
, tmp
);
7886 imm
= ((insn
& 0x04000000) >> 15)
7887 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7888 if (insn
& (1 << 22)) {
7889 /* 16-bit immediate. */
7890 imm
|= (insn
>> 4) & 0xf000;
7891 if (insn
& (1 << 23)) {
7893 tmp
= load_reg(s
, rd
);
7894 tcg_gen_ext16u_i32(tmp
, tmp
);
7895 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7899 tcg_gen_movi_i32(tmp
, imm
);
7902 /* Add/sub 12-bit immediate. */
7904 offset
= s
->pc
& ~(uint32_t)3;
7905 if (insn
& (1 << 23))
7910 tcg_gen_movi_i32(tmp
, offset
);
7912 tmp
= load_reg(s
, rn
);
7913 if (insn
& (1 << 23))
7914 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7916 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7919 store_reg(s
, rd
, tmp
);
7922 int shifter_out
= 0;
7923 /* modified 12-bit immediate. */
7924 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7925 imm
= (insn
& 0xff);
7928 /* Nothing to do. */
7930 case 1: /* 00XY00XY */
7933 case 2: /* XY00XY00 */
7937 case 3: /* XYXYXYXY */
7941 default: /* Rotated constant. */
7942 shift
= (shift
<< 1) | (imm
>> 7);
7944 imm
= imm
<< (32 - shift
);
7949 tcg_gen_movi_i32(tmp2
, imm
);
7950 rn
= (insn
>> 16) & 0xf;
7953 tcg_gen_movi_i32(tmp
, 0);
7955 tmp
= load_reg(s
, rn
);
7957 op
= (insn
>> 21) & 0xf;
7958 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7959 shifter_out
, tmp
, tmp2
))
7962 rd
= (insn
>> 8) & 0xf;
7964 store_reg(s
, rd
, tmp
);
7971 case 12: /* Load/store single data item. */
7976 if ((insn
& 0x01100000) == 0x01000000) {
7977 if (disas_neon_ls_insn(env
, s
, insn
))
7985 /* s->pc has already been incremented by 4. */
7986 imm
= s
->pc
& 0xfffffffc;
7987 if (insn
& (1 << 23))
7988 imm
+= insn
& 0xfff;
7990 imm
-= insn
& 0xfff;
7991 tcg_gen_movi_i32(addr
, imm
);
7993 addr
= load_reg(s
, rn
);
7994 if (insn
& (1 << 23)) {
7995 /* Positive offset. */
7997 tcg_gen_addi_i32(addr
, addr
, imm
);
7999 op
= (insn
>> 8) & 7;
8002 case 0: case 8: /* Shifted Register. */
8003 shift
= (insn
>> 4) & 0xf;
8006 tmp
= load_reg(s
, rm
);
8008 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8009 tcg_gen_add_i32(addr
, addr
, tmp
);
8012 case 4: /* Negative offset. */
8013 tcg_gen_addi_i32(addr
, addr
, -imm
);
8015 case 6: /* User privilege. */
8016 tcg_gen_addi_i32(addr
, addr
, imm
);
8019 case 1: /* Post-decrement. */
8022 case 3: /* Post-increment. */
8026 case 5: /* Pre-decrement. */
8029 case 7: /* Pre-increment. */
8030 tcg_gen_addi_i32(addr
, addr
, imm
);
8038 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8039 if (insn
& (1 << 20)) {
8041 if (rs
== 15 && op
!= 2) {
8044 /* Memory hint. Implemented as NOP. */
8047 case 0: tmp
= gen_ld8u(addr
, user
); break;
8048 case 4: tmp
= gen_ld8s(addr
, user
); break;
8049 case 1: tmp
= gen_ld16u(addr
, user
); break;
8050 case 5: tmp
= gen_ld16s(addr
, user
); break;
8051 case 2: tmp
= gen_ld32(addr
, user
); break;
8052 default: goto illegal_op
;
8057 store_reg(s
, rs
, tmp
);
8064 tmp
= load_reg(s
, rs
);
8066 case 0: gen_st8(tmp
, addr
, user
); break;
8067 case 1: gen_st16(tmp
, addr
, user
); break;
8068 case 2: gen_st32(tmp
, addr
, user
); break;
8069 default: goto illegal_op
;
8073 tcg_gen_addi_i32(addr
, addr
, imm
);
8075 store_reg(s
, rn
, addr
);
8089 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8091 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8098 if (s
->condexec_mask
) {
8099 cond
= s
->condexec_cond
;
8100 s
->condlabel
= gen_new_label();
8101 gen_test_cc(cond
^ 1, s
->condlabel
);
8105 insn
= lduw_code(s
->pc
);
8108 switch (insn
>> 12) {
8112 op
= (insn
>> 11) & 3;
8115 rn
= (insn
>> 3) & 7;
8116 tmp
= load_reg(s
, rn
);
8117 if (insn
& (1 << 10)) {
8120 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8123 rm
= (insn
>> 6) & 7;
8124 tmp2
= load_reg(s
, rm
);
8126 if (insn
& (1 << 9)) {
8127 if (s
->condexec_mask
)
8128 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8130 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8132 if (s
->condexec_mask
)
8133 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8135 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8138 store_reg(s
, rd
, tmp
);
8140 /* shift immediate */
8141 rm
= (insn
>> 3) & 7;
8142 shift
= (insn
>> 6) & 0x1f;
8143 tmp
= load_reg(s
, rm
);
8144 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8145 if (!s
->condexec_mask
)
8147 store_reg(s
, rd
, tmp
);
8151 /* arithmetic large immediate */
8152 op
= (insn
>> 11) & 3;
8153 rd
= (insn
>> 8) & 0x7;
8154 if (op
== 0) { /* mov */
8156 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8157 if (!s
->condexec_mask
)
8159 store_reg(s
, rd
, tmp
);
8161 tmp
= load_reg(s
, rd
);
8163 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8166 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8171 if (s
->condexec_mask
)
8172 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8174 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8176 store_reg(s
, rd
, tmp
);
8179 if (s
->condexec_mask
)
8180 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8182 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8184 store_reg(s
, rd
, tmp
);
8190 if (insn
& (1 << 11)) {
8191 rd
= (insn
>> 8) & 7;
8192 /* load pc-relative. Bit 1 of PC is ignored. */
8193 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8194 val
&= ~(uint32_t)2;
8196 tcg_gen_movi_i32(addr
, val
);
8197 tmp
= gen_ld32(addr
, IS_USER(s
));
8199 store_reg(s
, rd
, tmp
);
8202 if (insn
& (1 << 10)) {
8203 /* data processing extended or blx */
8204 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8205 rm
= (insn
>> 3) & 0xf;
8206 op
= (insn
>> 8) & 3;
8209 tmp
= load_reg(s
, rd
);
8210 tmp2
= load_reg(s
, rm
);
8211 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8213 store_reg(s
, rd
, tmp
);
8216 tmp
= load_reg(s
, rd
);
8217 tmp2
= load_reg(s
, rm
);
8218 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8222 case 2: /* mov/cpy */
8223 tmp
= load_reg(s
, rm
);
8224 store_reg(s
, rd
, tmp
);
8226 case 3:/* branch [and link] exchange thumb register */
8227 tmp
= load_reg(s
, rm
);
8228 if (insn
& (1 << 7)) {
8229 val
= (uint32_t)s
->pc
| 1;
8231 tcg_gen_movi_i32(tmp2
, val
);
8232 store_reg(s
, 14, tmp2
);
8240 /* data processing register */
8242 rm
= (insn
>> 3) & 7;
8243 op
= (insn
>> 6) & 0xf;
8244 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8245 /* the shift/rotate ops want the operands backwards */
8254 if (op
== 9) { /* neg */
8256 tcg_gen_movi_i32(tmp
, 0);
8257 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8258 tmp
= load_reg(s
, rd
);
8263 tmp2
= load_reg(s
, rm
);
8266 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8267 if (!s
->condexec_mask
)
8271 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8272 if (!s
->condexec_mask
)
8276 if (s
->condexec_mask
) {
8277 gen_helper_shl(tmp2
, tmp2
, tmp
);
8279 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8284 if (s
->condexec_mask
) {
8285 gen_helper_shr(tmp2
, tmp2
, tmp
);
8287 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8292 if (s
->condexec_mask
) {
8293 gen_helper_sar(tmp2
, tmp2
, tmp
);
8295 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8300 if (s
->condexec_mask
)
8303 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8306 if (s
->condexec_mask
)
8307 gen_sub_carry(tmp
, tmp
, tmp2
);
8309 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8312 if (s
->condexec_mask
) {
8313 gen_helper_ror(tmp2
, tmp2
, tmp
);
8315 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8320 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8325 if (s
->condexec_mask
)
8326 tcg_gen_neg_i32(tmp
, tmp2
);
8328 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8331 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8335 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8339 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8340 if (!s
->condexec_mask
)
8344 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8345 if (!s
->condexec_mask
)
8349 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8350 if (!s
->condexec_mask
)
8354 tcg_gen_not_i32(tmp2
, tmp2
);
8355 if (!s
->condexec_mask
)
8363 store_reg(s
, rm
, tmp2
);
8367 store_reg(s
, rd
, tmp
);
8377 /* load/store register offset. */
8379 rn
= (insn
>> 3) & 7;
8380 rm
= (insn
>> 6) & 7;
8381 op
= (insn
>> 9) & 7;
8382 addr
= load_reg(s
, rn
);
8383 tmp
= load_reg(s
, rm
);
8384 tcg_gen_add_i32(addr
, addr
, tmp
);
8387 if (op
< 3) /* store */
8388 tmp
= load_reg(s
, rd
);
8392 gen_st32(tmp
, addr
, IS_USER(s
));
8395 gen_st16(tmp
, addr
, IS_USER(s
));
8398 gen_st8(tmp
, addr
, IS_USER(s
));
8401 tmp
= gen_ld8s(addr
, IS_USER(s
));
8404 tmp
= gen_ld32(addr
, IS_USER(s
));
8407 tmp
= gen_ld16u(addr
, IS_USER(s
));
8410 tmp
= gen_ld8u(addr
, IS_USER(s
));
8413 tmp
= gen_ld16s(addr
, IS_USER(s
));
8416 if (op
>= 3) /* load */
8417 store_reg(s
, rd
, tmp
);
8422 /* load/store word immediate offset */
8424 rn
= (insn
>> 3) & 7;
8425 addr
= load_reg(s
, rn
);
8426 val
= (insn
>> 4) & 0x7c;
8427 tcg_gen_addi_i32(addr
, addr
, val
);
8429 if (insn
& (1 << 11)) {
8431 tmp
= gen_ld32(addr
, IS_USER(s
));
8432 store_reg(s
, rd
, tmp
);
8435 tmp
= load_reg(s
, rd
);
8436 gen_st32(tmp
, addr
, IS_USER(s
));
8442 /* load/store byte immediate offset */
8444 rn
= (insn
>> 3) & 7;
8445 addr
= load_reg(s
, rn
);
8446 val
= (insn
>> 6) & 0x1f;
8447 tcg_gen_addi_i32(addr
, addr
, val
);
8449 if (insn
& (1 << 11)) {
8451 tmp
= gen_ld8u(addr
, IS_USER(s
));
8452 store_reg(s
, rd
, tmp
);
8455 tmp
= load_reg(s
, rd
);
8456 gen_st8(tmp
, addr
, IS_USER(s
));
8462 /* load/store halfword immediate offset */
8464 rn
= (insn
>> 3) & 7;
8465 addr
= load_reg(s
, rn
);
8466 val
= (insn
>> 5) & 0x3e;
8467 tcg_gen_addi_i32(addr
, addr
, val
);
8469 if (insn
& (1 << 11)) {
8471 tmp
= gen_ld16u(addr
, IS_USER(s
));
8472 store_reg(s
, rd
, tmp
);
8475 tmp
= load_reg(s
, rd
);
8476 gen_st16(tmp
, addr
, IS_USER(s
));
8482 /* load/store from stack */
8483 rd
= (insn
>> 8) & 7;
8484 addr
= load_reg(s
, 13);
8485 val
= (insn
& 0xff) * 4;
8486 tcg_gen_addi_i32(addr
, addr
, val
);
8488 if (insn
& (1 << 11)) {
8490 tmp
= gen_ld32(addr
, IS_USER(s
));
8491 store_reg(s
, rd
, tmp
);
8494 tmp
= load_reg(s
, rd
);
8495 gen_st32(tmp
, addr
, IS_USER(s
));
8501 /* add to high reg */
8502 rd
= (insn
>> 8) & 7;
8503 if (insn
& (1 << 11)) {
8505 tmp
= load_reg(s
, 13);
8507 /* PC. bit 1 is ignored. */
8509 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8511 val
= (insn
& 0xff) * 4;
8512 tcg_gen_addi_i32(tmp
, tmp
, val
);
8513 store_reg(s
, rd
, tmp
);
8518 op
= (insn
>> 8) & 0xf;
8521 /* adjust stack pointer */
8522 tmp
= load_reg(s
, 13);
8523 val
= (insn
& 0x7f) * 4;
8524 if (insn
& (1 << 7))
8525 val
= -(int32_t)val
;
8526 tcg_gen_addi_i32(tmp
, tmp
, val
);
8527 store_reg(s
, 13, tmp
);
8530 case 2: /* sign/zero extend. */
8533 rm
= (insn
>> 3) & 7;
8534 tmp
= load_reg(s
, rm
);
8535 switch ((insn
>> 6) & 3) {
8536 case 0: gen_sxth(tmp
); break;
8537 case 1: gen_sxtb(tmp
); break;
8538 case 2: gen_uxth(tmp
); break;
8539 case 3: gen_uxtb(tmp
); break;
8541 store_reg(s
, rd
, tmp
);
8543 case 4: case 5: case 0xc: case 0xd:
8545 addr
= load_reg(s
, 13);
8546 if (insn
& (1 << 8))
8550 for (i
= 0; i
< 8; i
++) {
8551 if (insn
& (1 << i
))
8554 if ((insn
& (1 << 11)) == 0) {
8555 tcg_gen_addi_i32(addr
, addr
, -offset
);
8557 for (i
= 0; i
< 8; i
++) {
8558 if (insn
& (1 << i
)) {
8559 if (insn
& (1 << 11)) {
8561 tmp
= gen_ld32(addr
, IS_USER(s
));
8562 store_reg(s
, i
, tmp
);
8565 tmp
= load_reg(s
, i
);
8566 gen_st32(tmp
, addr
, IS_USER(s
));
8568 /* advance to the next address. */
8569 tcg_gen_addi_i32(addr
, addr
, 4);
8573 if (insn
& (1 << 8)) {
8574 if (insn
& (1 << 11)) {
8576 tmp
= gen_ld32(addr
, IS_USER(s
));
8577 /* don't set the pc until the rest of the instruction
8581 tmp
= load_reg(s
, 14);
8582 gen_st32(tmp
, addr
, IS_USER(s
));
8584 tcg_gen_addi_i32(addr
, addr
, 4);
8586 if ((insn
& (1 << 11)) == 0) {
8587 tcg_gen_addi_i32(addr
, addr
, -offset
);
8589 /* write back the new stack pointer */
8590 store_reg(s
, 13, addr
);
8591 /* set the new PC value */
8592 if ((insn
& 0x0900) == 0x0900)
8596 case 1: case 3: case 9: case 11: /* czb */
8598 tmp
= load_reg(s
, rm
);
8599 s
->condlabel
= gen_new_label();
8601 if (insn
& (1 << 11))
8602 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8604 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8606 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8607 val
= (uint32_t)s
->pc
+ 2;
8612 case 15: /* IT, nop-hint. */
8613 if ((insn
& 0xf) == 0) {
8614 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8618 s
->condexec_cond
= (insn
>> 4) & 0xe;
8619 s
->condexec_mask
= insn
& 0x1f;
8620 /* No actual code generated for this insn, just setup state. */
8623 case 0xe: /* bkpt */
8624 gen_set_condexec(s
);
8625 gen_set_pc_im(s
->pc
- 2);
8626 gen_exception(EXCP_BKPT
);
8627 s
->is_jmp
= DISAS_JUMP
;
8632 rn
= (insn
>> 3) & 0x7;
8634 tmp
= load_reg(s
, rn
);
8635 switch ((insn
>> 6) & 3) {
8636 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8637 case 1: gen_rev16(tmp
); break;
8638 case 3: gen_revsh(tmp
); break;
8639 default: goto illegal_op
;
8641 store_reg(s
, rd
, tmp
);
8649 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8652 addr
= tcg_const_i32(16);
8653 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8654 tcg_temp_free_i32(addr
);
8658 addr
= tcg_const_i32(17);
8659 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8660 tcg_temp_free_i32(addr
);
8662 tcg_temp_free_i32(tmp
);
8665 if (insn
& (1 << 4))
8666 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8669 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8679 /* load/store multiple */
8680 rn
= (insn
>> 8) & 0x7;
8681 addr
= load_reg(s
, rn
);
8682 for (i
= 0; i
< 8; i
++) {
8683 if (insn
& (1 << i
)) {
8684 if (insn
& (1 << 11)) {
8686 tmp
= gen_ld32(addr
, IS_USER(s
));
8687 store_reg(s
, i
, tmp
);
8690 tmp
= load_reg(s
, i
);
8691 gen_st32(tmp
, addr
, IS_USER(s
));
8693 /* advance to the next address */
8694 tcg_gen_addi_i32(addr
, addr
, 4);
8697 /* Base register writeback. */
8698 if ((insn
& (1 << rn
)) == 0) {
8699 store_reg(s
, rn
, addr
);
8706 /* conditional branch or swi */
8707 cond
= (insn
>> 8) & 0xf;
8713 gen_set_condexec(s
);
8714 gen_set_pc_im(s
->pc
);
8715 s
->is_jmp
= DISAS_SWI
;
8718 /* generate a conditional jump to next instruction */
8719 s
->condlabel
= gen_new_label();
8720 gen_test_cc(cond
^ 1, s
->condlabel
);
8723 /* jump to the offset */
8724 val
= (uint32_t)s
->pc
+ 2;
8725 offset
= ((int32_t)insn
<< 24) >> 24;
8731 if (insn
& (1 << 11)) {
8732 if (disas_thumb2_insn(env
, s
, insn
))
8736 /* unconditional branch */
8737 val
= (uint32_t)s
->pc
;
8738 offset
= ((int32_t)insn
<< 21) >> 21;
8739 val
+= (offset
<< 1) + 2;
8744 if (disas_thumb2_insn(env
, s
, insn
))
8750 gen_set_condexec(s
);
8751 gen_set_pc_im(s
->pc
- 4);
8752 gen_exception(EXCP_UDEF
);
8753 s
->is_jmp
= DISAS_JUMP
;
8757 gen_set_condexec(s
);
8758 gen_set_pc_im(s
->pc
- 2);
8759 gen_exception(EXCP_UDEF
);
8760 s
->is_jmp
= DISAS_JUMP
;
8763 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8764 basic block 'tb'. If search_pc is TRUE, also generate PC
8765 information for each intermediate instruction. */
8766 static inline void gen_intermediate_code_internal(CPUState
*env
,
8767 TranslationBlock
*tb
,
8770 DisasContext dc1
, *dc
= &dc1
;
8772 uint16_t *gen_opc_end
;
8774 target_ulong pc_start
;
8775 uint32_t next_page_start
;
8779 /* generate intermediate code */
8786 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8788 dc
->is_jmp
= DISAS_NEXT
;
8790 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8792 dc
->thumb
= env
->thumb
;
8793 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8794 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8795 #if !defined(CONFIG_USER_ONLY)
8797 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8799 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8802 cpu_F0s
= tcg_temp_new_i32();
8803 cpu_F1s
= tcg_temp_new_i32();
8804 cpu_F0d
= tcg_temp_new_i64();
8805 cpu_F1d
= tcg_temp_new_i64();
8808 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8809 cpu_M0
= tcg_temp_new_i64();
8810 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8813 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8815 max_insns
= CF_COUNT_MASK
;
8818 /* Reset the conditional execution bits immediately. This avoids
8819 complications trying to do it at the end of the block. */
8820 if (env
->condexec_bits
)
8822 TCGv tmp
= new_tmp();
8823 tcg_gen_movi_i32(tmp
, 0);
8824 store_cpu_field(tmp
, condexec_bits
);
8827 #ifdef CONFIG_USER_ONLY
8828 /* Intercept jump to the magic kernel page. */
8829 if (dc
->pc
>= 0xffff0000) {
8830 /* We always get here via a jump, so know we are not in a
8831 conditional execution block. */
8832 gen_exception(EXCP_KERNEL_TRAP
);
8833 dc
->is_jmp
= DISAS_UPDATE
;
8837 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8838 /* We always get here via a jump, so know we are not in a
8839 conditional execution block. */
8840 gen_exception(EXCP_EXCEPTION_EXIT
);
8841 dc
->is_jmp
= DISAS_UPDATE
;
8846 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8847 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8848 if (bp
->pc
== dc
->pc
) {
8849 gen_set_condexec(dc
);
8850 gen_set_pc_im(dc
->pc
);
8851 gen_exception(EXCP_DEBUG
);
8852 dc
->is_jmp
= DISAS_JUMP
;
8853 /* Advance PC so that clearing the breakpoint will
8854 invalidate this TB. */
8856 goto done_generating
;
8862 j
= gen_opc_ptr
- gen_opc_buf
;
8866 gen_opc_instr_start
[lj
++] = 0;
8868 gen_opc_pc
[lj
] = dc
->pc
;
8869 gen_opc_instr_start
[lj
] = 1;
8870 gen_opc_icount
[lj
] = num_insns
;
8873 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8877 disas_thumb_insn(env
, dc
);
8878 if (dc
->condexec_mask
) {
8879 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8880 | ((dc
->condexec_mask
>> 4) & 1);
8881 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8882 if (dc
->condexec_mask
== 0) {
8883 dc
->condexec_cond
= 0;
8887 disas_arm_insn(env
, dc
);
8890 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8894 if (dc
->condjmp
&& !dc
->is_jmp
) {
8895 gen_set_label(dc
->condlabel
);
8898 /* Translation stops when a conditional branch is encountered.
8899 * Otherwise the subsequent code could get translated several times.
8900 * Also stop translation when a page boundary is reached. This
8901 * ensures prefetch aborts occur at the right place. */
8903 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8904 !env
->singlestep_enabled
&&
8906 dc
->pc
< next_page_start
&&
8907 num_insns
< max_insns
);
8909 if (tb
->cflags
& CF_LAST_IO
) {
8911 /* FIXME: This can theoretically happen with self-modifying
8913 cpu_abort(env
, "IO on conditional branch instruction");
8918 /* At this stage dc->condjmp will only be set when the skipped
8919 instruction was a conditional branch or trap, and the PC has
8920 already been written. */
8921 if (unlikely(env
->singlestep_enabled
)) {
8922 /* Make sure the pc is updated, and raise a debug exception. */
8924 gen_set_condexec(dc
);
8925 if (dc
->is_jmp
== DISAS_SWI
) {
8926 gen_exception(EXCP_SWI
);
8928 gen_exception(EXCP_DEBUG
);
8930 gen_set_label(dc
->condlabel
);
8932 if (dc
->condjmp
|| !dc
->is_jmp
) {
8933 gen_set_pc_im(dc
->pc
);
8936 gen_set_condexec(dc
);
8937 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8938 gen_exception(EXCP_SWI
);
8940 /* FIXME: Single stepping a WFI insn will not halt
8942 gen_exception(EXCP_DEBUG
);
8945 /* While branches must always occur at the end of an IT block,
8946 there are a few other things that can cause us to terminate
8947 the TB in the middel of an IT block:
8948 - Exception generating instructions (bkpt, swi, undefined).
8950 - Hardware watchpoints.
8951 Hardware breakpoints have already been handled and skip this code.
8953 gen_set_condexec(dc
);
8954 switch(dc
->is_jmp
) {
8956 gen_goto_tb(dc
, 1, dc
->pc
);
8961 /* indicate that the hash table must be used to find the next TB */
8965 /* nothing more to generate */
8971 gen_exception(EXCP_SWI
);
8975 gen_set_label(dc
->condlabel
);
8976 gen_set_condexec(dc
);
8977 gen_goto_tb(dc
, 1, dc
->pc
);
8983 gen_icount_end(tb
, num_insns
);
8984 *gen_opc_ptr
= INDEX_op_end
;
8987 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8988 qemu_log("----------------\n");
8989 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8990 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8995 j
= gen_opc_ptr
- gen_opc_buf
;
8998 gen_opc_instr_start
[lj
++] = 0;
9000 tb
->size
= dc
->pc
- pc_start
;
9001 tb
->icount
= num_insns
;
9005 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9007 gen_intermediate_code_internal(env
, tb
, 0);
9010 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9012 gen_intermediate_code_internal(env
, tb
, 1);
9015 static const char *cpu_mode_names
[16] = {
9016 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9017 "???", "???", "???", "und", "???", "???", "???", "sys"
9020 void cpu_dump_state(CPUState
*env
, FILE *f
,
9021 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9031 /* ??? This assumes float64 and double have the same layout.
9032 Oh well, it's only debug dumps. */
9041 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9043 cpu_fprintf(f
, "\n");
9045 cpu_fprintf(f
, " ");
9047 psr
= cpsr_read(env
);
9048 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9050 psr
& (1 << 31) ? 'N' : '-',
9051 psr
& (1 << 30) ? 'Z' : '-',
9052 psr
& (1 << 29) ? 'C' : '-',
9053 psr
& (1 << 28) ? 'V' : '-',
9054 psr
& CPSR_T
? 'T' : 'A',
9055 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9058 for (i
= 0; i
< 16; i
++) {
9059 d
.d
= env
->vfp
.regs
[i
];
9063 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9064 i
* 2, (int)s0
.i
, s0
.s
,
9065 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9066 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9069 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9073 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9074 unsigned long searched_pc
, int pc_pos
, void *puc
)
9076 env
->regs
[15] = gen_opc_pc
[pc_pos
];