]>
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. */
82 static TCGv cpu_F0s
, cpu_F1s
;
83 static TCGv_i64 cpu_F0d
, cpu_F1d
;
85 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h"
88 static const char *regnames
[] =
89 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
92 /* initialize TCG globals. */
93 void arm_translate_init(void)
97 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
99 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
100 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
102 for (i
= 0; i
< 16; i
++) {
103 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
104 offsetof(CPUState
, regs
[i
]),
112 static int num_temps
;
114 /* Allocate a temporary variable. */
115 static TCGv_i32
new_tmp(void)
118 return tcg_temp_new_i32();
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp
)
128 static inline TCGv
load_cpu_offset(int offset
)
130 TCGv tmp
= new_tmp();
131 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
135 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
137 static inline void store_cpu_offset(TCGv var
, int offset
)
139 tcg_gen_st_i32(var
, cpu_env
, offset
);
143 #define store_cpu_field(var, name) \
144 store_cpu_offset(var, offsetof(CPUState, name))
146 /* Set a variable to the value of a CPU register. */
147 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
151 /* normaly, since we updated PC, we need only to add one insn */
153 addr
= (long)s
->pc
+ 2;
155 addr
= (long)s
->pc
+ 4;
156 tcg_gen_movi_i32(var
, addr
);
158 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
162 /* Create a new temporary and set it to the value of a CPU register. */
163 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
165 TCGv tmp
= new_tmp();
166 load_reg_var(s
, tmp
, reg
);
170 /* Set a CPU register. The source must be a temporary and will be
172 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
175 tcg_gen_andi_i32(var
, var
, ~1);
176 s
->is_jmp
= DISAS_JUMP
;
178 tcg_gen_mov_i32(cpu_R
[reg
], var
);
183 /* Basic operations. */
184 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
185 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
188 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
190 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
191 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
193 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
194 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
195 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
196 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
197 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
199 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
200 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
201 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
203 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
204 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
205 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
207 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
208 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
210 /* Value extensions. */
211 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
212 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
213 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
214 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
216 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
217 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
219 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
221 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
222 /* Set NZCV flags from the high 4 bits of var. */
223 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
225 static void gen_exception(int excp
)
227 TCGv tmp
= new_tmp();
228 tcg_gen_movi_i32(tmp
, excp
);
229 gen_helper_exception(tmp
);
233 static void gen_smul_dual(TCGv a
, TCGv b
)
235 TCGv tmp1
= new_tmp();
236 TCGv tmp2
= new_tmp();
237 tcg_gen_ext16s_i32(tmp1
, a
);
238 tcg_gen_ext16s_i32(tmp2
, b
);
239 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
241 tcg_gen_sari_i32(a
, a
, 16);
242 tcg_gen_sari_i32(b
, b
, 16);
243 tcg_gen_mul_i32(b
, b
, a
);
244 tcg_gen_mov_i32(a
, tmp1
);
248 /* Byteswap each halfword. */
249 static void gen_rev16(TCGv var
)
251 TCGv tmp
= new_tmp();
252 tcg_gen_shri_i32(tmp
, var
, 8);
253 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
254 tcg_gen_shli_i32(var
, var
, 8);
255 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
256 tcg_gen_or_i32(var
, var
, tmp
);
260 /* Byteswap low halfword and sign extend. */
261 static void gen_revsh(TCGv var
)
263 TCGv tmp
= new_tmp();
264 tcg_gen_shri_i32(tmp
, var
, 8);
265 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
266 tcg_gen_shli_i32(var
, var
, 8);
267 tcg_gen_ext8s_i32(var
, var
);
268 tcg_gen_or_i32(var
, var
, tmp
);
272 /* Unsigned bitfield extract. */
273 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
276 tcg_gen_shri_i32(var
, var
, shift
);
277 tcg_gen_andi_i32(var
, var
, mask
);
280 /* Signed bitfield extract. */
281 static void gen_sbfx(TCGv var
, int shift
, int width
)
286 tcg_gen_sari_i32(var
, var
, shift
);
287 if (shift
+ width
< 32) {
288 signbit
= 1u << (width
- 1);
289 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
290 tcg_gen_xori_i32(var
, var
, signbit
);
291 tcg_gen_subi_i32(var
, var
, signbit
);
295 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
296 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
298 tcg_gen_andi_i32(val
, val
, mask
);
299 tcg_gen_shli_i32(val
, val
, shift
);
300 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
301 tcg_gen_or_i32(dest
, base
, val
);
304 /* Round the top 32 bits of a 64-bit value. */
305 static void gen_roundqd(TCGv a
, TCGv b
)
307 tcg_gen_shri_i32(a
, a
, 31);
308 tcg_gen_add_i32(a
, a
, b
);
311 /* FIXME: Most targets have native widening multiplication.
312 It would be good to use that instead of a full wide multiply. */
313 /* 32x32->64 multiply. Marks inputs as dead. */
314 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_extu_i32_i64(tmp1
, a
);
321 tcg_gen_extu_i32_i64(tmp2
, b
);
323 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
327 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
329 TCGv_i64 tmp1
= tcg_temp_new_i64();
330 TCGv_i64 tmp2
= tcg_temp_new_i64();
332 tcg_gen_ext_i32_i64(tmp1
, a
);
334 tcg_gen_ext_i32_i64(tmp2
, b
);
336 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
340 /* Unsigned 32x32->64 multiply. */
341 static void gen_op_mull_T0_T1(void)
343 TCGv_i64 tmp1
= tcg_temp_new_i64();
344 TCGv_i64 tmp2
= tcg_temp_new_i64();
346 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
347 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
348 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
349 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
350 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
351 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
354 /* Signed 32x32->64 multiply. */
355 static void gen_imull(TCGv a
, TCGv b
)
357 TCGv_i64 tmp1
= tcg_temp_new_i64();
358 TCGv_i64 tmp2
= tcg_temp_new_i64();
360 tcg_gen_ext_i32_i64(tmp1
, a
);
361 tcg_gen_ext_i32_i64(tmp2
, b
);
362 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
363 tcg_gen_trunc_i64_i32(a
, tmp1
);
364 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
365 tcg_gen_trunc_i64_i32(b
, tmp1
);
368 /* Swap low and high halfwords. */
369 static void gen_swap_half(TCGv var
)
371 TCGv tmp
= new_tmp();
372 tcg_gen_shri_i32(tmp
, var
, 16);
373 tcg_gen_shli_i32(var
, var
, 16);
374 tcg_gen_or_i32(var
, var
, tmp
);
378 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
379 tmp = (t0 ^ t1) & 0x8000;
382 t0 = (t0 + t1) ^ tmp;
385 static void gen_add16(TCGv t0
, TCGv t1
)
387 TCGv tmp
= new_tmp();
388 tcg_gen_xor_i32(tmp
, t0
, t1
);
389 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
390 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
391 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
392 tcg_gen_add_i32(t0
, t0
, t1
);
393 tcg_gen_xor_i32(t0
, t0
, tmp
);
398 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
400 /* Set CF to the top bit of var. */
401 static void gen_set_CF_bit31(TCGv var
)
403 TCGv tmp
= new_tmp();
404 tcg_gen_shri_i32(tmp
, var
, 31);
409 /* Set N and Z flags from var. */
410 static inline void gen_logic_CC(TCGv var
)
412 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
413 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
417 static void gen_adc_T0_T1(void)
421 tmp
= load_cpu_field(CF
);
422 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
426 /* dest = T0 + T1 + CF. */
427 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
430 tcg_gen_add_i32(dest
, t0
, t1
);
431 tmp
= load_cpu_field(CF
);
432 tcg_gen_add_i32(dest
, dest
, tmp
);
436 /* dest = T0 - T1 + CF - 1. */
437 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
440 tcg_gen_sub_i32(dest
, t0
, t1
);
441 tmp
= load_cpu_field(CF
);
442 tcg_gen_add_i32(dest
, dest
, tmp
);
443 tcg_gen_subi_i32(dest
, dest
, 1);
447 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
448 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
450 /* T0 &= ~T1. Clobbers T1. */
451 /* FIXME: Implement bic natively. */
452 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
454 TCGv tmp
= new_tmp();
455 tcg_gen_not_i32(tmp
, t1
);
456 tcg_gen_and_i32(dest
, t0
, tmp
);
459 static inline void gen_op_bicl_T0_T1(void)
465 /* FIXME: Implement this natively. */
466 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
468 /* FIXME: Implement this natively. */
469 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
477 tcg_gen_shri_i32(tmp
, t1
, i
);
478 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
479 tcg_gen_or_i32(t0
, t1
, tmp
);
483 static void shifter_out_im(TCGv var
, int shift
)
485 TCGv tmp
= new_tmp();
487 tcg_gen_andi_i32(tmp
, var
, 1);
489 tcg_gen_shri_i32(tmp
, var
, shift
);
491 tcg_gen_andi_i32(tmp
, tmp
, 1);
497 /* Shift by immediate. Includes special handling for shift == 0. */
498 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
504 shifter_out_im(var
, 32 - shift
);
505 tcg_gen_shli_i32(var
, var
, shift
);
511 tcg_gen_shri_i32(var
, var
, 31);
514 tcg_gen_movi_i32(var
, 0);
517 shifter_out_im(var
, shift
- 1);
518 tcg_gen_shri_i32(var
, var
, shift
);
525 shifter_out_im(var
, shift
- 1);
528 tcg_gen_sari_i32(var
, var
, shift
);
530 case 3: /* ROR/RRX */
533 shifter_out_im(var
, shift
- 1);
534 tcg_gen_rori_i32(var
, var
, shift
); break;
536 TCGv tmp
= load_cpu_field(CF
);
538 shifter_out_im(var
, 0);
539 tcg_gen_shri_i32(var
, var
, 1);
540 tcg_gen_shli_i32(tmp
, tmp
, 31);
541 tcg_gen_or_i32(var
, var
, tmp
);
547 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
548 TCGv shift
, int flags
)
552 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
553 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
554 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
555 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
559 case 0: gen_helper_shl(var
, var
, shift
); break;
560 case 1: gen_helper_shr(var
, var
, shift
); break;
561 case 2: gen_helper_sar(var
, var
, shift
); break;
562 case 3: gen_helper_ror(var
, var
, shift
); break;
568 #define PAS_OP(pfx) \
570 case 0: gen_pas_helper(glue(pfx,add16)); break; \
571 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
572 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
573 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
574 case 4: gen_pas_helper(glue(pfx,add8)); break; \
575 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
577 static void gen_arm_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
));
589 tmp
= tcg_temp_new_ptr();
590 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
593 #undef gen_pas_helper
594 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
607 #undef gen_pas_helper
612 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
613 #define PAS_OP(pfx) \
615 case 0: gen_pas_helper(glue(pfx,add8)); break; \
616 case 1: gen_pas_helper(glue(pfx,add16)); break; \
617 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
618 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
619 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
620 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
622 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
627 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
629 tmp
= tcg_temp_new_ptr();
630 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
634 tmp
= tcg_temp_new_ptr();
635 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
638 #undef gen_pas_helper
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
652 #undef gen_pas_helper
657 static void gen_test_cc(int cc
, int label
)
665 tmp
= load_cpu_field(ZF
);
666 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
669 tmp
= load_cpu_field(ZF
);
670 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
673 tmp
= load_cpu_field(CF
);
674 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
677 tmp
= load_cpu_field(CF
);
678 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
681 tmp
= load_cpu_field(NF
);
682 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
685 tmp
= load_cpu_field(NF
);
686 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
689 tmp
= load_cpu_field(VF
);
690 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
693 tmp
= load_cpu_field(VF
);
694 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
696 case 8: /* hi: C && !Z */
697 inv
= gen_new_label();
698 tmp
= load_cpu_field(CF
);
699 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
701 tmp
= load_cpu_field(ZF
);
702 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
705 case 9: /* ls: !C || Z */
706 tmp
= load_cpu_field(CF
);
707 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
709 tmp
= load_cpu_field(ZF
);
710 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
712 case 10: /* ge: N == V -> N ^ V == 0 */
713 tmp
= load_cpu_field(VF
);
714 tmp2
= load_cpu_field(NF
);
715 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
717 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
719 case 11: /* lt: N != V -> N ^ V != 0 */
720 tmp
= load_cpu_field(VF
);
721 tmp2
= load_cpu_field(NF
);
722 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
724 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
726 case 12: /* gt: !Z && N == V */
727 inv
= gen_new_label();
728 tmp
= load_cpu_field(ZF
);
729 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
731 tmp
= load_cpu_field(VF
);
732 tmp2
= load_cpu_field(NF
);
733 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
735 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
738 case 13: /* le: Z || N != V */
739 tmp
= load_cpu_field(ZF
);
740 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
742 tmp
= load_cpu_field(VF
);
743 tmp2
= load_cpu_field(NF
);
744 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
746 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
749 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
755 static const uint8_t table_logic_cc
[16] = {
774 /* Set PC and Thumb state from an immediate address. */
775 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
779 s
->is_jmp
= DISAS_UPDATE
;
780 if (s
->thumb
!= (addr
& 1)) {
782 tcg_gen_movi_i32(tmp
, addr
& 1);
783 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
786 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
789 /* Set PC and Thumb state from var. var is marked as dead. */
790 static inline void gen_bx(DisasContext
*s
, TCGv var
)
792 s
->is_jmp
= DISAS_UPDATE
;
793 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
794 tcg_gen_andi_i32(var
, var
, 1);
795 store_cpu_field(var
, thumb
);
798 /* Variant of store_reg which uses branch&exchange logic when storing
799 to r15 in ARM architecture v7 and above. The source must be a temporary
800 and will be marked as dead. */
801 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
804 if (reg
== 15 && ENABLE_ARCH_7
) {
807 store_reg(s
, reg
, var
);
811 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
813 TCGv tmp
= new_tmp();
814 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
817 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
819 TCGv tmp
= new_tmp();
820 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
823 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
825 TCGv tmp
= new_tmp();
826 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
829 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
831 TCGv tmp
= new_tmp();
832 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
835 static inline TCGv
gen_ld32(TCGv addr
, int index
)
837 TCGv tmp
= new_tmp();
838 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
841 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
843 tcg_gen_qemu_st8(val
, addr
, index
);
846 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
848 tcg_gen_qemu_st16(val
, addr
, index
);
851 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
853 tcg_gen_qemu_st32(val
, addr
, index
);
857 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
859 load_reg_var(s
, cpu_T
[0], reg
);
862 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
864 load_reg_var(s
, cpu_T
[1], reg
);
867 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
869 load_reg_var(s
, cpu_T
[2], reg
);
872 static inline void gen_set_pc_im(uint32_t val
)
874 tcg_gen_movi_i32(cpu_R
[15], val
);
877 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
882 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
886 tcg_gen_mov_i32(cpu_R
[reg
], tmp
);
889 s
->is_jmp
= DISAS_JUMP
;
893 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
895 gen_movl_reg_TN(s
, reg
, 0);
898 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
900 gen_movl_reg_TN(s
, reg
, 1);
903 /* Force a TB lookup after an instruction that changes the CPU state. */
904 static inline void gen_lookup_tb(DisasContext
*s
)
906 gen_op_movl_T0_im(s
->pc
);
907 gen_movl_reg_T0(s
, 15);
908 s
->is_jmp
= DISAS_UPDATE
;
911 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
914 int val
, rm
, shift
, shiftop
;
917 if (!(insn
& (1 << 25))) {
920 if (!(insn
& (1 << 23)))
923 tcg_gen_addi_i32(var
, var
, val
);
927 shift
= (insn
>> 7) & 0x1f;
928 shiftop
= (insn
>> 5) & 3;
929 offset
= load_reg(s
, rm
);
930 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
931 if (!(insn
& (1 << 23)))
932 tcg_gen_sub_i32(var
, var
, offset
);
934 tcg_gen_add_i32(var
, var
, offset
);
939 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
945 if (insn
& (1 << 22)) {
947 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
948 if (!(insn
& (1 << 23)))
952 tcg_gen_addi_i32(var
, var
, val
);
956 tcg_gen_addi_i32(var
, var
, extra
);
958 offset
= load_reg(s
, rm
);
959 if (!(insn
& (1 << 23)))
960 tcg_gen_sub_i32(var
, var
, offset
);
962 tcg_gen_add_i32(var
, var
, offset
);
967 #define VFP_OP2(name) \
968 static inline void gen_vfp_##name(int dp) \
971 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
973 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
983 static inline void gen_vfp_abs(int dp
)
986 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
988 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
991 static inline void gen_vfp_neg(int dp
)
994 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
996 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
999 static inline void gen_vfp_sqrt(int dp
)
1002 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1004 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1007 static inline void gen_vfp_cmp(int dp
)
1010 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1012 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1015 static inline void gen_vfp_cmpe(int dp
)
1018 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1020 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1023 static inline void gen_vfp_F1_ld0(int dp
)
1026 tcg_gen_movi_i64(cpu_F1d
, 0);
1028 tcg_gen_movi_i32(cpu_F1s
, 0);
1031 static inline void gen_vfp_uito(int dp
)
1034 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1036 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1039 static inline void gen_vfp_sito(int dp
)
1042 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1044 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1047 static inline void gen_vfp_toui(int dp
)
1050 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1052 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1055 static inline void gen_vfp_touiz(int dp
)
1058 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1060 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1063 static inline void gen_vfp_tosi(int dp
)
1066 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1068 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1071 static inline void gen_vfp_tosiz(int dp
)
1074 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1076 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1079 #define VFP_GEN_FIX(name) \
1080 static inline void gen_vfp_##name(int dp, int shift) \
1083 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1085 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1097 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1100 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1102 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1105 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1108 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1110 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1114 vfp_reg_offset (int dp
, int reg
)
1117 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1119 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1120 + offsetof(CPU_DoubleU
, l
.upper
);
1122 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1123 + offsetof(CPU_DoubleU
, l
.lower
);
1127 /* Return the offset of a 32-bit piece of a NEON register.
1128 zero is the least significant end of the register. */
1130 neon_reg_offset (int reg
, int n
)
1134 return vfp_reg_offset(0, sreg
);
1137 /* FIXME: Remove these. */
1138 #define neon_T0 cpu_T[0]
1139 #define neon_T1 cpu_T[1]
1140 #define NEON_GET_REG(T, reg, n) \
1141 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1142 #define NEON_SET_REG(T, reg, n) \
1143 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1145 static TCGv
neon_load_reg(int reg
, int pass
)
1147 TCGv tmp
= new_tmp();
1148 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1152 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1154 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1158 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1160 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1163 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1165 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1168 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1169 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1170 #define tcg_gen_st_f32 tcg_gen_st_i32
1171 #define tcg_gen_st_f64 tcg_gen_st_i64
1173 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1176 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1178 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1181 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1184 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1186 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1189 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1192 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1194 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1197 #define ARM_CP_RW_BIT (1 << 20)
1199 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1201 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1204 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1206 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1209 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1211 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1214 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1216 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1219 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1221 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1224 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1226 iwmmxt_store_reg(cpu_M0
, rn
);
1229 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1231 iwmmxt_load_reg(cpu_M0
, rn
);
1234 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1236 iwmmxt_load_reg(cpu_V1
, rn
);
1237 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1240 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1242 iwmmxt_load_reg(cpu_V1
, rn
);
1243 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1246 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1248 iwmmxt_load_reg(cpu_V1
, rn
);
1249 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1252 #define IWMMXT_OP(name) \
1253 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1255 iwmmxt_load_reg(cpu_V1, rn); \
1256 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1259 #define IWMMXT_OP_ENV(name) \
1260 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1262 iwmmxt_load_reg(cpu_V1, rn); \
1263 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1266 #define IWMMXT_OP_ENV_SIZE(name) \
1267 IWMMXT_OP_ENV(name##b) \
1268 IWMMXT_OP_ENV(name##w) \
1269 IWMMXT_OP_ENV(name##l)
1271 #define IWMMXT_OP_ENV1(name) \
1272 static inline void gen_op_iwmmxt_##name##_M0(void) \
1274 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1288 IWMMXT_OP_ENV_SIZE(unpackl
)
1289 IWMMXT_OP_ENV_SIZE(unpackh
)
1291 IWMMXT_OP_ENV1(unpacklub
)
1292 IWMMXT_OP_ENV1(unpackluw
)
1293 IWMMXT_OP_ENV1(unpacklul
)
1294 IWMMXT_OP_ENV1(unpackhub
)
1295 IWMMXT_OP_ENV1(unpackhuw
)
1296 IWMMXT_OP_ENV1(unpackhul
)
1297 IWMMXT_OP_ENV1(unpacklsb
)
1298 IWMMXT_OP_ENV1(unpacklsw
)
1299 IWMMXT_OP_ENV1(unpacklsl
)
1300 IWMMXT_OP_ENV1(unpackhsb
)
1301 IWMMXT_OP_ENV1(unpackhsw
)
1302 IWMMXT_OP_ENV1(unpackhsl
)
1304 IWMMXT_OP_ENV_SIZE(cmpeq
)
1305 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1306 IWMMXT_OP_ENV_SIZE(cmpgts
)
1308 IWMMXT_OP_ENV_SIZE(mins
)
1309 IWMMXT_OP_ENV_SIZE(minu
)
1310 IWMMXT_OP_ENV_SIZE(maxs
)
1311 IWMMXT_OP_ENV_SIZE(maxu
)
1313 IWMMXT_OP_ENV_SIZE(subn
)
1314 IWMMXT_OP_ENV_SIZE(addn
)
1315 IWMMXT_OP_ENV_SIZE(subu
)
1316 IWMMXT_OP_ENV_SIZE(addu
)
1317 IWMMXT_OP_ENV_SIZE(subs
)
1318 IWMMXT_OP_ENV_SIZE(adds
)
1320 IWMMXT_OP_ENV(avgb0
)
1321 IWMMXT_OP_ENV(avgb1
)
1322 IWMMXT_OP_ENV(avgw0
)
1323 IWMMXT_OP_ENV(avgw1
)
1327 IWMMXT_OP_ENV(packuw
)
1328 IWMMXT_OP_ENV(packul
)
1329 IWMMXT_OP_ENV(packuq
)
1330 IWMMXT_OP_ENV(packsw
)
1331 IWMMXT_OP_ENV(packsl
)
1332 IWMMXT_OP_ENV(packsq
)
1334 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1336 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1339 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1341 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1344 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1346 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1349 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1351 iwmmxt_load_reg(cpu_V1
, rn
);
1352 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1355 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1357 TCGv tmp
= tcg_const_i32(shift
);
1358 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1361 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1363 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1364 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1365 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1368 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1370 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1371 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1372 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1375 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1377 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1378 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1380 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1383 static void gen_op_iwmmxt_set_mup(void)
1386 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1387 tcg_gen_ori_i32(tmp
, tmp
, 2);
1388 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1391 static void gen_op_iwmmxt_set_cup(void)
1394 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1395 tcg_gen_ori_i32(tmp
, tmp
, 1);
1396 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1399 static void gen_op_iwmmxt_setpsr_nz(void)
1401 TCGv tmp
= new_tmp();
1402 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1403 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1406 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1408 iwmmxt_load_reg(cpu_V1
, rn
);
1409 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1410 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1414 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1416 iwmmxt_load_reg(cpu_V0
, rn
);
1417 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1418 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1419 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1422 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1424 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1425 iwmmxt_store_reg(cpu_V0
, rn
);
1428 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1433 rd
= (insn
>> 16) & 0xf;
1434 gen_movl_T1_reg(s
, rd
);
1436 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1437 if (insn
& (1 << 24)) {
1439 if (insn
& (1 << 23))
1440 gen_op_addl_T1_im(offset
);
1442 gen_op_addl_T1_im(-offset
);
1444 if (insn
& (1 << 21))
1445 gen_movl_reg_T1(s
, rd
);
1446 } else if (insn
& (1 << 21)) {
1448 if (insn
& (1 << 23))
1449 gen_op_movl_T0_im(offset
);
1451 gen_op_movl_T0_im(- offset
);
1452 gen_op_addl_T0_T1();
1453 gen_movl_reg_T0(s
, rd
);
1454 } else if (!(insn
& (1 << 23)))
1459 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1461 int rd
= (insn
>> 0) & 0xf;
1463 if (insn
& (1 << 8))
1464 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1467 gen_op_iwmmxt_movl_T0_wCx(rd
);
1469 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1471 gen_op_movl_T1_im(mask
);
1472 gen_op_andl_T0_T1();
1476 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1477 (ie. an undefined instruction). */
1478 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1481 int rdhi
, rdlo
, rd0
, rd1
, i
;
1484 if ((insn
& 0x0e000e00) == 0x0c000000) {
1485 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1487 rdlo
= (insn
>> 12) & 0xf;
1488 rdhi
= (insn
>> 16) & 0xf;
1489 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1490 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1491 gen_movl_reg_T0(s
, rdlo
);
1492 gen_movl_reg_T1(s
, rdhi
);
1493 } else { /* TMCRR */
1494 gen_movl_T0_reg(s
, rdlo
);
1495 gen_movl_T1_reg(s
, rdhi
);
1496 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1497 gen_op_iwmmxt_set_mup();
1502 wrd
= (insn
>> 12) & 0xf;
1503 if (gen_iwmmxt_address(s
, insn
))
1505 if (insn
& ARM_CP_RW_BIT
) {
1506 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1507 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1508 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1510 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1513 if (insn
& (1 << 8)) {
1514 if (insn
& (1 << 22)) { /* WLDRD */
1515 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1517 } else { /* WLDRW wRd */
1518 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1521 if (insn
& (1 << 22)) { /* WLDRH */
1522 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1523 } else { /* WLDRB */
1524 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1528 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1531 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1534 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1535 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1537 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1538 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1540 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1542 if (insn
& (1 << 8)) {
1543 if (insn
& (1 << 22)) { /* WSTRD */
1545 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1546 } else { /* WSTRW wRd */
1547 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1548 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1551 if (insn
& (1 << 22)) { /* WSTRH */
1552 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1553 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1554 } else { /* WSTRB */
1555 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1556 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1564 if ((insn
& 0x0f000000) != 0x0e000000)
1567 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1568 case 0x000: /* WOR */
1569 wrd
= (insn
>> 12) & 0xf;
1570 rd0
= (insn
>> 0) & 0xf;
1571 rd1
= (insn
>> 16) & 0xf;
1572 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1573 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1574 gen_op_iwmmxt_setpsr_nz();
1575 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1576 gen_op_iwmmxt_set_mup();
1577 gen_op_iwmmxt_set_cup();
1579 case 0x011: /* TMCR */
1582 rd
= (insn
>> 12) & 0xf;
1583 wrd
= (insn
>> 16) & 0xf;
1585 case ARM_IWMMXT_wCID
:
1586 case ARM_IWMMXT_wCASF
:
1588 case ARM_IWMMXT_wCon
:
1589 gen_op_iwmmxt_set_cup();
1591 case ARM_IWMMXT_wCSSF
:
1592 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1593 gen_movl_T1_reg(s
, rd
);
1594 gen_op_bicl_T0_T1();
1595 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1597 case ARM_IWMMXT_wCGR0
:
1598 case ARM_IWMMXT_wCGR1
:
1599 case ARM_IWMMXT_wCGR2
:
1600 case ARM_IWMMXT_wCGR3
:
1601 gen_op_iwmmxt_set_cup();
1602 gen_movl_reg_T0(s
, rd
);
1603 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1609 case 0x100: /* WXOR */
1610 wrd
= (insn
>> 12) & 0xf;
1611 rd0
= (insn
>> 0) & 0xf;
1612 rd1
= (insn
>> 16) & 0xf;
1613 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1614 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1615 gen_op_iwmmxt_setpsr_nz();
1616 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1617 gen_op_iwmmxt_set_mup();
1618 gen_op_iwmmxt_set_cup();
1620 case 0x111: /* TMRC */
1623 rd
= (insn
>> 12) & 0xf;
1624 wrd
= (insn
>> 16) & 0xf;
1625 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1626 gen_movl_reg_T0(s
, rd
);
1628 case 0x300: /* WANDN */
1629 wrd
= (insn
>> 12) & 0xf;
1630 rd0
= (insn
>> 0) & 0xf;
1631 rd1
= (insn
>> 16) & 0xf;
1632 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1633 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1634 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1635 gen_op_iwmmxt_setpsr_nz();
1636 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1637 gen_op_iwmmxt_set_mup();
1638 gen_op_iwmmxt_set_cup();
1640 case 0x200: /* WAND */
1641 wrd
= (insn
>> 12) & 0xf;
1642 rd0
= (insn
>> 0) & 0xf;
1643 rd1
= (insn
>> 16) & 0xf;
1644 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1645 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1646 gen_op_iwmmxt_setpsr_nz();
1647 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1648 gen_op_iwmmxt_set_mup();
1649 gen_op_iwmmxt_set_cup();
1651 case 0x810: case 0xa10: /* WMADD */
1652 wrd
= (insn
>> 12) & 0xf;
1653 rd0
= (insn
>> 0) & 0xf;
1654 rd1
= (insn
>> 16) & 0xf;
1655 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1656 if (insn
& (1 << 21))
1657 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1659 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1660 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1661 gen_op_iwmmxt_set_mup();
1663 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1664 wrd
= (insn
>> 12) & 0xf;
1665 rd0
= (insn
>> 16) & 0xf;
1666 rd1
= (insn
>> 0) & 0xf;
1667 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1668 switch ((insn
>> 22) & 3) {
1670 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1673 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1676 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1681 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1682 gen_op_iwmmxt_set_mup();
1683 gen_op_iwmmxt_set_cup();
1685 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1686 wrd
= (insn
>> 12) & 0xf;
1687 rd0
= (insn
>> 16) & 0xf;
1688 rd1
= (insn
>> 0) & 0xf;
1689 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1690 switch ((insn
>> 22) & 3) {
1692 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1695 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1698 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1703 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1704 gen_op_iwmmxt_set_mup();
1705 gen_op_iwmmxt_set_cup();
1707 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1708 wrd
= (insn
>> 12) & 0xf;
1709 rd0
= (insn
>> 16) & 0xf;
1710 rd1
= (insn
>> 0) & 0xf;
1711 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1712 if (insn
& (1 << 22))
1713 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1715 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1716 if (!(insn
& (1 << 20)))
1717 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1718 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1719 gen_op_iwmmxt_set_mup();
1721 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1722 wrd
= (insn
>> 12) & 0xf;
1723 rd0
= (insn
>> 16) & 0xf;
1724 rd1
= (insn
>> 0) & 0xf;
1725 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1726 if (insn
& (1 << 21)) {
1727 if (insn
& (1 << 20))
1728 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1730 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1732 if (insn
& (1 << 20))
1733 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1735 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1737 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1738 gen_op_iwmmxt_set_mup();
1740 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1741 wrd
= (insn
>> 12) & 0xf;
1742 rd0
= (insn
>> 16) & 0xf;
1743 rd1
= (insn
>> 0) & 0xf;
1744 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1745 if (insn
& (1 << 21))
1746 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1748 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1749 if (!(insn
& (1 << 20))) {
1750 iwmmxt_load_reg(cpu_V1
, wrd
);
1751 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1753 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1754 gen_op_iwmmxt_set_mup();
1756 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1757 wrd
= (insn
>> 12) & 0xf;
1758 rd0
= (insn
>> 16) & 0xf;
1759 rd1
= (insn
>> 0) & 0xf;
1760 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1761 switch ((insn
>> 22) & 3) {
1763 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1766 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1769 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1774 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1775 gen_op_iwmmxt_set_mup();
1776 gen_op_iwmmxt_set_cup();
1778 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1779 wrd
= (insn
>> 12) & 0xf;
1780 rd0
= (insn
>> 16) & 0xf;
1781 rd1
= (insn
>> 0) & 0xf;
1782 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1783 if (insn
& (1 << 22)) {
1784 if (insn
& (1 << 20))
1785 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1787 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1789 if (insn
& (1 << 20))
1790 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1792 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1794 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1795 gen_op_iwmmxt_set_mup();
1796 gen_op_iwmmxt_set_cup();
1798 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1799 wrd
= (insn
>> 12) & 0xf;
1800 rd0
= (insn
>> 16) & 0xf;
1801 rd1
= (insn
>> 0) & 0xf;
1802 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1803 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1804 gen_op_movl_T1_im(7);
1805 gen_op_andl_T0_T1();
1806 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1807 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1808 gen_op_iwmmxt_set_mup();
1810 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1811 rd
= (insn
>> 12) & 0xf;
1812 wrd
= (insn
>> 16) & 0xf;
1813 gen_movl_T0_reg(s
, rd
);
1814 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1815 switch ((insn
>> 6) & 3) {
1817 gen_op_movl_T1_im(0xff);
1818 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1821 gen_op_movl_T1_im(0xffff);
1822 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1825 gen_op_movl_T1_im(0xffffffff);
1826 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1831 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1832 gen_op_iwmmxt_set_mup();
1834 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1835 rd
= (insn
>> 12) & 0xf;
1836 wrd
= (insn
>> 16) & 0xf;
1839 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1840 switch ((insn
>> 22) & 3) {
1843 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1845 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1850 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1852 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1856 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1861 gen_movl_reg_T0(s
, rd
);
1863 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1864 if ((insn
& 0x000ff008) != 0x0003f000)
1866 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1867 switch ((insn
>> 22) & 3) {
1869 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1872 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1875 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1880 gen_op_shll_T1_im(28);
1881 gen_set_nzcv(cpu_T
[1]);
1883 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1884 rd
= (insn
>> 12) & 0xf;
1885 wrd
= (insn
>> 16) & 0xf;
1886 gen_movl_T0_reg(s
, rd
);
1887 switch ((insn
>> 6) & 3) {
1889 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1892 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1895 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1900 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1901 gen_op_iwmmxt_set_mup();
1903 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1904 if ((insn
& 0x000ff00f) != 0x0003f000)
1906 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1907 switch ((insn
>> 22) & 3) {
1909 for (i
= 0; i
< 7; i
++) {
1910 gen_op_shll_T1_im(4);
1911 gen_op_andl_T0_T1();
1915 for (i
= 0; i
< 3; i
++) {
1916 gen_op_shll_T1_im(8);
1917 gen_op_andl_T0_T1();
1921 gen_op_shll_T1_im(16);
1922 gen_op_andl_T0_T1();
1927 gen_set_nzcv(cpu_T
[0]);
1929 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1930 wrd
= (insn
>> 12) & 0xf;
1931 rd0
= (insn
>> 16) & 0xf;
1932 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1933 switch ((insn
>> 22) & 3) {
1935 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1938 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1941 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1946 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1947 gen_op_iwmmxt_set_mup();
1949 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1950 if ((insn
& 0x000ff00f) != 0x0003f000)
1952 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1953 switch ((insn
>> 22) & 3) {
1955 for (i
= 0; i
< 7; i
++) {
1956 gen_op_shll_T1_im(4);
1961 for (i
= 0; i
< 3; i
++) {
1962 gen_op_shll_T1_im(8);
1967 gen_op_shll_T1_im(16);
1973 gen_set_nzcv(cpu_T
[0]);
1975 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1976 rd
= (insn
>> 12) & 0xf;
1977 rd0
= (insn
>> 16) & 0xf;
1978 if ((insn
& 0xf) != 0)
1980 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1981 switch ((insn
>> 22) & 3) {
1983 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
1986 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
1989 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
1994 gen_movl_reg_T0(s
, rd
);
1996 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1997 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1998 wrd
= (insn
>> 12) & 0xf;
1999 rd0
= (insn
>> 16) & 0xf;
2000 rd1
= (insn
>> 0) & 0xf;
2001 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2002 switch ((insn
>> 22) & 3) {
2004 if (insn
& (1 << 21))
2005 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2007 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2010 if (insn
& (1 << 21))
2011 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2013 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2016 if (insn
& (1 << 21))
2017 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2019 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2024 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2025 gen_op_iwmmxt_set_mup();
2026 gen_op_iwmmxt_set_cup();
2028 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2029 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2030 wrd
= (insn
>> 12) & 0xf;
2031 rd0
= (insn
>> 16) & 0xf;
2032 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2033 switch ((insn
>> 22) & 3) {
2035 if (insn
& (1 << 21))
2036 gen_op_iwmmxt_unpacklsb_M0();
2038 gen_op_iwmmxt_unpacklub_M0();
2041 if (insn
& (1 << 21))
2042 gen_op_iwmmxt_unpacklsw_M0();
2044 gen_op_iwmmxt_unpackluw_M0();
2047 if (insn
& (1 << 21))
2048 gen_op_iwmmxt_unpacklsl_M0();
2050 gen_op_iwmmxt_unpacklul_M0();
2055 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2056 gen_op_iwmmxt_set_mup();
2057 gen_op_iwmmxt_set_cup();
2059 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2060 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2061 wrd
= (insn
>> 12) & 0xf;
2062 rd0
= (insn
>> 16) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2064 switch ((insn
>> 22) & 3) {
2066 if (insn
& (1 << 21))
2067 gen_op_iwmmxt_unpackhsb_M0();
2069 gen_op_iwmmxt_unpackhub_M0();
2072 if (insn
& (1 << 21))
2073 gen_op_iwmmxt_unpackhsw_M0();
2075 gen_op_iwmmxt_unpackhuw_M0();
2078 if (insn
& (1 << 21))
2079 gen_op_iwmmxt_unpackhsl_M0();
2081 gen_op_iwmmxt_unpackhul_M0();
2086 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2087 gen_op_iwmmxt_set_mup();
2088 gen_op_iwmmxt_set_cup();
2090 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2091 case 0x214: case 0x614: case 0xa14: case 0xe14:
2092 wrd
= (insn
>> 12) & 0xf;
2093 rd0
= (insn
>> 16) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2095 if (gen_iwmmxt_shift(insn
, 0xff))
2097 switch ((insn
>> 22) & 3) {
2101 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2104 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2107 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2110 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2111 gen_op_iwmmxt_set_mup();
2112 gen_op_iwmmxt_set_cup();
2114 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2115 case 0x014: case 0x414: case 0x814: case 0xc14:
2116 wrd
= (insn
>> 12) & 0xf;
2117 rd0
= (insn
>> 16) & 0xf;
2118 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2119 if (gen_iwmmxt_shift(insn
, 0xff))
2121 switch ((insn
>> 22) & 3) {
2125 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2128 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2131 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2134 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2135 gen_op_iwmmxt_set_mup();
2136 gen_op_iwmmxt_set_cup();
2138 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2139 case 0x114: case 0x514: case 0x914: case 0xd14:
2140 wrd
= (insn
>> 12) & 0xf;
2141 rd0
= (insn
>> 16) & 0xf;
2142 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2143 if (gen_iwmmxt_shift(insn
, 0xff))
2145 switch ((insn
>> 22) & 3) {
2149 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2152 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2155 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2158 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2159 gen_op_iwmmxt_set_mup();
2160 gen_op_iwmmxt_set_cup();
2162 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2163 case 0x314: case 0x714: case 0xb14: case 0xf14:
2164 wrd
= (insn
>> 12) & 0xf;
2165 rd0
= (insn
>> 16) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2167 switch ((insn
>> 22) & 3) {
2171 if (gen_iwmmxt_shift(insn
, 0xf))
2173 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2176 if (gen_iwmmxt_shift(insn
, 0x1f))
2178 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2181 if (gen_iwmmxt_shift(insn
, 0x3f))
2183 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2186 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2187 gen_op_iwmmxt_set_mup();
2188 gen_op_iwmmxt_set_cup();
2190 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2191 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2192 wrd
= (insn
>> 12) & 0xf;
2193 rd0
= (insn
>> 16) & 0xf;
2194 rd1
= (insn
>> 0) & 0xf;
2195 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2196 switch ((insn
>> 22) & 3) {
2198 if (insn
& (1 << 21))
2199 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2201 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2204 if (insn
& (1 << 21))
2205 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2207 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2210 if (insn
& (1 << 21))
2211 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2213 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2218 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2219 gen_op_iwmmxt_set_mup();
2221 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2222 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2223 wrd
= (insn
>> 12) & 0xf;
2224 rd0
= (insn
>> 16) & 0xf;
2225 rd1
= (insn
>> 0) & 0xf;
2226 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2227 switch ((insn
>> 22) & 3) {
2229 if (insn
& (1 << 21))
2230 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2232 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2235 if (insn
& (1 << 21))
2236 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2238 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2241 if (insn
& (1 << 21))
2242 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2244 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2249 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2250 gen_op_iwmmxt_set_mup();
2252 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2253 case 0x402: case 0x502: case 0x602: case 0x702:
2254 wrd
= (insn
>> 12) & 0xf;
2255 rd0
= (insn
>> 16) & 0xf;
2256 rd1
= (insn
>> 0) & 0xf;
2257 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2258 gen_op_movl_T0_im((insn
>> 20) & 3);
2259 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2260 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2261 gen_op_iwmmxt_set_mup();
2263 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2264 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2265 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2266 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2267 wrd
= (insn
>> 12) & 0xf;
2268 rd0
= (insn
>> 16) & 0xf;
2269 rd1
= (insn
>> 0) & 0xf;
2270 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2271 switch ((insn
>> 20) & 0xf) {
2273 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2276 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2279 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2282 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2285 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2288 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2291 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2294 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2297 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2302 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2303 gen_op_iwmmxt_set_mup();
2304 gen_op_iwmmxt_set_cup();
2306 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2307 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2308 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2309 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2310 wrd
= (insn
>> 12) & 0xf;
2311 rd0
= (insn
>> 16) & 0xf;
2312 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2313 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2314 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2315 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2316 gen_op_iwmmxt_set_mup();
2317 gen_op_iwmmxt_set_cup();
2319 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2320 case 0x418: case 0x518: case 0x618: case 0x718:
2321 case 0x818: case 0x918: case 0xa18: case 0xb18:
2322 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2323 wrd
= (insn
>> 12) & 0xf;
2324 rd0
= (insn
>> 16) & 0xf;
2325 rd1
= (insn
>> 0) & 0xf;
2326 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2327 switch ((insn
>> 20) & 0xf) {
2329 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2332 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2335 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2338 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2341 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2344 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2347 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2350 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2353 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2358 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2359 gen_op_iwmmxt_set_mup();
2360 gen_op_iwmmxt_set_cup();
2362 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2363 case 0x408: case 0x508: case 0x608: case 0x708:
2364 case 0x808: case 0x908: case 0xa08: case 0xb08:
2365 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2366 wrd
= (insn
>> 12) & 0xf;
2367 rd0
= (insn
>> 16) & 0xf;
2368 rd1
= (insn
>> 0) & 0xf;
2369 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2370 if (!(insn
& (1 << 20)))
2372 switch ((insn
>> 22) & 3) {
2376 if (insn
& (1 << 21))
2377 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2379 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2382 if (insn
& (1 << 21))
2383 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2385 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2388 if (insn
& (1 << 21))
2389 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2391 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2394 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2395 gen_op_iwmmxt_set_mup();
2396 gen_op_iwmmxt_set_cup();
2398 case 0x201: case 0x203: case 0x205: case 0x207:
2399 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2400 case 0x211: case 0x213: case 0x215: case 0x217:
2401 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2402 wrd
= (insn
>> 5) & 0xf;
2403 rd0
= (insn
>> 12) & 0xf;
2404 rd1
= (insn
>> 0) & 0xf;
2405 if (rd0
== 0xf || rd1
== 0xf)
2407 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2408 switch ((insn
>> 16) & 0xf) {
2409 case 0x0: /* TMIA */
2410 gen_movl_T0_reg(s
, rd0
);
2411 gen_movl_T1_reg(s
, rd1
);
2412 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2414 case 0x8: /* TMIAPH */
2415 gen_movl_T0_reg(s
, rd0
);
2416 gen_movl_T1_reg(s
, rd1
);
2417 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2419 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2420 gen_movl_T1_reg(s
, rd0
);
2421 if (insn
& (1 << 16))
2422 gen_op_shrl_T1_im(16);
2423 gen_op_movl_T0_T1();
2424 gen_movl_T1_reg(s
, rd1
);
2425 if (insn
& (1 << 17))
2426 gen_op_shrl_T1_im(16);
2427 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2432 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2433 gen_op_iwmmxt_set_mup();
2442 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2443 (ie. an undefined instruction). */
2444 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2446 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2448 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2449 /* Multiply with Internal Accumulate Format */
2450 rd0
= (insn
>> 12) & 0xf;
2452 acc
= (insn
>> 5) & 7;
2457 switch ((insn
>> 16) & 0xf) {
2459 gen_movl_T0_reg(s
, rd0
);
2460 gen_movl_T1_reg(s
, rd1
);
2461 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2463 case 0x8: /* MIAPH */
2464 gen_movl_T0_reg(s
, rd0
);
2465 gen_movl_T1_reg(s
, rd1
);
2466 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2468 case 0xc: /* MIABB */
2469 case 0xd: /* MIABT */
2470 case 0xe: /* MIATB */
2471 case 0xf: /* MIATT */
2472 gen_movl_T1_reg(s
, rd0
);
2473 if (insn
& (1 << 16))
2474 gen_op_shrl_T1_im(16);
2475 gen_op_movl_T0_T1();
2476 gen_movl_T1_reg(s
, rd1
);
2477 if (insn
& (1 << 17))
2478 gen_op_shrl_T1_im(16);
2479 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2485 gen_op_iwmmxt_movq_wRn_M0(acc
);
2489 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2490 /* Internal Accumulator Access Format */
2491 rdhi
= (insn
>> 16) & 0xf;
2492 rdlo
= (insn
>> 12) & 0xf;
2498 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2499 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2500 gen_movl_reg_T0(s
, rdlo
);
2501 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2502 gen_op_andl_T0_T1();
2503 gen_movl_reg_T0(s
, rdhi
);
2505 gen_movl_T0_reg(s
, rdlo
);
2506 gen_movl_T1_reg(s
, rdhi
);
2507 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2515 /* Disassemble system coprocessor instruction. Return nonzero if
2516 instruction is not defined. */
2517 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2520 uint32_t rd
= (insn
>> 12) & 0xf;
2521 uint32_t cp
= (insn
>> 8) & 0xf;
2526 if (insn
& ARM_CP_RW_BIT
) {
2527 if (!env
->cp
[cp
].cp_read
)
2529 gen_set_pc_im(s
->pc
);
2531 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2532 store_reg(s
, rd
, tmp
);
2534 if (!env
->cp
[cp
].cp_write
)
2536 gen_set_pc_im(s
->pc
);
2537 tmp
= load_reg(s
, rd
);
2538 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2544 static int cp15_user_ok(uint32_t insn
)
2546 int cpn
= (insn
>> 16) & 0xf;
2547 int cpm
= insn
& 0xf;
2548 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2550 if (cpn
== 13 && cpm
== 0) {
2552 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2556 /* ISB, DSB, DMB. */
2557 if ((cpm
== 5 && op
== 4)
2558 || (cpm
== 10 && (op
== 4 || op
== 5)))
2564 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2565 instruction is not defined. */
2566 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2571 /* M profile cores use memory mapped registers instead of cp15. */
2572 if (arm_feature(env
, ARM_FEATURE_M
))
2575 if ((insn
& (1 << 25)) == 0) {
2576 if (insn
& (1 << 20)) {
2580 /* mcrr. Used for block cache operations, so implement as no-op. */
2583 if ((insn
& (1 << 4)) == 0) {
2587 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2590 if ((insn
& 0x0fff0fff) == 0x0e070f90
2591 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2592 /* Wait for interrupt. */
2593 gen_set_pc_im(s
->pc
);
2594 s
->is_jmp
= DISAS_WFI
;
2597 rd
= (insn
>> 12) & 0xf;
2598 if (insn
& ARM_CP_RW_BIT
) {
2600 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2601 /* If the destination register is r15 then sets condition codes. */
2603 store_reg(s
, rd
, tmp
);
2607 tmp
= load_reg(s
, rd
);
2608 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2610 /* Normally we would always end the TB here, but Linux
2611 * arch/arm/mach-pxa/sleep.S expects two instructions following
2612 * an MMU enable to execute from cache. Imitate this behaviour. */
2613 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2614 (insn
& 0x0fff0fff) != 0x0e010f10)
2620 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2621 #define VFP_SREG(insn, bigbit, smallbit) \
2622 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2623 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2624 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2625 reg = (((insn) >> (bigbit)) & 0x0f) \
2626 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2628 if (insn & (1 << (smallbit))) \
2630 reg = ((insn) >> (bigbit)) & 0x0f; \
2633 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2634 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2635 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2636 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2637 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2638 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2640 /* Move between integer and VFP cores. */
2641 static TCGv
gen_vfp_mrs(void)
2643 TCGv tmp
= new_tmp();
2644 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2648 static void gen_vfp_msr(TCGv tmp
)
2650 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2655 vfp_enabled(CPUState
* env
)
2657 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2660 static void gen_neon_dup_u8(TCGv var
, int shift
)
2662 TCGv tmp
= new_tmp();
2664 tcg_gen_shri_i32(var
, var
, shift
);
2665 tcg_gen_ext8u_i32(var
, var
);
2666 tcg_gen_shli_i32(tmp
, var
, 8);
2667 tcg_gen_or_i32(var
, var
, tmp
);
2668 tcg_gen_shli_i32(tmp
, var
, 16);
2669 tcg_gen_or_i32(var
, var
, tmp
);
2673 static void gen_neon_dup_low16(TCGv var
)
2675 TCGv tmp
= new_tmp();
2676 tcg_gen_ext16u_i32(var
, var
);
2677 tcg_gen_shli_i32(tmp
, var
, 16);
2678 tcg_gen_or_i32(var
, var
, tmp
);
2682 static void gen_neon_dup_high16(TCGv var
)
2684 TCGv tmp
= new_tmp();
2685 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2686 tcg_gen_shri_i32(tmp
, var
, 16);
2687 tcg_gen_or_i32(var
, var
, tmp
);
2691 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2692 (ie. an undefined instruction). */
2693 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2695 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2700 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2703 if (!vfp_enabled(env
)) {
2704 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2705 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2707 rn
= (insn
>> 16) & 0xf;
2708 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2709 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2712 dp
= ((insn
& 0xf00) == 0xb00);
2713 switch ((insn
>> 24) & 0xf) {
2715 if (insn
& (1 << 4)) {
2716 /* single register transfer */
2717 rd
= (insn
>> 12) & 0xf;
2722 VFP_DREG_N(rn
, insn
);
2725 if (insn
& 0x00c00060
2726 && !arm_feature(env
, ARM_FEATURE_NEON
))
2729 pass
= (insn
>> 21) & 1;
2730 if (insn
& (1 << 22)) {
2732 offset
= ((insn
>> 5) & 3) * 8;
2733 } else if (insn
& (1 << 5)) {
2735 offset
= (insn
& (1 << 6)) ? 16 : 0;
2740 if (insn
& ARM_CP_RW_BIT
) {
2742 tmp
= neon_load_reg(rn
, pass
);
2746 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2747 if (insn
& (1 << 23))
2753 if (insn
& (1 << 23)) {
2755 tcg_gen_shri_i32(tmp
, tmp
, 16);
2761 tcg_gen_sari_i32(tmp
, tmp
, 16);
2770 store_reg(s
, rd
, tmp
);
2773 tmp
= load_reg(s
, rd
);
2774 if (insn
& (1 << 23)) {
2777 gen_neon_dup_u8(tmp
, 0);
2778 } else if (size
== 1) {
2779 gen_neon_dup_low16(tmp
);
2781 for (n
= 0; n
<= pass
* 2; n
++) {
2783 tcg_gen_mov_i32(tmp2
, tmp
);
2784 neon_store_reg(rn
, n
, tmp2
);
2786 neon_store_reg(rn
, n
, tmp
);
2791 tmp2
= neon_load_reg(rn
, pass
);
2792 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2796 tmp2
= neon_load_reg(rn
, pass
);
2797 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2803 neon_store_reg(rn
, pass
, tmp
);
2807 if ((insn
& 0x6f) != 0x00)
2809 rn
= VFP_SREG_N(insn
);
2810 if (insn
& ARM_CP_RW_BIT
) {
2812 if (insn
& (1 << 21)) {
2813 /* system register */
2818 /* VFP2 allows access to FSID from userspace.
2819 VFP3 restricts all id registers to privileged
2822 && arm_feature(env
, ARM_FEATURE_VFP3
))
2824 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2829 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2831 case ARM_VFP_FPINST
:
2832 case ARM_VFP_FPINST2
:
2833 /* Not present in VFP3. */
2835 || arm_feature(env
, ARM_FEATURE_VFP3
))
2837 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2841 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2842 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2845 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2851 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2853 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2859 gen_mov_F0_vreg(0, rn
);
2860 tmp
= gen_vfp_mrs();
2863 /* Set the 4 flag bits in the CPSR. */
2867 store_reg(s
, rd
, tmp
);
2871 tmp
= load_reg(s
, rd
);
2872 if (insn
& (1 << 21)) {
2874 /* system register */
2879 /* Writes are ignored. */
2882 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2889 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2892 case ARM_VFP_FPINST
:
2893 case ARM_VFP_FPINST2
:
2894 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2901 gen_mov_vreg_F0(0, rn
);
2906 /* data processing */
2907 /* The opcode is in bits 23, 21, 20 and 6. */
2908 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2912 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2914 /* rn is register number */
2915 VFP_DREG_N(rn
, insn
);
2918 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2919 /* Integer or single precision destination. */
2920 rd
= VFP_SREG_D(insn
);
2922 VFP_DREG_D(rd
, insn
);
2925 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2926 /* Integer source. */
2927 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2929 VFP_DREG_M(rm
, insn
);
2932 rn
= VFP_SREG_N(insn
);
2933 if (op
== 15 && rn
== 15) {
2934 /* Double precision destination. */
2935 VFP_DREG_D(rd
, insn
);
2937 rd
= VFP_SREG_D(insn
);
2939 rm
= VFP_SREG_M(insn
);
2942 veclen
= env
->vfp
.vec_len
;
2943 if (op
== 15 && rn
> 3)
2946 /* Shut up compiler warnings. */
2957 /* Figure out what type of vector operation this is. */
2958 if ((rd
& bank_mask
) == 0) {
2963 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2965 delta_d
= env
->vfp
.vec_stride
+ 1;
2967 if ((rm
& bank_mask
) == 0) {
2968 /* mixed scalar/vector */
2977 /* Load the initial operands. */
2982 /* Integer source */
2983 gen_mov_F0_vreg(0, rm
);
2988 gen_mov_F0_vreg(dp
, rd
);
2989 gen_mov_F1_vreg(dp
, rm
);
2993 /* Compare with zero */
2994 gen_mov_F0_vreg(dp
, rd
);
3005 /* Source and destination the same. */
3006 gen_mov_F0_vreg(dp
, rd
);
3009 /* One source operand. */
3010 gen_mov_F0_vreg(dp
, rm
);
3014 /* Two source operands. */
3015 gen_mov_F0_vreg(dp
, rn
);
3016 gen_mov_F1_vreg(dp
, rm
);
3020 /* Perform the calculation. */
3022 case 0: /* mac: fd + (fn * fm) */
3024 gen_mov_F1_vreg(dp
, rd
);
3027 case 1: /* nmac: fd - (fn * fm) */
3030 gen_mov_F1_vreg(dp
, rd
);
3033 case 2: /* msc: -fd + (fn * fm) */
3035 gen_mov_F1_vreg(dp
, rd
);
3038 case 3: /* nmsc: -fd - (fn * fm) */
3041 gen_mov_F1_vreg(dp
, rd
);
3044 case 4: /* mul: fn * fm */
3047 case 5: /* nmul: -(fn * fm) */
3051 case 6: /* add: fn + fm */
3054 case 7: /* sub: fn - fm */
3057 case 8: /* div: fn / fm */
3060 case 14: /* fconst */
3061 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3064 n
= (insn
<< 12) & 0x80000000;
3065 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3072 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3079 tcg_gen_movi_i32(cpu_F0s
, n
);
3082 case 15: /* extension space */
3105 case 11: /* cmpez */
3109 case 15: /* single<->double conversion */
3111 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3113 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3115 case 16: /* fuito */
3118 case 17: /* fsito */
3121 case 20: /* fshto */
3122 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3124 gen_vfp_shto(dp
, 16 - rm
);
3126 case 21: /* fslto */
3127 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3129 gen_vfp_slto(dp
, 32 - rm
);
3131 case 22: /* fuhto */
3132 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3134 gen_vfp_uhto(dp
, 16 - rm
);
3136 case 23: /* fulto */
3137 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3139 gen_vfp_ulto(dp
, 32 - rm
);
3141 case 24: /* ftoui */
3144 case 25: /* ftouiz */
3147 case 26: /* ftosi */
3150 case 27: /* ftosiz */
3153 case 28: /* ftosh */
3154 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3156 gen_vfp_tosh(dp
, 16 - rm
);
3158 case 29: /* ftosl */
3159 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3161 gen_vfp_tosl(dp
, 32 - rm
);
3163 case 30: /* ftouh */
3164 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3166 gen_vfp_touh(dp
, 16 - rm
);
3168 case 31: /* ftoul */
3169 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3171 gen_vfp_toul(dp
, 32 - rm
);
3173 default: /* undefined */
3174 printf ("rn:%d\n", rn
);
3178 default: /* undefined */
3179 printf ("op:%d\n", op
);
3183 /* Write back the result. */
3184 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3185 ; /* Comparison, do nothing. */
3186 else if (op
== 15 && rn
> 17)
3187 /* Integer result. */
3188 gen_mov_vreg_F0(0, rd
);
3189 else if (op
== 15 && rn
== 15)
3191 gen_mov_vreg_F0(!dp
, rd
);
3193 gen_mov_vreg_F0(dp
, rd
);
3195 /* break out of the loop if we have finished */
3199 if (op
== 15 && delta_m
== 0) {
3200 /* single source one-many */
3202 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3204 gen_mov_vreg_F0(dp
, rd
);
3208 /* Setup the next operands. */
3210 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3214 /* One source operand. */
3215 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3217 gen_mov_F0_vreg(dp
, rm
);
3219 /* Two source operands. */
3220 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3222 gen_mov_F0_vreg(dp
, rn
);
3224 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3226 gen_mov_F1_vreg(dp
, rm
);
3234 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3235 /* two-register transfer */
3236 rn
= (insn
>> 16) & 0xf;
3237 rd
= (insn
>> 12) & 0xf;
3239 VFP_DREG_M(rm
, insn
);
3241 rm
= VFP_SREG_M(insn
);
3244 if (insn
& ARM_CP_RW_BIT
) {
3247 gen_mov_F0_vreg(0, rm
* 2);
3248 tmp
= gen_vfp_mrs();
3249 store_reg(s
, rd
, tmp
);
3250 gen_mov_F0_vreg(0, rm
* 2 + 1);
3251 tmp
= gen_vfp_mrs();
3252 store_reg(s
, rn
, tmp
);
3254 gen_mov_F0_vreg(0, rm
);
3255 tmp
= gen_vfp_mrs();
3256 store_reg(s
, rn
, tmp
);
3257 gen_mov_F0_vreg(0, rm
+ 1);
3258 tmp
= gen_vfp_mrs();
3259 store_reg(s
, rd
, tmp
);
3264 tmp
= load_reg(s
, rd
);
3266 gen_mov_vreg_F0(0, rm
* 2);
3267 tmp
= load_reg(s
, rn
);
3269 gen_mov_vreg_F0(0, rm
* 2 + 1);
3271 tmp
= load_reg(s
, rn
);
3273 gen_mov_vreg_F0(0, rm
);
3274 tmp
= load_reg(s
, rd
);
3276 gen_mov_vreg_F0(0, rm
+ 1);
3281 rn
= (insn
>> 16) & 0xf;
3283 VFP_DREG_D(rd
, insn
);
3285 rd
= VFP_SREG_D(insn
);
3286 if (s
->thumb
&& rn
== 15) {
3287 gen_op_movl_T1_im(s
->pc
& ~2);
3289 gen_movl_T1_reg(s
, rn
);
3291 if ((insn
& 0x01200000) == 0x01000000) {
3292 /* Single load/store */
3293 offset
= (insn
& 0xff) << 2;
3294 if ((insn
& (1 << 23)) == 0)
3296 gen_op_addl_T1_im(offset
);
3297 if (insn
& (1 << 20)) {
3299 gen_mov_vreg_F0(dp
, rd
);
3301 gen_mov_F0_vreg(dp
, rd
);
3305 /* load/store multiple */
3307 n
= (insn
>> 1) & 0x7f;
3311 if (insn
& (1 << 24)) /* pre-decrement */
3312 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3318 for (i
= 0; i
< n
; i
++) {
3319 if (insn
& ARM_CP_RW_BIT
) {
3322 gen_mov_vreg_F0(dp
, rd
+ i
);
3325 gen_mov_F0_vreg(dp
, rd
+ i
);
3328 gen_op_addl_T1_im(offset
);
3330 if (insn
& (1 << 21)) {
3332 if (insn
& (1 << 24))
3333 offset
= -offset
* n
;
3334 else if (dp
&& (insn
& 1))
3340 gen_op_addl_T1_im(offset
);
3341 gen_movl_reg_T1(s
, rn
);
3347 /* Should never happen. */
3353 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3355 TranslationBlock
*tb
;
3358 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3360 gen_set_pc_im(dest
);
3361 tcg_gen_exit_tb((long)tb
+ n
);
3363 gen_set_pc_im(dest
);
3368 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3370 if (unlikely(s
->singlestep_enabled
)) {
3371 /* An indirect jump so that we still trigger the debug exception. */
3376 gen_goto_tb(s
, 0, dest
);
3377 s
->is_jmp
= DISAS_TB_JUMP
;
3381 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3384 tcg_gen_sari_i32(t0
, t0
, 16);
3388 tcg_gen_sari_i32(t1
, t1
, 16);
3391 tcg_gen_mul_i32(t0
, t0
, t1
);
3394 /* Return the mask of PSR bits set by a MSR instruction. */
3395 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3399 if (flags
& (1 << 0))
3401 if (flags
& (1 << 1))
3403 if (flags
& (1 << 2))
3405 if (flags
& (1 << 3))
3408 /* Mask out undefined bits. */
3409 mask
&= ~CPSR_RESERVED
;
3410 if (!arm_feature(env
, ARM_FEATURE_V6
))
3411 mask
&= ~(CPSR_E
| CPSR_GE
);
3412 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3414 /* Mask out execution state bits. */
3417 /* Mask out privileged bits. */
3423 /* Returns nonzero if access to the PSR is not permitted. */
3424 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3428 /* ??? This is also undefined in system mode. */
3432 tmp
= load_cpu_field(spsr
);
3433 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3434 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3435 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3436 store_cpu_field(tmp
, spsr
);
3438 gen_set_cpsr(cpu_T
[0], mask
);
3444 /* Generate an old-style exception return. Marks pc as dead. */
3445 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3448 store_reg(s
, 15, pc
);
3449 tmp
= load_cpu_field(spsr
);
3450 gen_set_cpsr(tmp
, 0xffffffff);
3452 s
->is_jmp
= DISAS_UPDATE
;
3455 /* Generate a v6 exception return. Marks both values as dead. */
3456 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3458 gen_set_cpsr(cpsr
, 0xffffffff);
3460 store_reg(s
, 15, pc
);
3461 s
->is_jmp
= DISAS_UPDATE
;
3465 gen_set_condexec (DisasContext
*s
)
3467 if (s
->condexec_mask
) {
3468 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3469 TCGv tmp
= new_tmp();
3470 tcg_gen_movi_i32(tmp
, val
);
3471 store_cpu_field(tmp
, condexec_bits
);
3475 static void gen_nop_hint(DisasContext
*s
, int val
)
3479 gen_set_pc_im(s
->pc
);
3480 s
->is_jmp
= DISAS_WFI
;
3484 /* TODO: Implement SEV and WFE. May help SMP performance. */
3490 /* These macros help make the code more readable when migrating from the
3491 old dyngen helpers. They should probably be removed when
3492 T0/T1 are removed. */
3493 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3494 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3496 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3498 static inline int gen_neon_add(int size
)
3501 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3502 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3503 case 2: gen_op_addl_T0_T1(); break;
3509 static inline void gen_neon_rsb(int size
)
3512 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3513 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3514 case 2: gen_op_rsbl_T0_T1(); break;
3519 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3520 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3521 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3522 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3523 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3525 /* FIXME: This is wrong. They set the wrong overflow bit. */
3526 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3527 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3528 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3529 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3531 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3532 switch ((size << 1) | u) { \
3534 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3537 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3540 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3543 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3546 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3549 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3551 default: return 1; \
3554 #define GEN_NEON_INTEGER_OP(name) do { \
3555 switch ((size << 1) | u) { \
3557 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3560 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3563 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3566 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3569 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3572 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3574 default: return 1; \
3578 gen_neon_movl_scratch_T0(int scratch
)
3582 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3583 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3587 gen_neon_movl_scratch_T1(int scratch
)
3591 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3592 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3596 gen_neon_movl_T0_scratch(int scratch
)
3600 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3601 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3605 gen_neon_movl_T1_scratch(int scratch
)
3609 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3610 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3613 static inline void gen_neon_get_scalar(int size
, int reg
)
3616 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3618 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3620 gen_neon_dup_low16(cpu_T
[0]);
3622 gen_neon_dup_high16(cpu_T
[0]);
3626 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3630 for (n
= 0; n
< q
+ 1; n
+= 2) {
3631 NEON_GET_REG(T0
, reg
, n
);
3632 NEON_GET_REG(T0
, reg
, n
+ n
);
3634 case 0: gen_helper_neon_unzip_u8(); break;
3635 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3636 case 2: /* no-op */; break;
3639 gen_neon_movl_scratch_T0(tmp
+ n
);
3640 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3648 } neon_ls_element_type
[11] = {
3662 /* Translate a NEON load/store element instruction. Return nonzero if the
3663 instruction is invalid. */
3664 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3680 if (!vfp_enabled(env
))
3682 VFP_DREG_D(rd
, insn
);
3683 rn
= (insn
>> 16) & 0xf;
3685 load
= (insn
& (1 << 21)) != 0;
3686 if ((insn
& (1 << 23)) == 0) {
3687 /* Load store all elements. */
3688 op
= (insn
>> 8) & 0xf;
3689 size
= (insn
>> 6) & 3;
3690 if (op
> 10 || size
== 3)
3692 nregs
= neon_ls_element_type
[op
].nregs
;
3693 interleave
= neon_ls_element_type
[op
].interleave
;
3694 gen_movl_T1_reg(s
, rn
);
3695 stride
= (1 << size
) * interleave
;
3696 for (reg
= 0; reg
< nregs
; reg
++) {
3697 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3698 gen_movl_T1_reg(s
, rn
);
3699 gen_op_addl_T1_im((1 << size
) * reg
);
3700 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3701 gen_movl_T1_reg(s
, rn
);
3702 gen_op_addl_T1_im(1 << size
);
3704 for (pass
= 0; pass
< 2; pass
++) {
3707 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3708 neon_store_reg(rd
, pass
, tmp
);
3710 tmp
= neon_load_reg(rd
, pass
);
3711 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3713 gen_op_addl_T1_im(stride
);
3714 } else if (size
== 1) {
3716 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3717 gen_op_addl_T1_im(stride
);
3718 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3719 gen_op_addl_T1_im(stride
);
3720 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3722 neon_store_reg(rd
, pass
, tmp
);
3724 tmp
= neon_load_reg(rd
, pass
);
3726 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3727 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3728 gen_op_addl_T1_im(stride
);
3729 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3730 gen_op_addl_T1_im(stride
);
3732 } else /* size == 0 */ {
3735 for (n
= 0; n
< 4; n
++) {
3736 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3737 gen_op_addl_T1_im(stride
);
3741 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3745 neon_store_reg(rd
, pass
, tmp2
);
3747 tmp2
= neon_load_reg(rd
, pass
);
3748 for (n
= 0; n
< 4; n
++) {
3751 tcg_gen_mov_i32(tmp
, tmp2
);
3753 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3755 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3756 gen_op_addl_T1_im(stride
);
3762 rd
+= neon_ls_element_type
[op
].spacing
;
3766 size
= (insn
>> 10) & 3;
3768 /* Load single element to all lanes. */
3771 size
= (insn
>> 6) & 3;
3772 nregs
= ((insn
>> 8) & 3) + 1;
3773 stride
= (insn
& (1 << 5)) ? 2 : 1;
3774 gen_movl_T1_reg(s
, rn
);
3775 for (reg
= 0; reg
< nregs
; reg
++) {
3778 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3779 gen_neon_dup_u8(tmp
, 0);
3782 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3783 gen_neon_dup_low16(tmp
);
3786 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3790 default: /* Avoid compiler warnings. */
3793 gen_op_addl_T1_im(1 << size
);
3795 tcg_gen_mov_i32(tmp2
, tmp
);
3796 neon_store_reg(rd
, 0, tmp2
);
3797 neon_store_reg(rd
, 1, tmp
);
3800 stride
= (1 << size
) * nregs
;
3802 /* Single element. */
3803 pass
= (insn
>> 7) & 1;
3806 shift
= ((insn
>> 5) & 3) * 8;
3810 shift
= ((insn
>> 6) & 1) * 16;
3811 stride
= (insn
& (1 << 5)) ? 2 : 1;
3815 stride
= (insn
& (1 << 6)) ? 2 : 1;
3820 nregs
= ((insn
>> 8) & 3) + 1;
3821 gen_movl_T1_reg(s
, rn
);
3822 for (reg
= 0; reg
< nregs
; reg
++) {
3826 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3829 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3832 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3834 default: /* Avoid compiler warnings. */
3838 tmp2
= neon_load_reg(rd
, pass
);
3839 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3842 neon_store_reg(rd
, pass
, tmp
);
3843 } else { /* Store */
3844 tmp
= neon_load_reg(rd
, pass
);
3846 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3849 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3852 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3855 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3860 gen_op_addl_T1_im(1 << size
);
3862 stride
= nregs
* (1 << size
);
3868 base
= load_reg(s
, rn
);
3870 tcg_gen_addi_i32(base
, base
, stride
);
3873 index
= load_reg(s
, rm
);
3874 tcg_gen_add_i32(base
, base
, index
);
3877 store_reg(s
, rn
, base
);
3882 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3883 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3885 tcg_gen_and_i32(t
, t
, c
);
3886 tcg_gen_bic_i32(f
, f
, c
);
3887 tcg_gen_or_i32(dest
, t
, f
);
3890 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3893 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3894 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3895 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3900 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3903 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3904 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3905 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3910 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3913 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3914 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3915 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3920 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3926 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3927 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3932 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3933 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3940 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3941 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3946 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3947 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3954 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3958 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3959 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3960 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3965 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3966 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3967 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3974 static inline void gen_neon_addl(int size
)
3977 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3978 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3979 case 2: tcg_gen_add_i64(CPU_V001
); break;
3984 static inline void gen_neon_subl(int size
)
3987 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
3988 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
3989 case 2: tcg_gen_sub_i64(CPU_V001
); break;
3994 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
3997 case 0: gen_helper_neon_negl_u16(var
, var
); break;
3998 case 1: gen_helper_neon_negl_u32(var
, var
); break;
3999 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4004 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4007 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4008 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4013 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4017 switch ((size
<< 1) | u
) {
4018 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4019 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4020 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4021 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4023 tmp
= gen_muls_i64_i32(a
, b
);
4024 tcg_gen_mov_i64(dest
, tmp
);
4027 tmp
= gen_mulu_i64_i32(a
, b
);
4028 tcg_gen_mov_i64(dest
, tmp
);
4038 /* Translate a NEON data processing instruction. Return nonzero if the
4039 instruction is invalid.
4040 We process data in a mixture of 32-bit and 64-bit chunks.
4041 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4043 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4061 if (!vfp_enabled(env
))
4063 q
= (insn
& (1 << 6)) != 0;
4064 u
= (insn
>> 24) & 1;
4065 VFP_DREG_D(rd
, insn
);
4066 VFP_DREG_N(rn
, insn
);
4067 VFP_DREG_M(rm
, insn
);
4068 size
= (insn
>> 20) & 3;
4069 if ((insn
& (1 << 23)) == 0) {
4070 /* Three register same length. */
4071 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4072 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4073 || op
== 10 || op
== 11 || op
== 16)) {
4074 /* 64-bit element instructions. */
4075 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4076 neon_load_reg64(cpu_V0
, rn
+ pass
);
4077 neon_load_reg64(cpu_V1
, rm
+ pass
);
4081 gen_helper_neon_add_saturate_u64(CPU_V001
);
4083 gen_helper_neon_add_saturate_s64(CPU_V001
);
4088 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4090 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4095 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4097 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4102 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4105 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4109 case 10: /* VRSHL */
4111 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4113 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4116 case 11: /* VQRSHL */
4118 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4121 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4127 tcg_gen_sub_i64(CPU_V001
);
4129 tcg_gen_add_i64(CPU_V001
);
4135 neon_store_reg64(cpu_V0
, rd
+ pass
);
4142 case 10: /* VRSHL */
4143 case 11: /* VQRSHL */
4146 /* Shift instruction operands are reversed. */
4153 case 20: /* VPMAX */
4154 case 21: /* VPMIN */
4155 case 23: /* VPADD */
4158 case 26: /* VPADD (float) */
4159 pairwise
= (u
&& size
< 2);
4161 case 30: /* VPMIN/VPMAX (float) */
4168 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4177 NEON_GET_REG(T0
, rn
, n
);
4178 NEON_GET_REG(T1
, rn
, n
+ 1);
4180 NEON_GET_REG(T0
, rm
, n
);
4181 NEON_GET_REG(T1
, rm
, n
+ 1);
4185 NEON_GET_REG(T0
, rn
, pass
);
4186 NEON_GET_REG(T1
, rm
, pass
);
4190 GEN_NEON_INTEGER_OP(hadd
);
4193 GEN_NEON_INTEGER_OP_ENV(qadd
);
4195 case 2: /* VRHADD */
4196 GEN_NEON_INTEGER_OP(rhadd
);
4198 case 3: /* Logic ops. */
4199 switch ((u
<< 2) | size
) {
4201 gen_op_andl_T0_T1();
4204 gen_op_bicl_T0_T1();
4214 gen_op_xorl_T0_T1();
4217 tmp
= neon_load_reg(rd
, pass
);
4218 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4222 tmp
= neon_load_reg(rd
, pass
);
4223 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4227 tmp
= neon_load_reg(rd
, pass
);
4228 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4234 GEN_NEON_INTEGER_OP(hsub
);
4237 GEN_NEON_INTEGER_OP_ENV(qsub
);
4240 GEN_NEON_INTEGER_OP(cgt
);
4243 GEN_NEON_INTEGER_OP(cge
);
4246 GEN_NEON_INTEGER_OP(shl
);
4249 GEN_NEON_INTEGER_OP_ENV(qshl
);
4251 case 10: /* VRSHL */
4252 GEN_NEON_INTEGER_OP(rshl
);
4254 case 11: /* VQRSHL */
4255 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4258 GEN_NEON_INTEGER_OP(max
);
4261 GEN_NEON_INTEGER_OP(min
);
4264 GEN_NEON_INTEGER_OP(abd
);
4267 GEN_NEON_INTEGER_OP(abd
);
4268 NEON_GET_REG(T1
, rd
, pass
);
4272 if (!u
) { /* VADD */
4273 if (gen_neon_add(size
))
4277 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4278 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4279 case 2: gen_op_subl_T0_T1(); break;
4285 if (!u
) { /* VTST */
4287 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4288 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4289 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4294 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4295 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4296 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4301 case 18: /* Multiply. */
4303 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4304 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4305 case 2: gen_op_mul_T0_T1(); break;
4308 NEON_GET_REG(T1
, rd
, pass
);
4316 if (u
) { /* polynomial */
4317 gen_helper_neon_mul_p8(CPU_T001
);
4318 } else { /* Integer */
4320 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4321 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4322 case 2: gen_op_mul_T0_T1(); break;
4327 case 20: /* VPMAX */
4328 GEN_NEON_INTEGER_OP(pmax
);
4330 case 21: /* VPMIN */
4331 GEN_NEON_INTEGER_OP(pmin
);
4333 case 22: /* Hultiply high. */
4334 if (!u
) { /* VQDMULH */
4336 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4337 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4340 } else { /* VQRDHMUL */
4342 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4343 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4348 case 23: /* VPADD */
4352 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4353 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4354 case 2: gen_op_addl_T0_T1(); break;
4358 case 26: /* Floating point arithnetic. */
4359 switch ((u
<< 2) | size
) {
4361 gen_helper_neon_add_f32(CPU_T001
);
4364 gen_helper_neon_sub_f32(CPU_T001
);
4367 gen_helper_neon_add_f32(CPU_T001
);
4370 gen_helper_neon_abd_f32(CPU_T001
);
4376 case 27: /* Float multiply. */
4377 gen_helper_neon_mul_f32(CPU_T001
);
4379 NEON_GET_REG(T1
, rd
, pass
);
4381 gen_helper_neon_add_f32(CPU_T001
);
4383 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4387 case 28: /* Float compare. */
4389 gen_helper_neon_ceq_f32(CPU_T001
);
4392 gen_helper_neon_cge_f32(CPU_T001
);
4394 gen_helper_neon_cgt_f32(CPU_T001
);
4397 case 29: /* Float compare absolute. */
4401 gen_helper_neon_acge_f32(CPU_T001
);
4403 gen_helper_neon_acgt_f32(CPU_T001
);
4405 case 30: /* Float min/max. */
4407 gen_helper_neon_max_f32(CPU_T001
);
4409 gen_helper_neon_min_f32(CPU_T001
);
4413 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4415 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4420 /* Save the result. For elementwise operations we can put it
4421 straight into the destination register. For pairwise operations
4422 we have to be careful to avoid clobbering the source operands. */
4423 if (pairwise
&& rd
== rm
) {
4424 gen_neon_movl_scratch_T0(pass
);
4426 NEON_SET_REG(T0
, rd
, pass
);
4430 if (pairwise
&& rd
== rm
) {
4431 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4432 gen_neon_movl_T0_scratch(pass
);
4433 NEON_SET_REG(T0
, rd
, pass
);
4436 /* End of 3 register same size operations. */
4437 } else if (insn
& (1 << 4)) {
4438 if ((insn
& 0x00380080) != 0) {
4439 /* Two registers and shift. */
4440 op
= (insn
>> 8) & 0xf;
4441 if (insn
& (1 << 7)) {
4446 while ((insn
& (1 << (size
+ 19))) == 0)
4449 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4450 /* To avoid excessive dumplication of ops we implement shift
4451 by immediate using the variable shift operations. */
4453 /* Shift by immediate:
4454 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4455 /* Right shifts are encoded as N - shift, where N is the
4456 element size in bits. */
4458 shift
= shift
- (1 << (size
+ 3));
4466 imm
= (uint8_t) shift
;
4471 imm
= (uint16_t) shift
;
4482 for (pass
= 0; pass
< count
; pass
++) {
4484 neon_load_reg64(cpu_V0
, rm
+ pass
);
4485 tcg_gen_movi_i64(cpu_V1
, imm
);
4490 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4492 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4497 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4499 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4504 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4506 case 5: /* VSHL, VSLI */
4507 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4511 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4513 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4515 case 7: /* VQSHLU */
4516 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4519 if (op
== 1 || op
== 3) {
4521 neon_load_reg64(cpu_V0
, rd
+ pass
);
4522 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4523 } else if (op
== 4 || (op
== 5 && u
)) {
4525 cpu_abort(env
, "VS[LR]I.64 not implemented");
4527 neon_store_reg64(cpu_V0
, rd
+ pass
);
4528 } else { /* size < 3 */
4529 /* Operands in T0 and T1. */
4530 gen_op_movl_T1_im(imm
);
4531 NEON_GET_REG(T0
, rm
, pass
);
4535 GEN_NEON_INTEGER_OP(shl
);
4539 GEN_NEON_INTEGER_OP(rshl
);
4544 GEN_NEON_INTEGER_OP(shl
);
4546 case 5: /* VSHL, VSLI */
4548 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4549 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4550 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4555 GEN_NEON_INTEGER_OP_ENV(qshl
);
4557 case 7: /* VQSHLU */
4559 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4560 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4561 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4567 if (op
== 1 || op
== 3) {
4569 NEON_GET_REG(T1
, rd
, pass
);
4571 } else if (op
== 4 || (op
== 5 && u
)) {
4576 imm
= 0xff >> -shift
;
4578 imm
= (uint8_t)(0xff << shift
);
4584 imm
= 0xffff >> -shift
;
4586 imm
= (uint16_t)(0xffff << shift
);
4591 imm
= 0xffffffffu
>> -shift
;
4593 imm
= 0xffffffffu
<< shift
;
4598 tmp
= neon_load_reg(rd
, pass
);
4599 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4600 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4601 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4603 NEON_SET_REG(T0
, rd
, pass
);
4606 } else if (op
< 10) {
4607 /* Shift by immediate and narrow:
4608 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4609 shift
= shift
- (1 << (size
+ 3));
4613 imm
= (uint16_t)shift
;
4615 tmp2
= tcg_const_i32(imm
);
4616 TCGV_UNUSED_I64(tmp64
);
4619 imm
= (uint32_t)shift
;
4620 tmp2
= tcg_const_i32(imm
);
4621 TCGV_UNUSED_I64(tmp64
);
4624 tmp64
= tcg_const_i64(shift
);
4631 for (pass
= 0; pass
< 2; pass
++) {
4633 neon_load_reg64(cpu_V0
, rm
+ pass
);
4636 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4638 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4641 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4643 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4646 tmp
= neon_load_reg(rm
+ pass
, 0);
4647 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4648 tmp3
= neon_load_reg(rm
+ pass
, 1);
4649 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4650 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4655 if (op
== 8 && !u
) {
4656 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4659 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4661 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4666 neon_store_reg(rd
, 0, tmp2
);
4667 neon_store_reg(rd
, 1, tmp
);
4670 } else if (op
== 10) {
4674 tmp
= neon_load_reg(rm
, 0);
4675 tmp2
= neon_load_reg(rm
, 1);
4676 for (pass
= 0; pass
< 2; pass
++) {
4680 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4683 /* The shift is less than the width of the source
4684 type, so we can just shift the whole register. */
4685 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4686 if (size
< 2 || !u
) {
4689 imm
= (0xffu
>> (8 - shift
));
4692 imm
= 0xffff >> (16 - shift
);
4694 imm64
= imm
| (((uint64_t)imm
) << 32);
4695 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4698 neon_store_reg64(cpu_V0
, rd
+ pass
);
4700 } else if (op
== 15 || op
== 16) {
4701 /* VCVT fixed-point. */
4702 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4703 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4706 gen_vfp_ulto(0, shift
);
4708 gen_vfp_slto(0, shift
);
4711 gen_vfp_toul(0, shift
);
4713 gen_vfp_tosl(0, shift
);
4715 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4720 } else { /* (insn & 0x00380080) == 0 */
4723 op
= (insn
>> 8) & 0xf;
4724 /* One register and immediate. */
4725 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4726 invert
= (insn
& (1 << 5)) != 0;
4744 imm
= (imm
<< 8) | (imm
<< 24);
4747 imm
= (imm
< 8) | 0xff;
4750 imm
= (imm
<< 16) | 0xffff;
4753 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4758 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4759 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4765 if (op
!= 14 || !invert
)
4766 gen_op_movl_T1_im(imm
);
4768 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4769 if (op
& 1 && op
< 12) {
4770 tmp
= neon_load_reg(rd
, pass
);
4772 /* The immediate value has already been inverted, so
4774 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4776 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4781 if (op
== 14 && invert
) {
4784 for (n
= 0; n
< 4; n
++) {
4785 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4786 val
|= 0xff << (n
* 8);
4788 tcg_gen_movi_i32(tmp
, val
);
4790 tcg_gen_movi_i32(tmp
, imm
);
4793 neon_store_reg(rd
, pass
, tmp
);
4796 } else { /* (insn & 0x00800010 == 0x00800000) */
4798 op
= (insn
>> 8) & 0xf;
4799 if ((insn
& (1 << 6)) == 0) {
4800 /* Three registers of different lengths. */
4804 /* prewiden, src1_wide, src2_wide */
4805 static const int neon_3reg_wide
[16][3] = {
4806 {1, 0, 0}, /* VADDL */
4807 {1, 1, 0}, /* VADDW */
4808 {1, 0, 0}, /* VSUBL */
4809 {1, 1, 0}, /* VSUBW */
4810 {0, 1, 1}, /* VADDHN */
4811 {0, 0, 0}, /* VABAL */
4812 {0, 1, 1}, /* VSUBHN */
4813 {0, 0, 0}, /* VABDL */
4814 {0, 0, 0}, /* VMLAL */
4815 {0, 0, 0}, /* VQDMLAL */
4816 {0, 0, 0}, /* VMLSL */
4817 {0, 0, 0}, /* VQDMLSL */
4818 {0, 0, 0}, /* Integer VMULL */
4819 {0, 0, 0}, /* VQDMULL */
4820 {0, 0, 0} /* Polynomial VMULL */
4823 prewiden
= neon_3reg_wide
[op
][0];
4824 src1_wide
= neon_3reg_wide
[op
][1];
4825 src2_wide
= neon_3reg_wide
[op
][2];
4827 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4830 /* Avoid overlapping operands. Wide source operands are
4831 always aligned so will never overlap with wide
4832 destinations in problematic ways. */
4833 if (rd
== rm
&& !src2_wide
) {
4834 NEON_GET_REG(T0
, rm
, 1);
4835 gen_neon_movl_scratch_T0(2);
4836 } else if (rd
== rn
&& !src1_wide
) {
4837 NEON_GET_REG(T0
, rn
, 1);
4838 gen_neon_movl_scratch_T0(2);
4841 for (pass
= 0; pass
< 2; pass
++) {
4843 neon_load_reg64(cpu_V0
, rn
+ pass
);
4846 if (pass
== 1 && rd
== rn
) {
4847 gen_neon_movl_T0_scratch(2);
4849 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4851 tmp
= neon_load_reg(rn
, pass
);
4854 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4858 neon_load_reg64(cpu_V1
, rm
+ pass
);
4861 if (pass
== 1 && rd
== rm
) {
4862 gen_neon_movl_T0_scratch(2);
4864 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4866 tmp2
= neon_load_reg(rm
, pass
);
4869 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4873 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4874 gen_neon_addl(size
);
4876 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4877 gen_neon_subl(size
);
4879 case 5: case 7: /* VABAL, VABDL */
4880 switch ((size
<< 1) | u
) {
4882 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4885 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4888 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4891 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4894 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4897 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4904 case 8: case 9: case 10: case 11: case 12: case 13:
4905 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4906 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4908 case 14: /* Polynomial VMULL */
4909 cpu_abort(env
, "Polynomial VMULL not implemented");
4911 default: /* 15 is RESERVED. */
4914 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4916 if (op
== 10 || op
== 11) {
4917 gen_neon_negl(cpu_V0
, size
);
4921 neon_load_reg64(cpu_V1
, rd
+ pass
);
4925 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4926 gen_neon_addl(size
);
4928 case 9: case 11: /* VQDMLAL, VQDMLSL */
4929 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4930 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4933 case 13: /* VQDMULL */
4934 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4939 neon_store_reg64(cpu_V0
, rd
+ pass
);
4940 } else if (op
== 4 || op
== 6) {
4941 /* Narrowing operation. */
4946 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4949 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4952 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4953 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4960 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4963 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4966 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4967 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4968 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4976 neon_store_reg(rd
, 0, tmp3
);
4977 neon_store_reg(rd
, 1, tmp
);
4980 /* Write back the result. */
4981 neon_store_reg64(cpu_V0
, rd
+ pass
);
4985 /* Two registers and a scalar. */
4987 case 0: /* Integer VMLA scalar */
4988 case 1: /* Float VMLA scalar */
4989 case 4: /* Integer VMLS scalar */
4990 case 5: /* Floating point VMLS scalar */
4991 case 8: /* Integer VMUL scalar */
4992 case 9: /* Floating point VMUL scalar */
4993 case 12: /* VQDMULH scalar */
4994 case 13: /* VQRDMULH scalar */
4995 gen_neon_get_scalar(size
, rm
);
4996 gen_neon_movl_scratch_T0(0);
4997 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
4999 gen_neon_movl_T0_scratch(0);
5000 NEON_GET_REG(T1
, rn
, pass
);
5003 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5005 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5007 } else if (op
== 13) {
5009 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5011 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5013 } else if (op
& 1) {
5014 gen_helper_neon_mul_f32(CPU_T001
);
5017 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5018 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5019 case 2: gen_op_mul_T0_T1(); break;
5025 NEON_GET_REG(T1
, rd
, pass
);
5031 gen_helper_neon_add_f32(CPU_T001
);
5037 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5043 NEON_SET_REG(T0
, rd
, pass
);
5046 case 2: /* VMLAL sclar */
5047 case 3: /* VQDMLAL scalar */
5048 case 6: /* VMLSL scalar */
5049 case 7: /* VQDMLSL scalar */
5050 case 10: /* VMULL scalar */
5051 case 11: /* VQDMULL scalar */
5052 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5055 gen_neon_get_scalar(size
, rm
);
5056 NEON_GET_REG(T1
, rn
, 1);
5058 for (pass
= 0; pass
< 2; pass
++) {
5060 tmp
= neon_load_reg(rn
, 0);
5063 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5066 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5067 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5068 if (op
== 6 || op
== 7) {
5069 gen_neon_negl(cpu_V0
, size
);
5072 neon_load_reg64(cpu_V1
, rd
+ pass
);
5076 gen_neon_addl(size
);
5079 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5080 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5086 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5091 neon_store_reg64(cpu_V0
, rd
+ pass
);
5094 default: /* 14 and 15 are RESERVED */
5098 } else { /* size == 3 */
5101 imm
= (insn
>> 8) & 0xf;
5108 neon_load_reg64(cpu_V0
, rn
);
5110 neon_load_reg64(cpu_V1
, rn
+ 1);
5112 } else if (imm
== 8) {
5113 neon_load_reg64(cpu_V0
, rn
+ 1);
5115 neon_load_reg64(cpu_V1
, rm
);
5118 tmp64
= tcg_temp_new_i64();
5120 neon_load_reg64(cpu_V0
, rn
);
5121 neon_load_reg64(tmp64
, rn
+ 1);
5123 neon_load_reg64(cpu_V0
, rn
+ 1);
5124 neon_load_reg64(tmp64
, rm
);
5126 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5127 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5128 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5130 neon_load_reg64(cpu_V1
, rm
);
5132 neon_load_reg64(cpu_V1
, rm
+ 1);
5135 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5136 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5137 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5140 neon_load_reg64(cpu_V0
, rn
);
5141 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5142 neon_load_reg64(cpu_V1
, rm
);
5143 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5144 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5146 neon_store_reg64(cpu_V0
, rd
);
5148 neon_store_reg64(cpu_V1
, rd
+ 1);
5150 } else if ((insn
& (1 << 11)) == 0) {
5151 /* Two register misc. */
5152 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5153 size
= (insn
>> 18) & 3;
5155 case 0: /* VREV64 */
5158 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5159 NEON_GET_REG(T0
, rm
, pass
* 2);
5160 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5162 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5163 case 1: gen_swap_half(cpu_T
[0]); break;
5164 case 2: /* no-op */ break;
5167 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5169 NEON_SET_REG(T1
, rd
, pass
* 2);
5171 gen_op_movl_T0_T1();
5173 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5174 case 1: gen_swap_half(cpu_T
[0]); break;
5177 NEON_SET_REG(T0
, rd
, pass
* 2);
5181 case 4: case 5: /* VPADDL */
5182 case 12: case 13: /* VPADAL */
5185 for (pass
= 0; pass
< q
+ 1; pass
++) {
5186 tmp
= neon_load_reg(rm
, pass
* 2);
5187 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5188 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5189 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5191 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5192 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5193 case 2: tcg_gen_add_i64(CPU_V001
); break;
5198 neon_load_reg64(cpu_V1
, rd
+ pass
);
5199 gen_neon_addl(size
);
5201 neon_store_reg64(cpu_V0
, rd
+ pass
);
5206 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5207 NEON_GET_REG(T0
, rm
, n
);
5208 NEON_GET_REG(T1
, rd
, n
+ 1);
5209 NEON_SET_REG(T1
, rm
, n
);
5210 NEON_SET_REG(T0
, rd
, n
+ 1);
5218 Rd A3 A2 A1 A0 B2 B0 A2 A0
5219 Rm B3 B2 B1 B0 B3 B1 A3 A1
5223 gen_neon_unzip(rd
, q
, 0, size
);
5224 gen_neon_unzip(rm
, q
, 4, size
);
5226 static int unzip_order_q
[8] =
5227 {0, 2, 4, 6, 1, 3, 5, 7};
5228 for (n
= 0; n
< 8; n
++) {
5229 int reg
= (n
< 4) ? rd
: rm
;
5230 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5231 NEON_SET_REG(T0
, reg
, n
% 4);
5234 static int unzip_order
[4] =
5236 for (n
= 0; n
< 4; n
++) {
5237 int reg
= (n
< 2) ? rd
: rm
;
5238 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5239 NEON_SET_REG(T0
, reg
, n
% 2);
5245 Rd A3 A2 A1 A0 B1 A1 B0 A0
5246 Rm B3 B2 B1 B0 B3 A3 B2 A2
5250 count
= (q
? 4 : 2);
5251 for (n
= 0; n
< count
; n
++) {
5252 NEON_GET_REG(T0
, rd
, n
);
5253 NEON_GET_REG(T1
, rd
, n
);
5255 case 0: gen_helper_neon_zip_u8(); break;
5256 case 1: gen_helper_neon_zip_u16(); break;
5257 case 2: /* no-op */; break;
5260 gen_neon_movl_scratch_T0(n
* 2);
5261 gen_neon_movl_scratch_T1(n
* 2 + 1);
5263 for (n
= 0; n
< count
* 2; n
++) {
5264 int reg
= (n
< count
) ? rd
: rm
;
5265 gen_neon_movl_T0_scratch(n
);
5266 NEON_SET_REG(T0
, reg
, n
% count
);
5269 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5273 for (pass
= 0; pass
< 2; pass
++) {
5274 neon_load_reg64(cpu_V0
, rm
+ pass
);
5276 if (op
== 36 && q
== 0) {
5277 gen_neon_narrow(size
, tmp
, cpu_V0
);
5279 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5281 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5286 neon_store_reg(rd
, 0, tmp2
);
5287 neon_store_reg(rd
, 1, tmp
);
5291 case 38: /* VSHLL */
5294 tmp
= neon_load_reg(rm
, 0);
5295 tmp2
= neon_load_reg(rm
, 1);
5296 for (pass
= 0; pass
< 2; pass
++) {
5299 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5300 neon_store_reg64(cpu_V0
, rd
+ pass
);
5305 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5306 if (op
== 30 || op
== 31 || op
>= 58) {
5307 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5308 neon_reg_offset(rm
, pass
));
5310 NEON_GET_REG(T0
, rm
, pass
);
5313 case 1: /* VREV32 */
5315 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5316 case 1: gen_swap_half(cpu_T
[0]); break;
5320 case 2: /* VREV16 */
5323 gen_rev16(cpu_T
[0]);
5327 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5328 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5329 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5335 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5336 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5337 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5344 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5351 case 14: /* VQABS */
5353 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5354 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5355 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5359 case 15: /* VQNEG */
5361 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5362 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5363 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5367 case 16: case 19: /* VCGT #0, VCLE #0 */
5368 gen_op_movl_T1_im(0);
5370 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5371 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5372 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5378 case 17: case 20: /* VCGE #0, VCLT #0 */
5379 gen_op_movl_T1_im(0);
5381 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5382 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5383 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5389 case 18: /* VCEQ #0 */
5390 gen_op_movl_T1_im(0);
5392 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5393 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5394 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5400 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5401 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5402 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5407 gen_op_movl_T1_im(0);
5412 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5413 gen_op_movl_T1_im(0);
5414 gen_helper_neon_cgt_f32(CPU_T001
);
5418 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5419 gen_op_movl_T1_im(0);
5420 gen_helper_neon_cge_f32(CPU_T001
);
5424 case 26: /* Float VCEQ #0 */
5425 gen_op_movl_T1_im(0);
5426 gen_helper_neon_ceq_f32(CPU_T001
);
5428 case 30: /* Float VABS */
5431 case 31: /* Float VNEG */
5435 NEON_GET_REG(T1
, rd
, pass
);
5436 NEON_SET_REG(T1
, rm
, pass
);
5439 NEON_GET_REG(T1
, rd
, pass
);
5441 case 0: gen_helper_neon_trn_u8(); break;
5442 case 1: gen_helper_neon_trn_u16(); break;
5446 NEON_SET_REG(T1
, rm
, pass
);
5448 case 56: /* Integer VRECPE */
5449 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5451 case 57: /* Integer VRSQRTE */
5452 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5454 case 58: /* Float VRECPE */
5455 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5457 case 59: /* Float VRSQRTE */
5458 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5460 case 60: /* VCVT.F32.S32 */
5463 case 61: /* VCVT.F32.U32 */
5466 case 62: /* VCVT.S32.F32 */
5469 case 63: /* VCVT.U32.F32 */
5473 /* Reserved: 21, 29, 39-56 */
5476 if (op
== 30 || op
== 31 || op
>= 58) {
5477 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5478 neon_reg_offset(rd
, pass
));
5480 NEON_SET_REG(T0
, rd
, pass
);
5485 } else if ((insn
& (1 << 10)) == 0) {
5487 n
= ((insn
>> 5) & 0x18) + 8;
5488 if (insn
& (1 << 6)) {
5489 tmp
= neon_load_reg(rd
, 0);
5492 tcg_gen_movi_i32(tmp
, 0);
5494 tmp2
= neon_load_reg(rm
, 0);
5495 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5498 if (insn
& (1 << 6)) {
5499 tmp
= neon_load_reg(rd
, 1);
5502 tcg_gen_movi_i32(tmp
, 0);
5504 tmp3
= neon_load_reg(rm
, 1);
5505 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5507 neon_store_reg(rd
, 0, tmp2
);
5508 neon_store_reg(rd
, 1, tmp3
);
5510 } else if ((insn
& 0x380) == 0) {
5512 if (insn
& (1 << 19)) {
5513 NEON_SET_REG(T0
, rm
, 1);
5515 NEON_SET_REG(T0
, rm
, 0);
5517 if (insn
& (1 << 16)) {
5518 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5519 } else if (insn
& (1 << 17)) {
5520 if ((insn
>> 18) & 1)
5521 gen_neon_dup_high16(cpu_T
[0]);
5523 gen_neon_dup_low16(cpu_T
[0]);
5525 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5526 NEON_SET_REG(T0
, rd
, pass
);
5536 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5538 int crn
= (insn
>> 16) & 0xf;
5539 int crm
= insn
& 0xf;
5540 int op1
= (insn
>> 21) & 7;
5541 int op2
= (insn
>> 5) & 7;
5542 int rt
= (insn
>> 12) & 0xf;
5545 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5546 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5550 tmp
= load_cpu_field(teecr
);
5551 store_reg(s
, rt
, tmp
);
5554 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5556 if (IS_USER(s
) && (env
->teecr
& 1))
5558 tmp
= load_cpu_field(teehbr
);
5559 store_reg(s
, rt
, tmp
);
5563 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5564 op1
, crn
, crm
, op2
);
5568 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5570 int crn
= (insn
>> 16) & 0xf;
5571 int crm
= insn
& 0xf;
5572 int op1
= (insn
>> 21) & 7;
5573 int op2
= (insn
>> 5) & 7;
5574 int rt
= (insn
>> 12) & 0xf;
5577 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5578 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5582 tmp
= load_reg(s
, rt
);
5583 gen_helper_set_teecr(cpu_env
, tmp
);
5587 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5589 if (IS_USER(s
) && (env
->teecr
& 1))
5591 tmp
= load_reg(s
, rt
);
5592 store_cpu_field(tmp
, teehbr
);
5596 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5597 op1
, crn
, crm
, op2
);
5601 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5605 cpnum
= (insn
>> 8) & 0xf;
5606 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5607 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5613 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5614 return disas_iwmmxt_insn(env
, s
, insn
);
5615 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5616 return disas_dsp_insn(env
, s
, insn
);
5621 return disas_vfp_insn (env
, s
, insn
);
5623 /* Coprocessors 7-15 are architecturally reserved by ARM.
5624 Unfortunately Intel decided to ignore this. */
5625 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5627 if (insn
& (1 << 20))
5628 return disas_cp14_read(env
, s
, insn
);
5630 return disas_cp14_write(env
, s
, insn
);
5632 return disas_cp15_insn (env
, s
, insn
);
5635 /* Unknown coprocessor. See if the board has hooked it. */
5636 return disas_cp_insn (env
, s
, insn
);
5641 /* Store a 64-bit value to a register pair. Clobbers val. */
5642 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5646 tcg_gen_trunc_i64_i32(tmp
, val
);
5647 store_reg(s
, rlow
, tmp
);
5649 tcg_gen_shri_i64(val
, val
, 32);
5650 tcg_gen_trunc_i64_i32(tmp
, val
);
5651 store_reg(s
, rhigh
, tmp
);
5654 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5655 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5660 /* Load value and extend to 64 bits. */
5661 tmp
= tcg_temp_new_i64();
5662 tmp2
= load_reg(s
, rlow
);
5663 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5665 tcg_gen_add_i64(val
, val
, tmp
);
5668 /* load and add a 64-bit value from a register pair. */
5669 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5675 /* Load 64-bit value rd:rn. */
5676 tmpl
= load_reg(s
, rlow
);
5677 tmph
= load_reg(s
, rhigh
);
5678 tmp
= tcg_temp_new_i64();
5679 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5682 tcg_gen_add_i64(val
, val
, tmp
);
5685 /* Set N and Z flags from a 64-bit value. */
5686 static void gen_logicq_cc(TCGv_i64 val
)
5688 TCGv tmp
= new_tmp();
5689 gen_helper_logicq_cc(tmp
, val
);
5694 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5696 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5703 insn
= ldl_code(s
->pc
);
5706 /* M variants do not implement ARM mode. */
5711 /* Unconditional instructions. */
5712 if (((insn
>> 25) & 7) == 1) {
5713 /* NEON Data processing. */
5714 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5717 if (disas_neon_data_insn(env
, s
, insn
))
5721 if ((insn
& 0x0f100000) == 0x04000000) {
5722 /* NEON load/store. */
5723 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5726 if (disas_neon_ls_insn(env
, s
, insn
))
5730 if ((insn
& 0x0d70f000) == 0x0550f000)
5732 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5735 if (insn
& (1 << 9)) {
5736 /* BE8 mode not implemented. */
5740 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5741 switch ((insn
>> 4) & 0xf) {
5744 gen_helper_clrex(cpu_env
);
5750 /* We don't emulate caches so these are a no-op. */
5755 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5761 op1
= (insn
& 0x1f);
5762 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5763 addr
= load_reg(s
, 13);
5766 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5768 i
= (insn
>> 23) & 3;
5770 case 0: offset
= -4; break; /* DA */
5771 case 1: offset
= -8; break; /* DB */
5772 case 2: offset
= 0; break; /* IA */
5773 case 3: offset
= 4; break; /* IB */
5777 tcg_gen_addi_i32(addr
, addr
, offset
);
5778 tmp
= load_reg(s
, 14);
5779 gen_st32(tmp
, addr
, 0);
5781 gen_helper_cpsr_read(tmp
);
5782 tcg_gen_addi_i32(addr
, addr
, 4);
5783 gen_st32(tmp
, addr
, 0);
5784 if (insn
& (1 << 21)) {
5785 /* Base writeback. */
5787 case 0: offset
= -8; break;
5788 case 1: offset
= -4; break;
5789 case 2: offset
= 4; break;
5790 case 3: offset
= 0; break;
5794 tcg_gen_addi_i32(addr
, tmp
, offset
);
5795 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5796 gen_movl_reg_T1(s
, 13);
5798 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5803 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5809 rn
= (insn
>> 16) & 0xf;
5810 addr
= load_reg(s
, rn
);
5811 i
= (insn
>> 23) & 3;
5813 case 0: offset
= -4; break; /* DA */
5814 case 1: offset
= -8; break; /* DB */
5815 case 2: offset
= 0; break; /* IA */
5816 case 3: offset
= 4; break; /* IB */
5820 tcg_gen_addi_i32(addr
, addr
, offset
);
5821 /* Load PC into tmp and CPSR into tmp2. */
5822 tmp
= gen_ld32(addr
, 0);
5823 tcg_gen_addi_i32(addr
, addr
, 4);
5824 tmp2
= gen_ld32(addr
, 0);
5825 if (insn
& (1 << 21)) {
5826 /* Base writeback. */
5828 case 0: offset
= -8; break;
5829 case 1: offset
= -4; break;
5830 case 2: offset
= 4; break;
5831 case 3: offset
= 0; break;
5835 tcg_gen_addi_i32(addr
, addr
, offset
);
5836 store_reg(s
, rn
, addr
);
5840 gen_rfe(s
, tmp
, tmp2
);
5841 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5842 /* branch link and change to thumb (blx <offset>) */
5845 val
= (uint32_t)s
->pc
;
5847 tcg_gen_movi_i32(tmp
, val
);
5848 store_reg(s
, 14, tmp
);
5849 /* Sign-extend the 24-bit offset */
5850 offset
= (((int32_t)insn
) << 8) >> 8;
5851 /* offset * 4 + bit24 * 2 + (thumb bit) */
5852 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5853 /* pipeline offset */
5857 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5858 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5859 /* iWMMXt register transfer. */
5860 if (env
->cp15
.c15_cpar
& (1 << 1))
5861 if (!disas_iwmmxt_insn(env
, s
, insn
))
5864 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5865 /* Coprocessor double register transfer. */
5866 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5867 /* Additional coprocessor register transfer. */
5868 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5871 /* cps (privileged) */
5875 if (insn
& (1 << 19)) {
5876 if (insn
& (1 << 8))
5878 if (insn
& (1 << 7))
5880 if (insn
& (1 << 6))
5882 if (insn
& (1 << 18))
5885 if (insn
& (1 << 17)) {
5887 val
|= (insn
& 0x1f);
5890 gen_op_movl_T0_im(val
);
5891 gen_set_psr_T0(s
, mask
, 0);
5898 /* if not always execute, we generate a conditional jump to
5900 s
->condlabel
= gen_new_label();
5901 gen_test_cc(cond
^ 1, s
->condlabel
);
5904 if ((insn
& 0x0f900000) == 0x03000000) {
5905 if ((insn
& (1 << 21)) == 0) {
5907 rd
= (insn
>> 12) & 0xf;
5908 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5909 if ((insn
& (1 << 22)) == 0) {
5912 tcg_gen_movi_i32(tmp
, val
);
5915 tmp
= load_reg(s
, rd
);
5916 tcg_gen_ext16u_i32(tmp
, tmp
);
5917 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5919 store_reg(s
, rd
, tmp
);
5921 if (((insn
>> 12) & 0xf) != 0xf)
5923 if (((insn
>> 16) & 0xf) == 0) {
5924 gen_nop_hint(s
, insn
& 0xff);
5926 /* CPSR = immediate */
5928 shift
= ((insn
>> 8) & 0xf) * 2;
5930 val
= (val
>> shift
) | (val
<< (32 - shift
));
5931 gen_op_movl_T0_im(val
);
5932 i
= ((insn
& (1 << 22)) != 0);
5933 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5937 } else if ((insn
& 0x0f900000) == 0x01000000
5938 && (insn
& 0x00000090) != 0x00000090) {
5939 /* miscellaneous instructions */
5940 op1
= (insn
>> 21) & 3;
5941 sh
= (insn
>> 4) & 0xf;
5944 case 0x0: /* move program status register */
5947 gen_movl_T0_reg(s
, rm
);
5948 i
= ((op1
& 2) != 0);
5949 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5953 rd
= (insn
>> 12) & 0xf;
5957 tmp
= load_cpu_field(spsr
);
5960 gen_helper_cpsr_read(tmp
);
5962 store_reg(s
, rd
, tmp
);
5967 /* branch/exchange thumb (bx). */
5968 tmp
= load_reg(s
, rm
);
5970 } else if (op1
== 3) {
5972 rd
= (insn
>> 12) & 0xf;
5973 tmp
= load_reg(s
, rm
);
5974 gen_helper_clz(tmp
, tmp
);
5975 store_reg(s
, rd
, tmp
);
5983 /* Trivial implementation equivalent to bx. */
5984 tmp
= load_reg(s
, rm
);
5994 /* branch link/exchange thumb (blx) */
5995 tmp
= load_reg(s
, rm
);
5997 tcg_gen_movi_i32(tmp2
, s
->pc
);
5998 store_reg(s
, 14, tmp2
);
6001 case 0x5: /* saturating add/subtract */
6002 rd
= (insn
>> 12) & 0xf;
6003 rn
= (insn
>> 16) & 0xf;
6004 tmp
= load_reg(s
, rm
);
6005 tmp2
= load_reg(s
, rn
);
6007 gen_helper_double_saturate(tmp2
, tmp2
);
6009 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6011 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6013 store_reg(s
, rd
, tmp
);
6016 gen_set_condexec(s
);
6017 gen_set_pc_im(s
->pc
- 4);
6018 gen_exception(EXCP_BKPT
);
6019 s
->is_jmp
= DISAS_JUMP
;
6021 case 0x8: /* signed multiply */
6025 rs
= (insn
>> 8) & 0xf;
6026 rn
= (insn
>> 12) & 0xf;
6027 rd
= (insn
>> 16) & 0xf;
6029 /* (32 * 16) >> 16 */
6030 tmp
= load_reg(s
, rm
);
6031 tmp2
= load_reg(s
, rs
);
6033 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6036 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6037 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6039 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6040 if ((sh
& 2) == 0) {
6041 tmp2
= load_reg(s
, rn
);
6042 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6045 store_reg(s
, rd
, tmp
);
6048 tmp
= load_reg(s
, rm
);
6049 tmp2
= load_reg(s
, rs
);
6050 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6053 tmp64
= tcg_temp_new_i64();
6054 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6056 gen_addq(s
, tmp64
, rn
, rd
);
6057 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6060 tmp2
= load_reg(s
, rn
);
6061 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6064 store_reg(s
, rd
, tmp
);
6071 } else if (((insn
& 0x0e000000) == 0 &&
6072 (insn
& 0x00000090) != 0x90) ||
6073 ((insn
& 0x0e000000) == (1 << 25))) {
6074 int set_cc
, logic_cc
, shiftop
;
6076 op1
= (insn
>> 21) & 0xf;
6077 set_cc
= (insn
>> 20) & 1;
6078 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6080 /* data processing instruction */
6081 if (insn
& (1 << 25)) {
6082 /* immediate operand */
6084 shift
= ((insn
>> 8) & 0xf) * 2;
6086 val
= (val
>> shift
) | (val
<< (32 - shift
));
6089 tcg_gen_movi_i32(tmp2
, val
);
6090 if (logic_cc
&& shift
) {
6091 gen_set_CF_bit31(tmp2
);
6096 tmp2
= load_reg(s
, rm
);
6097 shiftop
= (insn
>> 5) & 3;
6098 if (!(insn
& (1 << 4))) {
6099 shift
= (insn
>> 7) & 0x1f;
6100 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6102 rs
= (insn
>> 8) & 0xf;
6103 tmp
= load_reg(s
, rs
);
6104 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6107 if (op1
!= 0x0f && op1
!= 0x0d) {
6108 rn
= (insn
>> 16) & 0xf;
6109 tmp
= load_reg(s
, rn
);
6113 rd
= (insn
>> 12) & 0xf;
6116 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6120 store_reg_bx(env
, s
, rd
, tmp
);
6123 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6127 store_reg_bx(env
, s
, rd
, tmp
);
6130 if (set_cc
&& rd
== 15) {
6131 /* SUBS r15, ... is used for exception return. */
6135 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6136 gen_exception_return(s
, tmp
);
6139 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6141 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6143 store_reg_bx(env
, s
, rd
, tmp
);
6148 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6150 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6152 store_reg_bx(env
, s
, rd
, tmp
);
6156 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6158 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6160 store_reg_bx(env
, s
, rd
, tmp
);
6164 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6166 gen_add_carry(tmp
, tmp
, tmp2
);
6168 store_reg_bx(env
, s
, rd
, tmp
);
6172 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6174 gen_sub_carry(tmp
, tmp
, tmp2
);
6176 store_reg_bx(env
, s
, rd
, tmp
);
6180 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6182 gen_sub_carry(tmp
, tmp2
, tmp
);
6184 store_reg_bx(env
, s
, rd
, tmp
);
6188 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6195 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6202 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6208 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6213 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6217 store_reg_bx(env
, s
, rd
, tmp
);
6220 if (logic_cc
&& rd
== 15) {
6221 /* MOVS r15, ... is used for exception return. */
6225 gen_exception_return(s
, tmp2
);
6230 store_reg_bx(env
, s
, rd
, tmp2
);
6234 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6238 store_reg_bx(env
, s
, rd
, tmp
);
6242 tcg_gen_not_i32(tmp2
, tmp2
);
6246 store_reg_bx(env
, s
, rd
, tmp2
);
6249 if (op1
!= 0x0f && op1
!= 0x0d) {
6253 /* other instructions */
6254 op1
= (insn
>> 24) & 0xf;
6258 /* multiplies, extra load/stores */
6259 sh
= (insn
>> 5) & 3;
6262 rd
= (insn
>> 16) & 0xf;
6263 rn
= (insn
>> 12) & 0xf;
6264 rs
= (insn
>> 8) & 0xf;
6266 op1
= (insn
>> 20) & 0xf;
6268 case 0: case 1: case 2: case 3: case 6:
6270 tmp
= load_reg(s
, rs
);
6271 tmp2
= load_reg(s
, rm
);
6272 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6274 if (insn
& (1 << 22)) {
6275 /* Subtract (mls) */
6277 tmp2
= load_reg(s
, rn
);
6278 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6280 } else if (insn
& (1 << 21)) {
6282 tmp2
= load_reg(s
, rn
);
6283 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6286 if (insn
& (1 << 20))
6288 store_reg(s
, rd
, tmp
);
6292 tmp
= load_reg(s
, rs
);
6293 tmp2
= load_reg(s
, rm
);
6294 if (insn
& (1 << 22))
6295 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6297 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6298 if (insn
& (1 << 21)) /* mult accumulate */
6299 gen_addq(s
, tmp64
, rn
, rd
);
6300 if (!(insn
& (1 << 23))) { /* double accumulate */
6302 gen_addq_lo(s
, tmp64
, rn
);
6303 gen_addq_lo(s
, tmp64
, rd
);
6305 if (insn
& (1 << 20))
6306 gen_logicq_cc(tmp64
);
6307 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6311 rn
= (insn
>> 16) & 0xf;
6312 rd
= (insn
>> 12) & 0xf;
6313 if (insn
& (1 << 23)) {
6314 /* load/store exclusive */
6315 op1
= (insn
>> 21) & 0x3;
6320 gen_movl_T1_reg(s
, rn
);
6322 if (insn
& (1 << 20)) {
6323 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6326 tmp
= gen_ld32(addr
, IS_USER(s
));
6328 case 1: /* ldrexd */
6329 tmp
= gen_ld32(addr
, IS_USER(s
));
6330 store_reg(s
, rd
, tmp
);
6331 tcg_gen_addi_i32(addr
, addr
, 4);
6332 tmp
= gen_ld32(addr
, IS_USER(s
));
6335 case 2: /* ldrexb */
6336 tmp
= gen_ld8u(addr
, IS_USER(s
));
6338 case 3: /* ldrexh */
6339 tmp
= gen_ld16u(addr
, IS_USER(s
));
6344 store_reg(s
, rd
, tmp
);
6346 int label
= gen_new_label();
6348 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6349 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6351 tmp
= load_reg(s
,rm
);
6354 gen_st32(tmp
, addr
, IS_USER(s
));
6356 case 1: /* strexd */
6357 gen_st32(tmp
, addr
, IS_USER(s
));
6358 tcg_gen_addi_i32(addr
, addr
, 4);
6359 tmp
= load_reg(s
, rm
+ 1);
6360 gen_st32(tmp
, addr
, IS_USER(s
));
6362 case 2: /* strexb */
6363 gen_st8(tmp
, addr
, IS_USER(s
));
6365 case 3: /* strexh */
6366 gen_st16(tmp
, addr
, IS_USER(s
));
6371 gen_set_label(label
);
6372 gen_movl_reg_T0(s
, rd
);
6375 /* SWP instruction */
6378 /* ??? This is not really atomic. However we know
6379 we never have multiple CPUs running in parallel,
6380 so it is good enough. */
6381 addr
= load_reg(s
, rn
);
6382 tmp
= load_reg(s
, rm
);
6383 if (insn
& (1 << 22)) {
6384 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6385 gen_st8(tmp
, addr
, IS_USER(s
));
6387 tmp2
= gen_ld32(addr
, IS_USER(s
));
6388 gen_st32(tmp
, addr
, IS_USER(s
));
6391 store_reg(s
, rd
, tmp2
);
6397 /* Misc load/store */
6398 rn
= (insn
>> 16) & 0xf;
6399 rd
= (insn
>> 12) & 0xf;
6400 addr
= load_reg(s
, rn
);
6401 if (insn
& (1 << 24))
6402 gen_add_datah_offset(s
, insn
, 0, addr
);
6404 if (insn
& (1 << 20)) {
6408 tmp
= gen_ld16u(addr
, IS_USER(s
));
6411 tmp
= gen_ld8s(addr
, IS_USER(s
));
6415 tmp
= gen_ld16s(addr
, IS_USER(s
));
6419 } else if (sh
& 2) {
6423 tmp
= load_reg(s
, rd
);
6424 gen_st32(tmp
, addr
, IS_USER(s
));
6425 tcg_gen_addi_i32(addr
, addr
, 4);
6426 tmp
= load_reg(s
, rd
+ 1);
6427 gen_st32(tmp
, addr
, IS_USER(s
));
6431 tmp
= gen_ld32(addr
, IS_USER(s
));
6432 store_reg(s
, rd
, tmp
);
6433 tcg_gen_addi_i32(addr
, addr
, 4);
6434 tmp
= gen_ld32(addr
, IS_USER(s
));
6438 address_offset
= -4;
6441 tmp
= load_reg(s
, rd
);
6442 gen_st16(tmp
, addr
, IS_USER(s
));
6445 /* Perform base writeback before the loaded value to
6446 ensure correct behavior with overlapping index registers.
6447 ldrd with base writeback is is undefined if the
6448 destination and index registers overlap. */
6449 if (!(insn
& (1 << 24))) {
6450 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6451 store_reg(s
, rn
, addr
);
6452 } else if (insn
& (1 << 21)) {
6454 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6455 store_reg(s
, rn
, addr
);
6460 /* Complete the load. */
6461 store_reg(s
, rd
, tmp
);
6470 if (insn
& (1 << 4)) {
6472 /* Armv6 Media instructions. */
6474 rn
= (insn
>> 16) & 0xf;
6475 rd
= (insn
>> 12) & 0xf;
6476 rs
= (insn
>> 8) & 0xf;
6477 switch ((insn
>> 23) & 3) {
6478 case 0: /* Parallel add/subtract. */
6479 op1
= (insn
>> 20) & 7;
6480 tmp
= load_reg(s
, rn
);
6481 tmp2
= load_reg(s
, rm
);
6482 sh
= (insn
>> 5) & 7;
6483 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6485 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6487 store_reg(s
, rd
, tmp
);
6490 if ((insn
& 0x00700020) == 0) {
6491 /* Halfword pack. */
6492 tmp
= load_reg(s
, rn
);
6493 tmp2
= load_reg(s
, rm
);
6494 shift
= (insn
>> 7) & 0x1f;
6495 if (insn
& (1 << 6)) {
6499 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6500 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6501 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6505 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6506 tcg_gen_ext16u_i32(tmp
, tmp
);
6507 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6509 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6511 store_reg(s
, rd
, tmp
);
6512 } else if ((insn
& 0x00200020) == 0x00200000) {
6514 tmp
= load_reg(s
, rm
);
6515 shift
= (insn
>> 7) & 0x1f;
6516 if (insn
& (1 << 6)) {
6519 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6521 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6523 sh
= (insn
>> 16) & 0x1f;
6525 if (insn
& (1 << 22))
6526 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6528 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6530 store_reg(s
, rd
, tmp
);
6531 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6533 tmp
= load_reg(s
, rm
);
6534 sh
= (insn
>> 16) & 0x1f;
6536 if (insn
& (1 << 22))
6537 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6539 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6541 store_reg(s
, rd
, tmp
);
6542 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6544 tmp
= load_reg(s
, rn
);
6545 tmp2
= load_reg(s
, rm
);
6547 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6548 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6551 store_reg(s
, rd
, tmp
);
6552 } else if ((insn
& 0x000003e0) == 0x00000060) {
6553 tmp
= load_reg(s
, rm
);
6554 shift
= (insn
>> 10) & 3;
6555 /* ??? In many cases it's not neccessary to do a
6556 rotate, a shift is sufficient. */
6558 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6559 op1
= (insn
>> 20) & 7;
6561 case 0: gen_sxtb16(tmp
); break;
6562 case 2: gen_sxtb(tmp
); break;
6563 case 3: gen_sxth(tmp
); break;
6564 case 4: gen_uxtb16(tmp
); break;
6565 case 6: gen_uxtb(tmp
); break;
6566 case 7: gen_uxth(tmp
); break;
6567 default: goto illegal_op
;
6570 tmp2
= load_reg(s
, rn
);
6571 if ((op1
& 3) == 0) {
6572 gen_add16(tmp
, tmp2
);
6574 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6578 store_reg(s
, rd
, tmp
);
6579 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6581 tmp
= load_reg(s
, rm
);
6582 if (insn
& (1 << 22)) {
6583 if (insn
& (1 << 7)) {
6587 gen_helper_rbit(tmp
, tmp
);
6590 if (insn
& (1 << 7))
6593 tcg_gen_bswap32_i32(tmp
, tmp
);
6595 store_reg(s
, rd
, tmp
);
6600 case 2: /* Multiplies (Type 3). */
6601 tmp
= load_reg(s
, rm
);
6602 tmp2
= load_reg(s
, rs
);
6603 if (insn
& (1 << 20)) {
6604 /* Signed multiply most significant [accumulate]. */
6605 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6606 if (insn
& (1 << 5))
6607 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6608 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6610 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6612 tmp2
= load_reg(s
, rd
);
6613 if (insn
& (1 << 6)) {
6614 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6616 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6620 store_reg(s
, rn
, tmp
);
6622 if (insn
& (1 << 5))
6623 gen_swap_half(tmp2
);
6624 gen_smul_dual(tmp
, tmp2
);
6625 /* This addition cannot overflow. */
6626 if (insn
& (1 << 6)) {
6627 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6629 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6632 if (insn
& (1 << 22)) {
6633 /* smlald, smlsld */
6634 tmp64
= tcg_temp_new_i64();
6635 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6637 gen_addq(s
, tmp64
, rd
, rn
);
6638 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6640 /* smuad, smusd, smlad, smlsd */
6643 tmp2
= load_reg(s
, rd
);
6644 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6647 store_reg(s
, rn
, tmp
);
6652 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6654 case 0: /* Unsigned sum of absolute differences. */
6656 tmp
= load_reg(s
, rm
);
6657 tmp2
= load_reg(s
, rs
);
6658 gen_helper_usad8(tmp
, tmp
, tmp2
);
6661 tmp2
= load_reg(s
, rd
);
6662 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6665 store_reg(s
, rn
, tmp
);
6667 case 0x20: case 0x24: case 0x28: case 0x2c:
6668 /* Bitfield insert/clear. */
6670 shift
= (insn
>> 7) & 0x1f;
6671 i
= (insn
>> 16) & 0x1f;
6675 tcg_gen_movi_i32(tmp
, 0);
6677 tmp
= load_reg(s
, rm
);
6680 tmp2
= load_reg(s
, rd
);
6681 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6684 store_reg(s
, rd
, tmp
);
6686 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6687 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6689 tmp
= load_reg(s
, rm
);
6690 shift
= (insn
>> 7) & 0x1f;
6691 i
= ((insn
>> 16) & 0x1f) + 1;
6696 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6698 gen_sbfx(tmp
, shift
, i
);
6701 store_reg(s
, rd
, tmp
);
6711 /* Check for undefined extension instructions
6712 * per the ARM Bible IE:
6713 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6715 sh
= (0xf << 20) | (0xf << 4);
6716 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6720 /* load/store byte/word */
6721 rn
= (insn
>> 16) & 0xf;
6722 rd
= (insn
>> 12) & 0xf;
6723 tmp2
= load_reg(s
, rn
);
6724 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6725 if (insn
& (1 << 24))
6726 gen_add_data_offset(s
, insn
, tmp2
);
6727 if (insn
& (1 << 20)) {
6729 if (insn
& (1 << 22)) {
6730 tmp
= gen_ld8u(tmp2
, i
);
6732 tmp
= gen_ld32(tmp2
, i
);
6736 tmp
= load_reg(s
, rd
);
6737 if (insn
& (1 << 22))
6738 gen_st8(tmp
, tmp2
, i
);
6740 gen_st32(tmp
, tmp2
, i
);
6742 if (!(insn
& (1 << 24))) {
6743 gen_add_data_offset(s
, insn
, tmp2
);
6744 store_reg(s
, rn
, tmp2
);
6745 } else if (insn
& (1 << 21)) {
6746 store_reg(s
, rn
, tmp2
);
6750 if (insn
& (1 << 20)) {
6751 /* Complete the load. */
6755 store_reg(s
, rd
, tmp
);
6761 int j
, n
, user
, loaded_base
;
6763 /* load/store multiple words */
6764 /* XXX: store correct base if write back */
6766 if (insn
& (1 << 22)) {
6768 goto illegal_op
; /* only usable in supervisor mode */
6770 if ((insn
& (1 << 15)) == 0)
6773 rn
= (insn
>> 16) & 0xf;
6774 addr
= load_reg(s
, rn
);
6776 /* compute total size */
6778 TCGV_UNUSED(loaded_var
);
6781 if (insn
& (1 << i
))
6784 /* XXX: test invalid n == 0 case ? */
6785 if (insn
& (1 << 23)) {
6786 if (insn
& (1 << 24)) {
6788 tcg_gen_addi_i32(addr
, addr
, 4);
6790 /* post increment */
6793 if (insn
& (1 << 24)) {
6795 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6797 /* post decrement */
6799 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6804 if (insn
& (1 << i
)) {
6805 if (insn
& (1 << 20)) {
6807 tmp
= gen_ld32(addr
, IS_USER(s
));
6811 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6813 } else if (i
== rn
) {
6817 store_reg(s
, i
, tmp
);
6822 /* special case: r15 = PC + 8 */
6823 val
= (long)s
->pc
+ 4;
6825 tcg_gen_movi_i32(tmp
, val
);
6828 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6830 tmp
= load_reg(s
, i
);
6832 gen_st32(tmp
, addr
, IS_USER(s
));
6835 /* no need to add after the last transfer */
6837 tcg_gen_addi_i32(addr
, addr
, 4);
6840 if (insn
& (1 << 21)) {
6842 if (insn
& (1 << 23)) {
6843 if (insn
& (1 << 24)) {
6846 /* post increment */
6847 tcg_gen_addi_i32(addr
, addr
, 4);
6850 if (insn
& (1 << 24)) {
6853 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6855 /* post decrement */
6856 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6859 store_reg(s
, rn
, addr
);
6864 store_reg(s
, rn
, loaded_var
);
6866 if ((insn
& (1 << 22)) && !user
) {
6867 /* Restore CPSR from SPSR. */
6868 tmp
= load_cpu_field(spsr
);
6869 gen_set_cpsr(tmp
, 0xffffffff);
6871 s
->is_jmp
= DISAS_UPDATE
;
6880 /* branch (and link) */
6881 val
= (int32_t)s
->pc
;
6882 if (insn
& (1 << 24)) {
6884 tcg_gen_movi_i32(tmp
, val
);
6885 store_reg(s
, 14, tmp
);
6887 offset
= (((int32_t)insn
<< 8) >> 8);
6888 val
+= (offset
<< 2) + 4;
6896 if (disas_coproc_insn(env
, s
, insn
))
6901 gen_set_pc_im(s
->pc
);
6902 s
->is_jmp
= DISAS_SWI
;
6906 gen_set_condexec(s
);
6907 gen_set_pc_im(s
->pc
- 4);
6908 gen_exception(EXCP_UDEF
);
6909 s
->is_jmp
= DISAS_JUMP
;
6915 /* Return true if this is a Thumb-2 logical op. */
6917 thumb2_logic_op(int op
)
6922 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6923 then set condition code flags based on the result of the operation.
6924 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6925 to the high bit of T1.
6926 Returns zero if the opcode is valid. */
6929 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6936 gen_op_andl_T0_T1();
6940 gen_op_bicl_T0_T1();
6953 gen_op_xorl_T0_T1();
6958 gen_op_addl_T0_T1_cc();
6960 gen_op_addl_T0_T1();
6964 gen_op_adcl_T0_T1_cc();
6970 gen_op_sbcl_T0_T1_cc();
6976 gen_op_subl_T0_T1_cc();
6978 gen_op_subl_T0_T1();
6982 gen_op_rsbl_T0_T1_cc();
6984 gen_op_rsbl_T0_T1();
6986 default: /* 5, 6, 7, 9, 12, 15. */
6990 gen_op_logic_T0_cc();
6992 gen_set_CF_bit31(cpu_T
[1]);
6997 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6999 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7001 uint32_t insn
, imm
, shift
, offset
;
7002 uint32_t rd
, rn
, rm
, rs
;
7013 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7014 || arm_feature (env
, ARM_FEATURE_M
))) {
7015 /* Thumb-1 cores may need to treat bl and blx as a pair of
7016 16-bit instructions to get correct prefetch abort behavior. */
7018 if ((insn
& (1 << 12)) == 0) {
7019 /* Second half of blx. */
7020 offset
= ((insn
& 0x7ff) << 1);
7021 tmp
= load_reg(s
, 14);
7022 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7023 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7026 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7027 store_reg(s
, 14, tmp2
);
7031 if (insn
& (1 << 11)) {
7032 /* Second half of bl. */
7033 offset
= ((insn
& 0x7ff) << 1) | 1;
7034 tmp
= load_reg(s
, 14);
7035 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7038 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7039 store_reg(s
, 14, tmp2
);
7043 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7044 /* Instruction spans a page boundary. Implement it as two
7045 16-bit instructions in case the second half causes an
7047 offset
= ((int32_t)insn
<< 21) >> 9;
7048 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
7049 gen_movl_reg_T0(s
, 14);
7052 /* Fall through to 32-bit decode. */
7055 insn
= lduw_code(s
->pc
);
7057 insn
|= (uint32_t)insn_hw1
<< 16;
7059 if ((insn
& 0xf800e800) != 0xf000e800) {
7063 rn
= (insn
>> 16) & 0xf;
7064 rs
= (insn
>> 12) & 0xf;
7065 rd
= (insn
>> 8) & 0xf;
7067 switch ((insn
>> 25) & 0xf) {
7068 case 0: case 1: case 2: case 3:
7069 /* 16-bit instructions. Should never happen. */
7072 if (insn
& (1 << 22)) {
7073 /* Other load/store, table branch. */
7074 if (insn
& 0x01200000) {
7075 /* Load/store doubleword. */
7078 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7080 addr
= load_reg(s
, rn
);
7082 offset
= (insn
& 0xff) * 4;
7083 if ((insn
& (1 << 23)) == 0)
7085 if (insn
& (1 << 24)) {
7086 tcg_gen_addi_i32(addr
, addr
, offset
);
7089 if (insn
& (1 << 20)) {
7091 tmp
= gen_ld32(addr
, IS_USER(s
));
7092 store_reg(s
, rs
, tmp
);
7093 tcg_gen_addi_i32(addr
, addr
, 4);
7094 tmp
= gen_ld32(addr
, IS_USER(s
));
7095 store_reg(s
, rd
, tmp
);
7098 tmp
= load_reg(s
, rs
);
7099 gen_st32(tmp
, addr
, IS_USER(s
));
7100 tcg_gen_addi_i32(addr
, addr
, 4);
7101 tmp
= load_reg(s
, rd
);
7102 gen_st32(tmp
, addr
, IS_USER(s
));
7104 if (insn
& (1 << 21)) {
7105 /* Base writeback. */
7108 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7109 store_reg(s
, rn
, addr
);
7113 } else if ((insn
& (1 << 23)) == 0) {
7114 /* Load/store exclusive word. */
7115 gen_movl_T1_reg(s
, rn
);
7117 if (insn
& (1 << 20)) {
7118 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
7119 tmp
= gen_ld32(addr
, IS_USER(s
));
7120 store_reg(s
, rd
, tmp
);
7122 int label
= gen_new_label();
7123 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7124 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
7126 tmp
= load_reg(s
, rs
);
7127 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7128 gen_set_label(label
);
7129 gen_movl_reg_T0(s
, rd
);
7131 } else if ((insn
& (1 << 6)) == 0) {
7135 tcg_gen_movi_i32(addr
, s
->pc
);
7137 addr
= load_reg(s
, rn
);
7139 tmp
= load_reg(s
, rm
);
7140 tcg_gen_add_i32(addr
, addr
, tmp
);
7141 if (insn
& (1 << 4)) {
7143 tcg_gen_add_i32(addr
, addr
, tmp
);
7145 tmp
= gen_ld16u(addr
, IS_USER(s
));
7148 tmp
= gen_ld8u(addr
, IS_USER(s
));
7151 tcg_gen_shli_i32(tmp
, tmp
, 1);
7152 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7153 store_reg(s
, 15, tmp
);
7155 /* Load/store exclusive byte/halfword/doubleword. */
7156 /* ??? These are not really atomic. However we know
7157 we never have multiple CPUs running in parallel,
7158 so it is good enough. */
7159 op
= (insn
>> 4) & 0x3;
7160 /* Must use a global reg for the address because we have
7161 a conditional branch in the store instruction. */
7162 gen_movl_T1_reg(s
, rn
);
7164 if (insn
& (1 << 20)) {
7165 gen_helper_mark_exclusive(cpu_env
, addr
);
7168 tmp
= gen_ld8u(addr
, IS_USER(s
));
7171 tmp
= gen_ld16u(addr
, IS_USER(s
));
7174 tmp
= gen_ld32(addr
, IS_USER(s
));
7175 tcg_gen_addi_i32(addr
, addr
, 4);
7176 tmp2
= gen_ld32(addr
, IS_USER(s
));
7177 store_reg(s
, rd
, tmp2
);
7182 store_reg(s
, rs
, tmp
);
7184 int label
= gen_new_label();
7185 /* Must use a global that is not killed by the branch. */
7186 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7187 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7188 tmp
= load_reg(s
, rs
);
7191 gen_st8(tmp
, addr
, IS_USER(s
));
7194 gen_st16(tmp
, addr
, IS_USER(s
));
7197 gen_st32(tmp
, addr
, IS_USER(s
));
7198 tcg_gen_addi_i32(addr
, addr
, 4);
7199 tmp
= load_reg(s
, rd
);
7200 gen_st32(tmp
, addr
, IS_USER(s
));
7205 gen_set_label(label
);
7206 gen_movl_reg_T0(s
, rm
);
7210 /* Load/store multiple, RFE, SRS. */
7211 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7212 /* Not available in user mode. */
7215 if (insn
& (1 << 20)) {
7217 addr
= load_reg(s
, rn
);
7218 if ((insn
& (1 << 24)) == 0)
7219 tcg_gen_addi_i32(addr
, addr
, -8);
7220 /* Load PC into tmp and CPSR into tmp2. */
7221 tmp
= gen_ld32(addr
, 0);
7222 tcg_gen_addi_i32(addr
, addr
, 4);
7223 tmp2
= gen_ld32(addr
, 0);
7224 if (insn
& (1 << 21)) {
7225 /* Base writeback. */
7226 if (insn
& (1 << 24)) {
7227 tcg_gen_addi_i32(addr
, addr
, 4);
7229 tcg_gen_addi_i32(addr
, addr
, -4);
7231 store_reg(s
, rn
, addr
);
7235 gen_rfe(s
, tmp
, tmp2
);
7239 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7240 addr
= load_reg(s
, 13);
7243 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7245 if ((insn
& (1 << 24)) == 0) {
7246 tcg_gen_addi_i32(addr
, addr
, -8);
7248 tmp
= load_reg(s
, 14);
7249 gen_st32(tmp
, addr
, 0);
7250 tcg_gen_addi_i32(addr
, addr
, 4);
7252 gen_helper_cpsr_read(tmp
);
7253 gen_st32(tmp
, addr
, 0);
7254 if (insn
& (1 << 21)) {
7255 if ((insn
& (1 << 24)) == 0) {
7256 tcg_gen_addi_i32(addr
, addr
, -4);
7258 tcg_gen_addi_i32(addr
, addr
, 4);
7260 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7261 store_reg(s
, 13, addr
);
7263 gen_helper_set_r13_banked(cpu_env
,
7264 tcg_const_i32(op
), addr
);
7272 /* Load/store multiple. */
7273 addr
= load_reg(s
, rn
);
7275 for (i
= 0; i
< 16; i
++) {
7276 if (insn
& (1 << i
))
7279 if (insn
& (1 << 24)) {
7280 tcg_gen_addi_i32(addr
, addr
, -offset
);
7283 for (i
= 0; i
< 16; i
++) {
7284 if ((insn
& (1 << i
)) == 0)
7286 if (insn
& (1 << 20)) {
7288 tmp
= gen_ld32(addr
, IS_USER(s
));
7292 store_reg(s
, i
, tmp
);
7296 tmp
= load_reg(s
, i
);
7297 gen_st32(tmp
, addr
, IS_USER(s
));
7299 tcg_gen_addi_i32(addr
, addr
, 4);
7301 if (insn
& (1 << 21)) {
7302 /* Base register writeback. */
7303 if (insn
& (1 << 24)) {
7304 tcg_gen_addi_i32(addr
, addr
, -offset
);
7306 /* Fault if writeback register is in register list. */
7307 if (insn
& (1 << rn
))
7309 store_reg(s
, rn
, addr
);
7316 case 5: /* Data processing register constant shift. */
7318 gen_op_movl_T0_im(0);
7320 gen_movl_T0_reg(s
, rn
);
7321 gen_movl_T1_reg(s
, rm
);
7322 op
= (insn
>> 21) & 0xf;
7323 shiftop
= (insn
>> 4) & 3;
7324 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7325 conds
= (insn
& (1 << 20)) != 0;
7326 logic_cc
= (conds
&& thumb2_logic_op(op
));
7327 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7328 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7331 gen_movl_reg_T0(s
, rd
);
7333 case 13: /* Misc data processing. */
7334 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7335 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7338 case 0: /* Register controlled shift. */
7339 tmp
= load_reg(s
, rn
);
7340 tmp2
= load_reg(s
, rm
);
7341 if ((insn
& 0x70) != 0)
7343 op
= (insn
>> 21) & 3;
7344 logic_cc
= (insn
& (1 << 20)) != 0;
7345 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7348 store_reg_bx(env
, s
, rd
, tmp
);
7350 case 1: /* Sign/zero extend. */
7351 tmp
= load_reg(s
, rm
);
7352 shift
= (insn
>> 4) & 3;
7353 /* ??? In many cases it's not neccessary to do a
7354 rotate, a shift is sufficient. */
7356 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7357 op
= (insn
>> 20) & 7;
7359 case 0: gen_sxth(tmp
); break;
7360 case 1: gen_uxth(tmp
); break;
7361 case 2: gen_sxtb16(tmp
); break;
7362 case 3: gen_uxtb16(tmp
); break;
7363 case 4: gen_sxtb(tmp
); break;
7364 case 5: gen_uxtb(tmp
); break;
7365 default: goto illegal_op
;
7368 tmp2
= load_reg(s
, rn
);
7369 if ((op
>> 1) == 1) {
7370 gen_add16(tmp
, tmp2
);
7372 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7376 store_reg(s
, rd
, tmp
);
7378 case 2: /* SIMD add/subtract. */
7379 op
= (insn
>> 20) & 7;
7380 shift
= (insn
>> 4) & 7;
7381 if ((op
& 3) == 3 || (shift
& 3) == 3)
7383 tmp
= load_reg(s
, rn
);
7384 tmp2
= load_reg(s
, rm
);
7385 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7387 store_reg(s
, rd
, tmp
);
7389 case 3: /* Other data processing. */
7390 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7392 /* Saturating add/subtract. */
7393 tmp
= load_reg(s
, rn
);
7394 tmp2
= load_reg(s
, rm
);
7396 gen_helper_double_saturate(tmp
, tmp
);
7398 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7400 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7403 tmp
= load_reg(s
, rn
);
7405 case 0x0a: /* rbit */
7406 gen_helper_rbit(tmp
, tmp
);
7408 case 0x08: /* rev */
7409 tcg_gen_bswap32_i32(tmp
, tmp
);
7411 case 0x09: /* rev16 */
7414 case 0x0b: /* revsh */
7417 case 0x10: /* sel */
7418 tmp2
= load_reg(s
, rm
);
7420 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7421 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7425 case 0x18: /* clz */
7426 gen_helper_clz(tmp
, tmp
);
7432 store_reg(s
, rd
, tmp
);
7434 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7435 op
= (insn
>> 4) & 0xf;
7436 tmp
= load_reg(s
, rn
);
7437 tmp2
= load_reg(s
, rm
);
7438 switch ((insn
>> 20) & 7) {
7439 case 0: /* 32 x 32 -> 32 */
7440 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7443 tmp2
= load_reg(s
, rs
);
7445 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7447 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7451 case 1: /* 16 x 16 -> 32 */
7452 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7455 tmp2
= load_reg(s
, rs
);
7456 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7460 case 2: /* Dual multiply add. */
7461 case 4: /* Dual multiply subtract. */
7463 gen_swap_half(tmp2
);
7464 gen_smul_dual(tmp
, tmp2
);
7465 /* This addition cannot overflow. */
7466 if (insn
& (1 << 22)) {
7467 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7469 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7474 tmp2
= load_reg(s
, rs
);
7475 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7479 case 3: /* 32 * 16 -> 32msb */
7481 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7484 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7485 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7487 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7490 tmp2
= load_reg(s
, rs
);
7491 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7495 case 5: case 6: /* 32 * 32 -> 32msb */
7496 gen_imull(tmp
, tmp2
);
7497 if (insn
& (1 << 5)) {
7498 gen_roundqd(tmp
, tmp2
);
7505 tmp2
= load_reg(s
, rs
);
7506 if (insn
& (1 << 21)) {
7507 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7509 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7514 case 7: /* Unsigned sum of absolute differences. */
7515 gen_helper_usad8(tmp
, tmp
, tmp2
);
7518 tmp2
= load_reg(s
, rs
);
7519 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7524 store_reg(s
, rd
, tmp
);
7526 case 6: case 7: /* 64-bit multiply, Divide. */
7527 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7528 tmp
= load_reg(s
, rn
);
7529 tmp2
= load_reg(s
, rm
);
7530 if ((op
& 0x50) == 0x10) {
7532 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7535 gen_helper_udiv(tmp
, tmp
, tmp2
);
7537 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7539 store_reg(s
, rd
, tmp
);
7540 } else if ((op
& 0xe) == 0xc) {
7541 /* Dual multiply accumulate long. */
7543 gen_swap_half(tmp2
);
7544 gen_smul_dual(tmp
, tmp2
);
7546 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7548 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7552 tmp64
= tcg_temp_new_i64();
7553 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7555 gen_addq(s
, tmp64
, rs
, rd
);
7556 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7559 /* Unsigned 64-bit multiply */
7560 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7564 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7566 tmp64
= tcg_temp_new_i64();
7567 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7570 /* Signed 64-bit multiply */
7571 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7576 gen_addq_lo(s
, tmp64
, rs
);
7577 gen_addq_lo(s
, tmp64
, rd
);
7578 } else if (op
& 0x40) {
7579 /* 64-bit accumulate. */
7580 gen_addq(s
, tmp64
, rs
, rd
);
7582 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7587 case 6: case 7: case 14: case 15:
7589 if (((insn
>> 24) & 3) == 3) {
7590 /* Translate into the equivalent ARM encoding. */
7591 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7592 if (disas_neon_data_insn(env
, s
, insn
))
7595 if (insn
& (1 << 28))
7597 if (disas_coproc_insn (env
, s
, insn
))
7601 case 8: case 9: case 10: case 11:
7602 if (insn
& (1 << 15)) {
7603 /* Branches, misc control. */
7604 if (insn
& 0x5000) {
7605 /* Unconditional branch. */
7606 /* signextend(hw1[10:0]) -> offset[:12]. */
7607 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7608 /* hw1[10:0] -> offset[11:1]. */
7609 offset
|= (insn
& 0x7ff) << 1;
7610 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7611 offset[24:22] already have the same value because of the
7612 sign extension above. */
7613 offset
^= ((~insn
) & (1 << 13)) << 10;
7614 offset
^= ((~insn
) & (1 << 11)) << 11;
7616 if (insn
& (1 << 14)) {
7617 /* Branch and link. */
7618 gen_op_movl_T1_im(s
->pc
| 1);
7619 gen_movl_reg_T1(s
, 14);
7623 if (insn
& (1 << 12)) {
7628 offset
&= ~(uint32_t)2;
7629 gen_bx_im(s
, offset
);
7631 } else if (((insn
>> 23) & 7) == 7) {
7633 if (insn
& (1 << 13))
7636 if (insn
& (1 << 26)) {
7637 /* Secure monitor call (v6Z) */
7638 goto illegal_op
; /* not implemented. */
7640 op
= (insn
>> 20) & 7;
7642 case 0: /* msr cpsr. */
7644 tmp
= load_reg(s
, rn
);
7645 addr
= tcg_const_i32(insn
& 0xff);
7646 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7651 case 1: /* msr spsr. */
7654 gen_movl_T0_reg(s
, rn
);
7655 if (gen_set_psr_T0(s
,
7656 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7660 case 2: /* cps, nop-hint. */
7661 if (((insn
>> 8) & 7) == 0) {
7662 gen_nop_hint(s
, insn
& 0xff);
7664 /* Implemented as NOP in user mode. */
7669 if (insn
& (1 << 10)) {
7670 if (insn
& (1 << 7))
7672 if (insn
& (1 << 6))
7674 if (insn
& (1 << 5))
7676 if (insn
& (1 << 9))
7677 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7679 if (insn
& (1 << 8)) {
7681 imm
|= (insn
& 0x1f);
7684 gen_op_movl_T0_im(imm
);
7685 gen_set_psr_T0(s
, offset
, 0);
7688 case 3: /* Special control operations. */
7689 op
= (insn
>> 4) & 0xf;
7692 gen_helper_clrex(cpu_env
);
7697 /* These execute as NOPs. */
7705 /* Trivial implementation equivalent to bx. */
7706 tmp
= load_reg(s
, rn
);
7709 case 5: /* Exception return. */
7710 /* Unpredictable in user mode. */
7712 case 6: /* mrs cpsr. */
7715 addr
= tcg_const_i32(insn
& 0xff);
7716 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7718 gen_helper_cpsr_read(tmp
);
7720 store_reg(s
, rd
, tmp
);
7722 case 7: /* mrs spsr. */
7723 /* Not accessible in user mode. */
7724 if (IS_USER(s
) || IS_M(env
))
7726 tmp
= load_cpu_field(spsr
);
7727 store_reg(s
, rd
, tmp
);
7732 /* Conditional branch. */
7733 op
= (insn
>> 22) & 0xf;
7734 /* Generate a conditional jump to next instruction. */
7735 s
->condlabel
= gen_new_label();
7736 gen_test_cc(op
^ 1, s
->condlabel
);
7739 /* offset[11:1] = insn[10:0] */
7740 offset
= (insn
& 0x7ff) << 1;
7741 /* offset[17:12] = insn[21:16]. */
7742 offset
|= (insn
& 0x003f0000) >> 4;
7743 /* offset[31:20] = insn[26]. */
7744 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7745 /* offset[18] = insn[13]. */
7746 offset
|= (insn
& (1 << 13)) << 5;
7747 /* offset[19] = insn[11]. */
7748 offset
|= (insn
& (1 << 11)) << 8;
7750 /* jump to the offset */
7751 gen_jmp(s
, s
->pc
+ offset
);
7754 /* Data processing immediate. */
7755 if (insn
& (1 << 25)) {
7756 if (insn
& (1 << 24)) {
7757 if (insn
& (1 << 20))
7759 /* Bitfield/Saturate. */
7760 op
= (insn
>> 21) & 7;
7762 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7765 tcg_gen_movi_i32(tmp
, 0);
7767 tmp
= load_reg(s
, rn
);
7770 case 2: /* Signed bitfield extract. */
7772 if (shift
+ imm
> 32)
7775 gen_sbfx(tmp
, shift
, imm
);
7777 case 6: /* Unsigned bitfield extract. */
7779 if (shift
+ imm
> 32)
7782 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7784 case 3: /* Bitfield insert/clear. */
7787 imm
= imm
+ 1 - shift
;
7789 tmp2
= load_reg(s
, rd
);
7790 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7796 default: /* Saturate. */
7799 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7801 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7803 tmp2
= tcg_const_i32(imm
);
7806 if ((op
& 1) && shift
== 0)
7807 gen_helper_usat16(tmp
, tmp
, tmp2
);
7809 gen_helper_usat(tmp
, tmp
, tmp2
);
7812 if ((op
& 1) && shift
== 0)
7813 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7815 gen_helper_ssat(tmp
, tmp
, tmp2
);
7819 store_reg(s
, rd
, tmp
);
7821 imm
= ((insn
& 0x04000000) >> 15)
7822 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7823 if (insn
& (1 << 22)) {
7824 /* 16-bit immediate. */
7825 imm
|= (insn
>> 4) & 0xf000;
7826 if (insn
& (1 << 23)) {
7828 tmp
= load_reg(s
, rd
);
7829 tcg_gen_ext16u_i32(tmp
, tmp
);
7830 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7834 tcg_gen_movi_i32(tmp
, imm
);
7837 /* Add/sub 12-bit immediate. */
7839 offset
= s
->pc
& ~(uint32_t)3;
7840 if (insn
& (1 << 23))
7845 tcg_gen_movi_i32(tmp
, offset
);
7847 tmp
= load_reg(s
, rn
);
7848 if (insn
& (1 << 23))
7849 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7851 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7854 store_reg(s
, rd
, tmp
);
7857 int shifter_out
= 0;
7858 /* modified 12-bit immediate. */
7859 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7860 imm
= (insn
& 0xff);
7863 /* Nothing to do. */
7865 case 1: /* 00XY00XY */
7868 case 2: /* XY00XY00 */
7872 case 3: /* XYXYXYXY */
7876 default: /* Rotated constant. */
7877 shift
= (shift
<< 1) | (imm
>> 7);
7879 imm
= imm
<< (32 - shift
);
7883 gen_op_movl_T1_im(imm
);
7884 rn
= (insn
>> 16) & 0xf;
7886 gen_op_movl_T0_im(0);
7888 gen_movl_T0_reg(s
, rn
);
7889 op
= (insn
>> 21) & 0xf;
7890 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7893 rd
= (insn
>> 8) & 0xf;
7895 gen_movl_reg_T0(s
, rd
);
7900 case 12: /* Load/store single data item. */
7905 if ((insn
& 0x01100000) == 0x01000000) {
7906 if (disas_neon_ls_insn(env
, s
, insn
))
7914 /* s->pc has already been incremented by 4. */
7915 imm
= s
->pc
& 0xfffffffc;
7916 if (insn
& (1 << 23))
7917 imm
+= insn
& 0xfff;
7919 imm
-= insn
& 0xfff;
7920 tcg_gen_movi_i32(addr
, imm
);
7922 addr
= load_reg(s
, rn
);
7923 if (insn
& (1 << 23)) {
7924 /* Positive offset. */
7926 tcg_gen_addi_i32(addr
, addr
, imm
);
7928 op
= (insn
>> 8) & 7;
7931 case 0: case 8: /* Shifted Register. */
7932 shift
= (insn
>> 4) & 0xf;
7935 tmp
= load_reg(s
, rm
);
7937 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7938 tcg_gen_add_i32(addr
, addr
, tmp
);
7941 case 4: /* Negative offset. */
7942 tcg_gen_addi_i32(addr
, addr
, -imm
);
7944 case 6: /* User privilege. */
7945 tcg_gen_addi_i32(addr
, addr
, imm
);
7948 case 1: /* Post-decrement. */
7951 case 3: /* Post-increment. */
7955 case 5: /* Pre-decrement. */
7958 case 7: /* Pre-increment. */
7959 tcg_gen_addi_i32(addr
, addr
, imm
);
7967 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7968 if (insn
& (1 << 20)) {
7970 if (rs
== 15 && op
!= 2) {
7973 /* Memory hint. Implemented as NOP. */
7976 case 0: tmp
= gen_ld8u(addr
, user
); break;
7977 case 4: tmp
= gen_ld8s(addr
, user
); break;
7978 case 1: tmp
= gen_ld16u(addr
, user
); break;
7979 case 5: tmp
= gen_ld16s(addr
, user
); break;
7980 case 2: tmp
= gen_ld32(addr
, user
); break;
7981 default: goto illegal_op
;
7986 store_reg(s
, rs
, tmp
);
7993 tmp
= load_reg(s
, rs
);
7995 case 0: gen_st8(tmp
, addr
, user
); break;
7996 case 1: gen_st16(tmp
, addr
, user
); break;
7997 case 2: gen_st32(tmp
, addr
, user
); break;
7998 default: goto illegal_op
;
8002 tcg_gen_addi_i32(addr
, addr
, imm
);
8004 store_reg(s
, rn
, addr
);
8018 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8020 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8027 if (s
->condexec_mask
) {
8028 cond
= s
->condexec_cond
;
8029 s
->condlabel
= gen_new_label();
8030 gen_test_cc(cond
^ 1, s
->condlabel
);
8034 insn
= lduw_code(s
->pc
);
8037 switch (insn
>> 12) {
8040 op
= (insn
>> 11) & 3;
8043 rn
= (insn
>> 3) & 7;
8044 gen_movl_T0_reg(s
, rn
);
8045 if (insn
& (1 << 10)) {
8047 gen_op_movl_T1_im((insn
>> 6) & 7);
8050 rm
= (insn
>> 6) & 7;
8051 gen_movl_T1_reg(s
, rm
);
8053 if (insn
& (1 << 9)) {
8054 if (s
->condexec_mask
)
8055 gen_op_subl_T0_T1();
8057 gen_op_subl_T0_T1_cc();
8059 if (s
->condexec_mask
)
8060 gen_op_addl_T0_T1();
8062 gen_op_addl_T0_T1_cc();
8064 gen_movl_reg_T0(s
, rd
);
8066 /* shift immediate */
8067 rm
= (insn
>> 3) & 7;
8068 shift
= (insn
>> 6) & 0x1f;
8069 tmp
= load_reg(s
, rm
);
8070 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8071 if (!s
->condexec_mask
)
8073 store_reg(s
, rd
, tmp
);
8077 /* arithmetic large immediate */
8078 op
= (insn
>> 11) & 3;
8079 rd
= (insn
>> 8) & 0x7;
8081 gen_op_movl_T0_im(insn
& 0xff);
8083 gen_movl_T0_reg(s
, rd
);
8084 gen_op_movl_T1_im(insn
& 0xff);
8088 if (!s
->condexec_mask
)
8089 gen_op_logic_T0_cc();
8092 gen_op_subl_T0_T1_cc();
8095 if (s
->condexec_mask
)
8096 gen_op_addl_T0_T1();
8098 gen_op_addl_T0_T1_cc();
8101 if (s
->condexec_mask
)
8102 gen_op_subl_T0_T1();
8104 gen_op_subl_T0_T1_cc();
8108 gen_movl_reg_T0(s
, rd
);
8111 if (insn
& (1 << 11)) {
8112 rd
= (insn
>> 8) & 7;
8113 /* load pc-relative. Bit 1 of PC is ignored. */
8114 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8115 val
&= ~(uint32_t)2;
8117 tcg_gen_movi_i32(addr
, val
);
8118 tmp
= gen_ld32(addr
, IS_USER(s
));
8120 store_reg(s
, rd
, tmp
);
8123 if (insn
& (1 << 10)) {
8124 /* data processing extended or blx */
8125 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8126 rm
= (insn
>> 3) & 0xf;
8127 op
= (insn
>> 8) & 3;
8130 gen_movl_T0_reg(s
, rd
);
8131 gen_movl_T1_reg(s
, rm
);
8132 gen_op_addl_T0_T1();
8133 gen_movl_reg_T0(s
, rd
);
8136 gen_movl_T0_reg(s
, rd
);
8137 gen_movl_T1_reg(s
, rm
);
8138 gen_op_subl_T0_T1_cc();
8140 case 2: /* mov/cpy */
8141 gen_movl_T0_reg(s
, rm
);
8142 gen_movl_reg_T0(s
, rd
);
8144 case 3:/* branch [and link] exchange thumb register */
8145 tmp
= load_reg(s
, rm
);
8146 if (insn
& (1 << 7)) {
8147 val
= (uint32_t)s
->pc
| 1;
8149 tcg_gen_movi_i32(tmp2
, val
);
8150 store_reg(s
, 14, tmp2
);
8158 /* data processing register */
8160 rm
= (insn
>> 3) & 7;
8161 op
= (insn
>> 6) & 0xf;
8162 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8163 /* the shift/rotate ops want the operands backwards */
8172 if (op
== 9) /* neg */
8173 gen_op_movl_T0_im(0);
8174 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8175 gen_movl_T0_reg(s
, rd
);
8177 gen_movl_T1_reg(s
, rm
);
8180 gen_op_andl_T0_T1();
8181 if (!s
->condexec_mask
)
8182 gen_op_logic_T0_cc();
8185 gen_op_xorl_T0_T1();
8186 if (!s
->condexec_mask
)
8187 gen_op_logic_T0_cc();
8190 if (s
->condexec_mask
) {
8191 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8193 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8194 gen_op_logic_T1_cc();
8198 if (s
->condexec_mask
) {
8199 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8201 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8202 gen_op_logic_T1_cc();
8206 if (s
->condexec_mask
) {
8207 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8209 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8210 gen_op_logic_T1_cc();
8214 if (s
->condexec_mask
)
8217 gen_op_adcl_T0_T1_cc();
8220 if (s
->condexec_mask
)
8223 gen_op_sbcl_T0_T1_cc();
8226 if (s
->condexec_mask
) {
8227 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8229 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8230 gen_op_logic_T1_cc();
8234 gen_op_andl_T0_T1();
8235 gen_op_logic_T0_cc();
8239 if (s
->condexec_mask
)
8240 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8242 gen_op_subl_T0_T1_cc();
8245 gen_op_subl_T0_T1_cc();
8249 gen_op_addl_T0_T1_cc();
8254 if (!s
->condexec_mask
)
8255 gen_op_logic_T0_cc();
8258 gen_op_mull_T0_T1();
8259 if (!s
->condexec_mask
)
8260 gen_op_logic_T0_cc();
8263 gen_op_bicl_T0_T1();
8264 if (!s
->condexec_mask
)
8265 gen_op_logic_T0_cc();
8269 if (!s
->condexec_mask
)
8270 gen_op_logic_T1_cc();
8277 gen_movl_reg_T1(s
, rm
);
8279 gen_movl_reg_T0(s
, rd
);
8284 /* load/store register offset. */
8286 rn
= (insn
>> 3) & 7;
8287 rm
= (insn
>> 6) & 7;
8288 op
= (insn
>> 9) & 7;
8289 addr
= load_reg(s
, rn
);
8290 tmp
= load_reg(s
, rm
);
8291 tcg_gen_add_i32(addr
, addr
, tmp
);
8294 if (op
< 3) /* store */
8295 tmp
= load_reg(s
, rd
);
8299 gen_st32(tmp
, addr
, IS_USER(s
));
8302 gen_st16(tmp
, addr
, IS_USER(s
));
8305 gen_st8(tmp
, addr
, IS_USER(s
));
8308 tmp
= gen_ld8s(addr
, IS_USER(s
));
8311 tmp
= gen_ld32(addr
, IS_USER(s
));
8314 tmp
= gen_ld16u(addr
, IS_USER(s
));
8317 tmp
= gen_ld8u(addr
, IS_USER(s
));
8320 tmp
= gen_ld16s(addr
, IS_USER(s
));
8323 if (op
>= 3) /* load */
8324 store_reg(s
, rd
, tmp
);
8329 /* load/store word immediate offset */
8331 rn
= (insn
>> 3) & 7;
8332 addr
= load_reg(s
, rn
);
8333 val
= (insn
>> 4) & 0x7c;
8334 tcg_gen_addi_i32(addr
, addr
, val
);
8336 if (insn
& (1 << 11)) {
8338 tmp
= gen_ld32(addr
, IS_USER(s
));
8339 store_reg(s
, rd
, tmp
);
8342 tmp
= load_reg(s
, rd
);
8343 gen_st32(tmp
, addr
, IS_USER(s
));
8349 /* load/store byte immediate offset */
8351 rn
= (insn
>> 3) & 7;
8352 addr
= load_reg(s
, rn
);
8353 val
= (insn
>> 6) & 0x1f;
8354 tcg_gen_addi_i32(addr
, addr
, val
);
8356 if (insn
& (1 << 11)) {
8358 tmp
= gen_ld8u(addr
, IS_USER(s
));
8359 store_reg(s
, rd
, tmp
);
8362 tmp
= load_reg(s
, rd
);
8363 gen_st8(tmp
, addr
, IS_USER(s
));
8369 /* load/store halfword immediate offset */
8371 rn
= (insn
>> 3) & 7;
8372 addr
= load_reg(s
, rn
);
8373 val
= (insn
>> 5) & 0x3e;
8374 tcg_gen_addi_i32(addr
, addr
, val
);
8376 if (insn
& (1 << 11)) {
8378 tmp
= gen_ld16u(addr
, IS_USER(s
));
8379 store_reg(s
, rd
, tmp
);
8382 tmp
= load_reg(s
, rd
);
8383 gen_st16(tmp
, addr
, IS_USER(s
));
8389 /* load/store from stack */
8390 rd
= (insn
>> 8) & 7;
8391 addr
= load_reg(s
, 13);
8392 val
= (insn
& 0xff) * 4;
8393 tcg_gen_addi_i32(addr
, addr
, val
);
8395 if (insn
& (1 << 11)) {
8397 tmp
= gen_ld32(addr
, IS_USER(s
));
8398 store_reg(s
, rd
, tmp
);
8401 tmp
= load_reg(s
, rd
);
8402 gen_st32(tmp
, addr
, IS_USER(s
));
8408 /* add to high reg */
8409 rd
= (insn
>> 8) & 7;
8410 if (insn
& (1 << 11)) {
8412 tmp
= load_reg(s
, 13);
8414 /* PC. bit 1 is ignored. */
8416 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8418 val
= (insn
& 0xff) * 4;
8419 tcg_gen_addi_i32(tmp
, tmp
, val
);
8420 store_reg(s
, rd
, tmp
);
8425 op
= (insn
>> 8) & 0xf;
8428 /* adjust stack pointer */
8429 tmp
= load_reg(s
, 13);
8430 val
= (insn
& 0x7f) * 4;
8431 if (insn
& (1 << 7))
8432 val
= -(int32_t)val
;
8433 tcg_gen_addi_i32(tmp
, tmp
, val
);
8434 store_reg(s
, 13, tmp
);
8437 case 2: /* sign/zero extend. */
8440 rm
= (insn
>> 3) & 7;
8441 tmp
= load_reg(s
, rm
);
8442 switch ((insn
>> 6) & 3) {
8443 case 0: gen_sxth(tmp
); break;
8444 case 1: gen_sxtb(tmp
); break;
8445 case 2: gen_uxth(tmp
); break;
8446 case 3: gen_uxtb(tmp
); break;
8448 store_reg(s
, rd
, tmp
);
8450 case 4: case 5: case 0xc: case 0xd:
8452 addr
= load_reg(s
, 13);
8453 if (insn
& (1 << 8))
8457 for (i
= 0; i
< 8; i
++) {
8458 if (insn
& (1 << i
))
8461 if ((insn
& (1 << 11)) == 0) {
8462 tcg_gen_addi_i32(addr
, addr
, -offset
);
8464 for (i
= 0; i
< 8; i
++) {
8465 if (insn
& (1 << i
)) {
8466 if (insn
& (1 << 11)) {
8468 tmp
= gen_ld32(addr
, IS_USER(s
));
8469 store_reg(s
, i
, tmp
);
8472 tmp
= load_reg(s
, i
);
8473 gen_st32(tmp
, addr
, IS_USER(s
));
8475 /* advance to the next address. */
8476 tcg_gen_addi_i32(addr
, addr
, 4);
8480 if (insn
& (1 << 8)) {
8481 if (insn
& (1 << 11)) {
8483 tmp
= gen_ld32(addr
, IS_USER(s
));
8484 /* don't set the pc until the rest of the instruction
8488 tmp
= load_reg(s
, 14);
8489 gen_st32(tmp
, addr
, IS_USER(s
));
8491 tcg_gen_addi_i32(addr
, addr
, 4);
8493 if ((insn
& (1 << 11)) == 0) {
8494 tcg_gen_addi_i32(addr
, addr
, -offset
);
8496 /* write back the new stack pointer */
8497 store_reg(s
, 13, addr
);
8498 /* set the new PC value */
8499 if ((insn
& 0x0900) == 0x0900)
8503 case 1: case 3: case 9: case 11: /* czb */
8505 tmp
= load_reg(s
, rm
);
8506 s
->condlabel
= gen_new_label();
8508 if (insn
& (1 << 11))
8509 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8511 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8513 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8514 val
= (uint32_t)s
->pc
+ 2;
8519 case 15: /* IT, nop-hint. */
8520 if ((insn
& 0xf) == 0) {
8521 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8525 s
->condexec_cond
= (insn
>> 4) & 0xe;
8526 s
->condexec_mask
= insn
& 0x1f;
8527 /* No actual code generated for this insn, just setup state. */
8530 case 0xe: /* bkpt */
8531 gen_set_condexec(s
);
8532 gen_set_pc_im(s
->pc
- 2);
8533 gen_exception(EXCP_BKPT
);
8534 s
->is_jmp
= DISAS_JUMP
;
8539 rn
= (insn
>> 3) & 0x7;
8541 tmp
= load_reg(s
, rn
);
8542 switch ((insn
>> 6) & 3) {
8543 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8544 case 1: gen_rev16(tmp
); break;
8545 case 3: gen_revsh(tmp
); break;
8546 default: goto illegal_op
;
8548 store_reg(s
, rd
, tmp
);
8556 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8559 addr
= tcg_const_i32(16);
8560 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8564 addr
= tcg_const_i32(17);
8565 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8569 if (insn
& (1 << 4))
8570 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8574 val
= ((insn
& 7) << 6) & shift
;
8575 gen_op_movl_T0_im(val
);
8576 gen_set_psr_T0(s
, shift
, 0);
8586 /* load/store multiple */
8587 rn
= (insn
>> 8) & 0x7;
8588 addr
= load_reg(s
, rn
);
8589 for (i
= 0; i
< 8; i
++) {
8590 if (insn
& (1 << i
)) {
8591 if (insn
& (1 << 11)) {
8593 tmp
= gen_ld32(addr
, IS_USER(s
));
8594 store_reg(s
, i
, tmp
);
8597 tmp
= load_reg(s
, i
);
8598 gen_st32(tmp
, addr
, IS_USER(s
));
8600 /* advance to the next address */
8601 tcg_gen_addi_i32(addr
, addr
, 4);
8604 /* Base register writeback. */
8605 if ((insn
& (1 << rn
)) == 0) {
8606 store_reg(s
, rn
, addr
);
8613 /* conditional branch or swi */
8614 cond
= (insn
>> 8) & 0xf;
8620 gen_set_condexec(s
);
8621 gen_set_pc_im(s
->pc
);
8622 s
->is_jmp
= DISAS_SWI
;
8625 /* generate a conditional jump to next instruction */
8626 s
->condlabel
= gen_new_label();
8627 gen_test_cc(cond
^ 1, s
->condlabel
);
8630 /* jump to the offset */
8631 val
= (uint32_t)s
->pc
+ 2;
8632 offset
= ((int32_t)insn
<< 24) >> 24;
8638 if (insn
& (1 << 11)) {
8639 if (disas_thumb2_insn(env
, s
, insn
))
8643 /* unconditional branch */
8644 val
= (uint32_t)s
->pc
;
8645 offset
= ((int32_t)insn
<< 21) >> 21;
8646 val
+= (offset
<< 1) + 2;
8651 if (disas_thumb2_insn(env
, s
, insn
))
8657 gen_set_condexec(s
);
8658 gen_set_pc_im(s
->pc
- 4);
8659 gen_exception(EXCP_UDEF
);
8660 s
->is_jmp
= DISAS_JUMP
;
8664 gen_set_condexec(s
);
8665 gen_set_pc_im(s
->pc
- 2);
8666 gen_exception(EXCP_UDEF
);
8667 s
->is_jmp
= DISAS_JUMP
;
8670 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8671 basic block 'tb'. If search_pc is TRUE, also generate PC
8672 information for each intermediate instruction. */
8673 static inline void gen_intermediate_code_internal(CPUState
*env
,
8674 TranslationBlock
*tb
,
8677 DisasContext dc1
, *dc
= &dc1
;
8679 uint16_t *gen_opc_end
;
8681 target_ulong pc_start
;
8682 uint32_t next_page_start
;
8686 /* generate intermediate code */
8693 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8695 dc
->is_jmp
= DISAS_NEXT
;
8697 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8699 dc
->thumb
= env
->thumb
;
8700 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8701 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8702 #if !defined(CONFIG_USER_ONLY)
8704 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8706 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8709 cpu_F0s
= tcg_temp_new_i32();
8710 cpu_F1s
= tcg_temp_new_i32();
8711 cpu_F0d
= tcg_temp_new_i64();
8712 cpu_F1d
= tcg_temp_new_i64();
8715 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8716 cpu_M0
= tcg_temp_new_i64();
8717 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8720 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8722 max_insns
= CF_COUNT_MASK
;
8725 /* Reset the conditional execution bits immediately. This avoids
8726 complications trying to do it at the end of the block. */
8727 if (env
->condexec_bits
)
8729 TCGv tmp
= new_tmp();
8730 tcg_gen_movi_i32(tmp
, 0);
8731 store_cpu_field(tmp
, condexec_bits
);
8734 #ifdef CONFIG_USER_ONLY
8735 /* Intercept jump to the magic kernel page. */
8736 if (dc
->pc
>= 0xffff0000) {
8737 /* We always get here via a jump, so know we are not in a
8738 conditional execution block. */
8739 gen_exception(EXCP_KERNEL_TRAP
);
8740 dc
->is_jmp
= DISAS_UPDATE
;
8744 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8745 /* We always get here via a jump, so know we are not in a
8746 conditional execution block. */
8747 gen_exception(EXCP_EXCEPTION_EXIT
);
8748 dc
->is_jmp
= DISAS_UPDATE
;
8753 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8754 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8755 if (bp
->pc
== dc
->pc
) {
8756 gen_set_condexec(dc
);
8757 gen_set_pc_im(dc
->pc
);
8758 gen_exception(EXCP_DEBUG
);
8759 dc
->is_jmp
= DISAS_JUMP
;
8760 /* Advance PC so that clearing the breakpoint will
8761 invalidate this TB. */
8763 goto done_generating
;
8769 j
= gen_opc_ptr
- gen_opc_buf
;
8773 gen_opc_instr_start
[lj
++] = 0;
8775 gen_opc_pc
[lj
] = dc
->pc
;
8776 gen_opc_instr_start
[lj
] = 1;
8777 gen_opc_icount
[lj
] = num_insns
;
8780 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8784 disas_thumb_insn(env
, dc
);
8785 if (dc
->condexec_mask
) {
8786 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8787 | ((dc
->condexec_mask
>> 4) & 1);
8788 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8789 if (dc
->condexec_mask
== 0) {
8790 dc
->condexec_cond
= 0;
8794 disas_arm_insn(env
, dc
);
8797 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8801 if (dc
->condjmp
&& !dc
->is_jmp
) {
8802 gen_set_label(dc
->condlabel
);
8805 /* Translation stops when a conditional branch is encountered.
8806 * Otherwise the subsequent code could get translated several times.
8807 * Also stop translation when a page boundary is reached. This
8808 * ensures prefetch aborts occur at the right place. */
8810 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8811 !env
->singlestep_enabled
&&
8813 dc
->pc
< next_page_start
&&
8814 num_insns
< max_insns
);
8816 if (tb
->cflags
& CF_LAST_IO
) {
8818 /* FIXME: This can theoretically happen with self-modifying
8820 cpu_abort(env
, "IO on conditional branch instruction");
8825 /* At this stage dc->condjmp will only be set when the skipped
8826 instruction was a conditional branch or trap, and the PC has
8827 already been written. */
8828 if (unlikely(env
->singlestep_enabled
)) {
8829 /* Make sure the pc is updated, and raise a debug exception. */
8831 gen_set_condexec(dc
);
8832 if (dc
->is_jmp
== DISAS_SWI
) {
8833 gen_exception(EXCP_SWI
);
8835 gen_exception(EXCP_DEBUG
);
8837 gen_set_label(dc
->condlabel
);
8839 if (dc
->condjmp
|| !dc
->is_jmp
) {
8840 gen_set_pc_im(dc
->pc
);
8843 gen_set_condexec(dc
);
8844 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8845 gen_exception(EXCP_SWI
);
8847 /* FIXME: Single stepping a WFI insn will not halt
8849 gen_exception(EXCP_DEBUG
);
8852 /* While branches must always occur at the end of an IT block,
8853 there are a few other things that can cause us to terminate
8854 the TB in the middel of an IT block:
8855 - Exception generating instructions (bkpt, swi, undefined).
8857 - Hardware watchpoints.
8858 Hardware breakpoints have already been handled and skip this code.
8860 gen_set_condexec(dc
);
8861 switch(dc
->is_jmp
) {
8863 gen_goto_tb(dc
, 1, dc
->pc
);
8868 /* indicate that the hash table must be used to find the next TB */
8872 /* nothing more to generate */
8878 gen_exception(EXCP_SWI
);
8882 gen_set_label(dc
->condlabel
);
8883 gen_set_condexec(dc
);
8884 gen_goto_tb(dc
, 1, dc
->pc
);
8890 gen_icount_end(tb
, num_insns
);
8891 *gen_opc_ptr
= INDEX_op_end
;
8894 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8895 qemu_log("----------------\n");
8896 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8897 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8902 j
= gen_opc_ptr
- gen_opc_buf
;
8905 gen_opc_instr_start
[lj
++] = 0;
8907 tb
->size
= dc
->pc
- pc_start
;
8908 tb
->icount
= num_insns
;
8912 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8914 gen_intermediate_code_internal(env
, tb
, 0);
8917 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8919 gen_intermediate_code_internal(env
, tb
, 1);
8922 static const char *cpu_mode_names
[16] = {
8923 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8924 "???", "???", "???", "und", "???", "???", "???", "sys"
8927 void cpu_dump_state(CPUState
*env
, FILE *f
,
8928 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8938 /* ??? This assumes float64 and double have the same layout.
8939 Oh well, it's only debug dumps. */
8948 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8950 cpu_fprintf(f
, "\n");
8952 cpu_fprintf(f
, " ");
8954 psr
= cpsr_read(env
);
8955 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8957 psr
& (1 << 31) ? 'N' : '-',
8958 psr
& (1 << 30) ? 'Z' : '-',
8959 psr
& (1 << 29) ? 'C' : '-',
8960 psr
& (1 << 28) ? 'V' : '-',
8961 psr
& CPSR_T
? 'T' : 'A',
8962 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8965 for (i
= 0; i
< 16; i
++) {
8966 d
.d
= env
->vfp
.regs
[i
];
8970 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8971 i
* 2, (int)s0
.i
, s0
.s
,
8972 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8973 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8976 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
8980 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
8981 unsigned long searched_pc
, int pc_pos
, void *puc
)
8983 env
->regs
[15] = gen_opc_pc
[pc_pos
];