]>
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_set_pc_im(uint32_t val
)
869 tcg_gen_movi_i32(cpu_R
[15], val
);
872 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
877 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
881 tcg_gen_mov_i32(cpu_R
[reg
], tmp
);
884 s
->is_jmp
= DISAS_JUMP
;
888 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
890 gen_movl_reg_TN(s
, reg
, 0);
893 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
895 gen_movl_reg_TN(s
, reg
, 1);
898 /* Force a TB lookup after an instruction that changes the CPU state. */
899 static inline void gen_lookup_tb(DisasContext
*s
)
901 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
902 s
->is_jmp
= DISAS_UPDATE
;
905 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
908 int val
, rm
, shift
, shiftop
;
911 if (!(insn
& (1 << 25))) {
914 if (!(insn
& (1 << 23)))
917 tcg_gen_addi_i32(var
, var
, val
);
921 shift
= (insn
>> 7) & 0x1f;
922 shiftop
= (insn
>> 5) & 3;
923 offset
= load_reg(s
, rm
);
924 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
925 if (!(insn
& (1 << 23)))
926 tcg_gen_sub_i32(var
, var
, offset
);
928 tcg_gen_add_i32(var
, var
, offset
);
933 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
939 if (insn
& (1 << 22)) {
941 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
942 if (!(insn
& (1 << 23)))
946 tcg_gen_addi_i32(var
, var
, val
);
950 tcg_gen_addi_i32(var
, var
, extra
);
952 offset
= load_reg(s
, rm
);
953 if (!(insn
& (1 << 23)))
954 tcg_gen_sub_i32(var
, var
, offset
);
956 tcg_gen_add_i32(var
, var
, offset
);
961 #define VFP_OP2(name) \
962 static inline void gen_vfp_##name(int dp) \
965 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
967 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
977 static inline void gen_vfp_abs(int dp
)
980 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
982 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
985 static inline void gen_vfp_neg(int dp
)
988 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
990 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
993 static inline void gen_vfp_sqrt(int dp
)
996 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
998 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1001 static inline void gen_vfp_cmp(int dp
)
1004 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1006 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1009 static inline void gen_vfp_cmpe(int dp
)
1012 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1014 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1017 static inline void gen_vfp_F1_ld0(int dp
)
1020 tcg_gen_movi_i64(cpu_F1d
, 0);
1022 tcg_gen_movi_i32(cpu_F1s
, 0);
1025 static inline void gen_vfp_uito(int dp
)
1028 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1030 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1033 static inline void gen_vfp_sito(int dp
)
1036 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1038 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1041 static inline void gen_vfp_toui(int dp
)
1044 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1046 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1049 static inline void gen_vfp_touiz(int dp
)
1052 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1054 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1057 static inline void gen_vfp_tosi(int dp
)
1060 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1062 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1065 static inline void gen_vfp_tosiz(int dp
)
1068 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1070 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1073 #define VFP_GEN_FIX(name) \
1074 static inline void gen_vfp_##name(int dp, int shift) \
1077 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1079 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1091 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1094 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1096 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1099 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1102 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1104 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1108 vfp_reg_offset (int dp
, int reg
)
1111 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1113 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1114 + offsetof(CPU_DoubleU
, l
.upper
);
1116 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1117 + offsetof(CPU_DoubleU
, l
.lower
);
1121 /* Return the offset of a 32-bit piece of a NEON register.
1122 zero is the least significant end of the register. */
1124 neon_reg_offset (int reg
, int n
)
1128 return vfp_reg_offset(0, sreg
);
1131 /* FIXME: Remove these. */
1132 #define neon_T0 cpu_T[0]
1133 #define neon_T1 cpu_T[1]
1134 #define NEON_GET_REG(T, reg, n) \
1135 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1136 #define NEON_SET_REG(T, reg, n) \
1137 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1139 static TCGv
neon_load_reg(int reg
, int pass
)
1141 TCGv tmp
= new_tmp();
1142 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1146 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1148 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1152 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1154 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1157 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1159 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1162 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1163 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1164 #define tcg_gen_st_f32 tcg_gen_st_i32
1165 #define tcg_gen_st_f64 tcg_gen_st_i64
1167 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1170 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1172 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1175 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1178 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1180 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1183 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1186 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1188 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1191 #define ARM_CP_RW_BIT (1 << 20)
1193 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1195 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1198 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1200 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1203 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1205 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1208 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1210 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1213 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1215 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1218 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1220 iwmmxt_store_reg(cpu_M0
, rn
);
1223 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1225 iwmmxt_load_reg(cpu_M0
, rn
);
1228 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1230 iwmmxt_load_reg(cpu_V1
, rn
);
1231 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1234 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1236 iwmmxt_load_reg(cpu_V1
, rn
);
1237 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1240 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1242 iwmmxt_load_reg(cpu_V1
, rn
);
1243 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1246 #define IWMMXT_OP(name) \
1247 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1249 iwmmxt_load_reg(cpu_V1, rn); \
1250 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1253 #define IWMMXT_OP_ENV(name) \
1254 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1256 iwmmxt_load_reg(cpu_V1, rn); \
1257 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1260 #define IWMMXT_OP_ENV_SIZE(name) \
1261 IWMMXT_OP_ENV(name##b) \
1262 IWMMXT_OP_ENV(name##w) \
1263 IWMMXT_OP_ENV(name##l)
1265 #define IWMMXT_OP_ENV1(name) \
1266 static inline void gen_op_iwmmxt_##name##_M0(void) \
1268 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1282 IWMMXT_OP_ENV_SIZE(unpackl
)
1283 IWMMXT_OP_ENV_SIZE(unpackh
)
1285 IWMMXT_OP_ENV1(unpacklub
)
1286 IWMMXT_OP_ENV1(unpackluw
)
1287 IWMMXT_OP_ENV1(unpacklul
)
1288 IWMMXT_OP_ENV1(unpackhub
)
1289 IWMMXT_OP_ENV1(unpackhuw
)
1290 IWMMXT_OP_ENV1(unpackhul
)
1291 IWMMXT_OP_ENV1(unpacklsb
)
1292 IWMMXT_OP_ENV1(unpacklsw
)
1293 IWMMXT_OP_ENV1(unpacklsl
)
1294 IWMMXT_OP_ENV1(unpackhsb
)
1295 IWMMXT_OP_ENV1(unpackhsw
)
1296 IWMMXT_OP_ENV1(unpackhsl
)
1298 IWMMXT_OP_ENV_SIZE(cmpeq
)
1299 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1300 IWMMXT_OP_ENV_SIZE(cmpgts
)
1302 IWMMXT_OP_ENV_SIZE(mins
)
1303 IWMMXT_OP_ENV_SIZE(minu
)
1304 IWMMXT_OP_ENV_SIZE(maxs
)
1305 IWMMXT_OP_ENV_SIZE(maxu
)
1307 IWMMXT_OP_ENV_SIZE(subn
)
1308 IWMMXT_OP_ENV_SIZE(addn
)
1309 IWMMXT_OP_ENV_SIZE(subu
)
1310 IWMMXT_OP_ENV_SIZE(addu
)
1311 IWMMXT_OP_ENV_SIZE(subs
)
1312 IWMMXT_OP_ENV_SIZE(adds
)
1314 IWMMXT_OP_ENV(avgb0
)
1315 IWMMXT_OP_ENV(avgb1
)
1316 IWMMXT_OP_ENV(avgw0
)
1317 IWMMXT_OP_ENV(avgw1
)
1321 IWMMXT_OP_ENV(packuw
)
1322 IWMMXT_OP_ENV(packul
)
1323 IWMMXT_OP_ENV(packuq
)
1324 IWMMXT_OP_ENV(packsw
)
1325 IWMMXT_OP_ENV(packsl
)
1326 IWMMXT_OP_ENV(packsq
)
1328 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1330 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1333 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1335 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1338 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1340 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1343 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1345 iwmmxt_load_reg(cpu_V1
, rn
);
1346 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1349 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1351 TCGv tmp
= tcg_const_i32(shift
);
1352 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1355 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1357 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1358 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1359 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1362 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1364 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1365 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1366 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1369 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1371 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1372 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1374 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1377 static void gen_op_iwmmxt_set_mup(void)
1380 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1381 tcg_gen_ori_i32(tmp
, tmp
, 2);
1382 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1385 static void gen_op_iwmmxt_set_cup(void)
1388 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1389 tcg_gen_ori_i32(tmp
, tmp
, 1);
1390 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1393 static void gen_op_iwmmxt_setpsr_nz(void)
1395 TCGv tmp
= new_tmp();
1396 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1397 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1400 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1402 iwmmxt_load_reg(cpu_V1
, rn
);
1403 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1404 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1408 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1410 iwmmxt_load_reg(cpu_V0
, rn
);
1411 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1412 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1413 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1416 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1418 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1419 iwmmxt_store_reg(cpu_V0
, rn
);
1422 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1427 rd
= (insn
>> 16) & 0xf;
1428 gen_movl_T1_reg(s
, rd
);
1430 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1431 if (insn
& (1 << 24)) {
1433 if (insn
& (1 << 23))
1434 gen_op_addl_T1_im(offset
);
1436 gen_op_addl_T1_im(-offset
);
1438 if (insn
& (1 << 21))
1439 gen_movl_reg_T1(s
, rd
);
1440 } else if (insn
& (1 << 21)) {
1442 if (insn
& (1 << 23))
1443 gen_op_movl_T0_im(offset
);
1445 gen_op_movl_T0_im(- offset
);
1446 gen_op_addl_T0_T1();
1447 gen_movl_reg_T0(s
, rd
);
1448 } else if (!(insn
& (1 << 23)))
1453 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1455 int rd
= (insn
>> 0) & 0xf;
1457 if (insn
& (1 << 8))
1458 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1461 gen_op_iwmmxt_movl_T0_wCx(rd
);
1463 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1465 gen_op_movl_T1_im(mask
);
1466 gen_op_andl_T0_T1();
1470 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1471 (ie. an undefined instruction). */
1472 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1475 int rdhi
, rdlo
, rd0
, rd1
, i
;
1478 if ((insn
& 0x0e000e00) == 0x0c000000) {
1479 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1481 rdlo
= (insn
>> 12) & 0xf;
1482 rdhi
= (insn
>> 16) & 0xf;
1483 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1484 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1485 gen_movl_reg_T0(s
, rdlo
);
1486 gen_movl_reg_T1(s
, rdhi
);
1487 } else { /* TMCRR */
1488 gen_movl_T0_reg(s
, rdlo
);
1489 gen_movl_T1_reg(s
, rdhi
);
1490 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1491 gen_op_iwmmxt_set_mup();
1496 wrd
= (insn
>> 12) & 0xf;
1497 if (gen_iwmmxt_address(s
, insn
))
1499 if (insn
& ARM_CP_RW_BIT
) {
1500 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1501 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1502 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1504 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1507 if (insn
& (1 << 8)) {
1508 if (insn
& (1 << 22)) { /* WLDRD */
1509 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1511 } else { /* WLDRW wRd */
1512 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1515 if (insn
& (1 << 22)) { /* WLDRH */
1516 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1517 } else { /* WLDRB */
1518 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1522 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1525 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1528 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1529 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1531 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1532 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1534 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1536 if (insn
& (1 << 8)) {
1537 if (insn
& (1 << 22)) { /* WSTRD */
1539 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1540 } else { /* WSTRW wRd */
1541 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1542 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1545 if (insn
& (1 << 22)) { /* WSTRH */
1546 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1547 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1548 } else { /* WSTRB */
1549 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1550 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1558 if ((insn
& 0x0f000000) != 0x0e000000)
1561 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1562 case 0x000: /* WOR */
1563 wrd
= (insn
>> 12) & 0xf;
1564 rd0
= (insn
>> 0) & 0xf;
1565 rd1
= (insn
>> 16) & 0xf;
1566 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1567 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1568 gen_op_iwmmxt_setpsr_nz();
1569 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1570 gen_op_iwmmxt_set_mup();
1571 gen_op_iwmmxt_set_cup();
1573 case 0x011: /* TMCR */
1576 rd
= (insn
>> 12) & 0xf;
1577 wrd
= (insn
>> 16) & 0xf;
1579 case ARM_IWMMXT_wCID
:
1580 case ARM_IWMMXT_wCASF
:
1582 case ARM_IWMMXT_wCon
:
1583 gen_op_iwmmxt_set_cup();
1585 case ARM_IWMMXT_wCSSF
:
1586 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1587 gen_movl_T1_reg(s
, rd
);
1588 gen_op_bicl_T0_T1();
1589 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1591 case ARM_IWMMXT_wCGR0
:
1592 case ARM_IWMMXT_wCGR1
:
1593 case ARM_IWMMXT_wCGR2
:
1594 case ARM_IWMMXT_wCGR3
:
1595 gen_op_iwmmxt_set_cup();
1596 gen_movl_reg_T0(s
, rd
);
1597 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1603 case 0x100: /* WXOR */
1604 wrd
= (insn
>> 12) & 0xf;
1605 rd0
= (insn
>> 0) & 0xf;
1606 rd1
= (insn
>> 16) & 0xf;
1607 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1608 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1609 gen_op_iwmmxt_setpsr_nz();
1610 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1611 gen_op_iwmmxt_set_mup();
1612 gen_op_iwmmxt_set_cup();
1614 case 0x111: /* TMRC */
1617 rd
= (insn
>> 12) & 0xf;
1618 wrd
= (insn
>> 16) & 0xf;
1619 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1620 gen_movl_reg_T0(s
, rd
);
1622 case 0x300: /* WANDN */
1623 wrd
= (insn
>> 12) & 0xf;
1624 rd0
= (insn
>> 0) & 0xf;
1625 rd1
= (insn
>> 16) & 0xf;
1626 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1627 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1628 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1629 gen_op_iwmmxt_setpsr_nz();
1630 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1631 gen_op_iwmmxt_set_mup();
1632 gen_op_iwmmxt_set_cup();
1634 case 0x200: /* WAND */
1635 wrd
= (insn
>> 12) & 0xf;
1636 rd0
= (insn
>> 0) & 0xf;
1637 rd1
= (insn
>> 16) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1639 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1640 gen_op_iwmmxt_setpsr_nz();
1641 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1642 gen_op_iwmmxt_set_mup();
1643 gen_op_iwmmxt_set_cup();
1645 case 0x810: case 0xa10: /* WMADD */
1646 wrd
= (insn
>> 12) & 0xf;
1647 rd0
= (insn
>> 0) & 0xf;
1648 rd1
= (insn
>> 16) & 0xf;
1649 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1650 if (insn
& (1 << 21))
1651 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1653 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1654 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1655 gen_op_iwmmxt_set_mup();
1657 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1658 wrd
= (insn
>> 12) & 0xf;
1659 rd0
= (insn
>> 16) & 0xf;
1660 rd1
= (insn
>> 0) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1662 switch ((insn
>> 22) & 3) {
1664 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1667 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1670 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1675 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1676 gen_op_iwmmxt_set_mup();
1677 gen_op_iwmmxt_set_cup();
1679 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1680 wrd
= (insn
>> 12) & 0xf;
1681 rd0
= (insn
>> 16) & 0xf;
1682 rd1
= (insn
>> 0) & 0xf;
1683 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1684 switch ((insn
>> 22) & 3) {
1686 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1689 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1692 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1697 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1698 gen_op_iwmmxt_set_mup();
1699 gen_op_iwmmxt_set_cup();
1701 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1702 wrd
= (insn
>> 12) & 0xf;
1703 rd0
= (insn
>> 16) & 0xf;
1704 rd1
= (insn
>> 0) & 0xf;
1705 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1706 if (insn
& (1 << 22))
1707 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1709 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1710 if (!(insn
& (1 << 20)))
1711 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1712 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1713 gen_op_iwmmxt_set_mup();
1715 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1716 wrd
= (insn
>> 12) & 0xf;
1717 rd0
= (insn
>> 16) & 0xf;
1718 rd1
= (insn
>> 0) & 0xf;
1719 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1720 if (insn
& (1 << 21)) {
1721 if (insn
& (1 << 20))
1722 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1724 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1726 if (insn
& (1 << 20))
1727 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1729 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1731 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1732 gen_op_iwmmxt_set_mup();
1734 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1735 wrd
= (insn
>> 12) & 0xf;
1736 rd0
= (insn
>> 16) & 0xf;
1737 rd1
= (insn
>> 0) & 0xf;
1738 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1739 if (insn
& (1 << 21))
1740 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1742 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1743 if (!(insn
& (1 << 20))) {
1744 iwmmxt_load_reg(cpu_V1
, wrd
);
1745 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1747 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1748 gen_op_iwmmxt_set_mup();
1750 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1751 wrd
= (insn
>> 12) & 0xf;
1752 rd0
= (insn
>> 16) & 0xf;
1753 rd1
= (insn
>> 0) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1755 switch ((insn
>> 22) & 3) {
1757 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1760 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1763 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1768 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1769 gen_op_iwmmxt_set_mup();
1770 gen_op_iwmmxt_set_cup();
1772 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1773 wrd
= (insn
>> 12) & 0xf;
1774 rd0
= (insn
>> 16) & 0xf;
1775 rd1
= (insn
>> 0) & 0xf;
1776 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1777 if (insn
& (1 << 22)) {
1778 if (insn
& (1 << 20))
1779 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1781 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1783 if (insn
& (1 << 20))
1784 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1786 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1788 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1789 gen_op_iwmmxt_set_mup();
1790 gen_op_iwmmxt_set_cup();
1792 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1793 wrd
= (insn
>> 12) & 0xf;
1794 rd0
= (insn
>> 16) & 0xf;
1795 rd1
= (insn
>> 0) & 0xf;
1796 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1797 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1798 gen_op_movl_T1_im(7);
1799 gen_op_andl_T0_T1();
1800 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1801 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1802 gen_op_iwmmxt_set_mup();
1804 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1805 rd
= (insn
>> 12) & 0xf;
1806 wrd
= (insn
>> 16) & 0xf;
1807 gen_movl_T0_reg(s
, rd
);
1808 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1809 switch ((insn
>> 6) & 3) {
1811 gen_op_movl_T1_im(0xff);
1812 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1815 gen_op_movl_T1_im(0xffff);
1816 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1819 gen_op_movl_T1_im(0xffffffff);
1820 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1825 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1826 gen_op_iwmmxt_set_mup();
1828 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1829 rd
= (insn
>> 12) & 0xf;
1830 wrd
= (insn
>> 16) & 0xf;
1833 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1834 switch ((insn
>> 22) & 3) {
1837 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1839 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1844 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1846 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1850 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1855 gen_movl_reg_T0(s
, rd
);
1857 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1858 if ((insn
& 0x000ff008) != 0x0003f000)
1860 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1861 switch ((insn
>> 22) & 3) {
1863 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1866 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1869 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1874 gen_op_shll_T1_im(28);
1875 gen_set_nzcv(cpu_T
[1]);
1877 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1878 rd
= (insn
>> 12) & 0xf;
1879 wrd
= (insn
>> 16) & 0xf;
1880 gen_movl_T0_reg(s
, rd
);
1881 switch ((insn
>> 6) & 3) {
1883 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1886 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1889 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1894 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1895 gen_op_iwmmxt_set_mup();
1897 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1898 if ((insn
& 0x000ff00f) != 0x0003f000)
1900 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1901 gen_op_movl_T0_T1();
1902 switch ((insn
>> 22) & 3) {
1904 for (i
= 0; i
< 7; i
++) {
1905 gen_op_shll_T1_im(4);
1906 gen_op_andl_T0_T1();
1910 for (i
= 0; i
< 3; i
++) {
1911 gen_op_shll_T1_im(8);
1912 gen_op_andl_T0_T1();
1916 gen_op_shll_T1_im(16);
1917 gen_op_andl_T0_T1();
1922 gen_set_nzcv(cpu_T
[0]);
1924 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1925 wrd
= (insn
>> 12) & 0xf;
1926 rd0
= (insn
>> 16) & 0xf;
1927 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1928 switch ((insn
>> 22) & 3) {
1930 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1933 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1936 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1941 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1942 gen_op_iwmmxt_set_mup();
1944 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1945 if ((insn
& 0x000ff00f) != 0x0003f000)
1947 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1948 gen_op_movl_T0_T1();
1949 switch ((insn
>> 22) & 3) {
1951 for (i
= 0; i
< 7; i
++) {
1952 gen_op_shll_T1_im(4);
1957 for (i
= 0; i
< 3; i
++) {
1958 gen_op_shll_T1_im(8);
1963 gen_op_shll_T1_im(16);
1969 gen_set_nzcv(cpu_T
[0]);
1971 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1972 rd
= (insn
>> 12) & 0xf;
1973 rd0
= (insn
>> 16) & 0xf;
1974 if ((insn
& 0xf) != 0)
1976 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1977 switch ((insn
>> 22) & 3) {
1979 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
1982 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
1985 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
1990 gen_movl_reg_T0(s
, rd
);
1992 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1993 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1994 wrd
= (insn
>> 12) & 0xf;
1995 rd0
= (insn
>> 16) & 0xf;
1996 rd1
= (insn
>> 0) & 0xf;
1997 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1998 switch ((insn
>> 22) & 3) {
2000 if (insn
& (1 << 21))
2001 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2003 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2006 if (insn
& (1 << 21))
2007 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2009 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2012 if (insn
& (1 << 21))
2013 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2015 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2020 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2021 gen_op_iwmmxt_set_mup();
2022 gen_op_iwmmxt_set_cup();
2024 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2025 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2026 wrd
= (insn
>> 12) & 0xf;
2027 rd0
= (insn
>> 16) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2029 switch ((insn
>> 22) & 3) {
2031 if (insn
& (1 << 21))
2032 gen_op_iwmmxt_unpacklsb_M0();
2034 gen_op_iwmmxt_unpacklub_M0();
2037 if (insn
& (1 << 21))
2038 gen_op_iwmmxt_unpacklsw_M0();
2040 gen_op_iwmmxt_unpackluw_M0();
2043 if (insn
& (1 << 21))
2044 gen_op_iwmmxt_unpacklsl_M0();
2046 gen_op_iwmmxt_unpacklul_M0();
2051 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2055 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2056 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2057 wrd
= (insn
>> 12) & 0xf;
2058 rd0
= (insn
>> 16) & 0xf;
2059 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2060 switch ((insn
>> 22) & 3) {
2062 if (insn
& (1 << 21))
2063 gen_op_iwmmxt_unpackhsb_M0();
2065 gen_op_iwmmxt_unpackhub_M0();
2068 if (insn
& (1 << 21))
2069 gen_op_iwmmxt_unpackhsw_M0();
2071 gen_op_iwmmxt_unpackhuw_M0();
2074 if (insn
& (1 << 21))
2075 gen_op_iwmmxt_unpackhsl_M0();
2077 gen_op_iwmmxt_unpackhul_M0();
2082 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2086 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2087 case 0x214: case 0x614: case 0xa14: case 0xe14:
2088 wrd
= (insn
>> 12) & 0xf;
2089 rd0
= (insn
>> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2091 if (gen_iwmmxt_shift(insn
, 0xff))
2093 switch ((insn
>> 22) & 3) {
2097 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2100 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2103 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2106 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2107 gen_op_iwmmxt_set_mup();
2108 gen_op_iwmmxt_set_cup();
2110 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2111 case 0x014: case 0x414: case 0x814: case 0xc14:
2112 wrd
= (insn
>> 12) & 0xf;
2113 rd0
= (insn
>> 16) & 0xf;
2114 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2115 if (gen_iwmmxt_shift(insn
, 0xff))
2117 switch ((insn
>> 22) & 3) {
2121 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2124 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2127 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2130 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2131 gen_op_iwmmxt_set_mup();
2132 gen_op_iwmmxt_set_cup();
2134 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2135 case 0x114: case 0x514: case 0x914: case 0xd14:
2136 wrd
= (insn
>> 12) & 0xf;
2137 rd0
= (insn
>> 16) & 0xf;
2138 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2139 if (gen_iwmmxt_shift(insn
, 0xff))
2141 switch ((insn
>> 22) & 3) {
2145 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2148 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2151 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2154 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2155 gen_op_iwmmxt_set_mup();
2156 gen_op_iwmmxt_set_cup();
2158 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2159 case 0x314: case 0x714: case 0xb14: case 0xf14:
2160 wrd
= (insn
>> 12) & 0xf;
2161 rd0
= (insn
>> 16) & 0xf;
2162 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2163 switch ((insn
>> 22) & 3) {
2167 if (gen_iwmmxt_shift(insn
, 0xf))
2169 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2172 if (gen_iwmmxt_shift(insn
, 0x1f))
2174 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2177 if (gen_iwmmxt_shift(insn
, 0x3f))
2179 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2182 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2183 gen_op_iwmmxt_set_mup();
2184 gen_op_iwmmxt_set_cup();
2186 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2187 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2188 wrd
= (insn
>> 12) & 0xf;
2189 rd0
= (insn
>> 16) & 0xf;
2190 rd1
= (insn
>> 0) & 0xf;
2191 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2192 switch ((insn
>> 22) & 3) {
2194 if (insn
& (1 << 21))
2195 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2197 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2200 if (insn
& (1 << 21))
2201 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2203 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2206 if (insn
& (1 << 21))
2207 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2209 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2214 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2215 gen_op_iwmmxt_set_mup();
2217 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2218 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2219 wrd
= (insn
>> 12) & 0xf;
2220 rd0
= (insn
>> 16) & 0xf;
2221 rd1
= (insn
>> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2223 switch ((insn
>> 22) & 3) {
2225 if (insn
& (1 << 21))
2226 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2228 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2231 if (insn
& (1 << 21))
2232 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2234 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2237 if (insn
& (1 << 21))
2238 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2240 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2245 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2246 gen_op_iwmmxt_set_mup();
2248 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2249 case 0x402: case 0x502: case 0x602: case 0x702:
2250 wrd
= (insn
>> 12) & 0xf;
2251 rd0
= (insn
>> 16) & 0xf;
2252 rd1
= (insn
>> 0) & 0xf;
2253 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2254 gen_op_movl_T0_im((insn
>> 20) & 3);
2255 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2256 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2257 gen_op_iwmmxt_set_mup();
2259 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2260 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2261 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2262 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2263 wrd
= (insn
>> 12) & 0xf;
2264 rd0
= (insn
>> 16) & 0xf;
2265 rd1
= (insn
>> 0) & 0xf;
2266 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2267 switch ((insn
>> 20) & 0xf) {
2269 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2272 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2275 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2278 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2281 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2284 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2287 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2290 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2293 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2298 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2299 gen_op_iwmmxt_set_mup();
2300 gen_op_iwmmxt_set_cup();
2302 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2303 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2304 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2305 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2306 wrd
= (insn
>> 12) & 0xf;
2307 rd0
= (insn
>> 16) & 0xf;
2308 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2309 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2310 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2311 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2312 gen_op_iwmmxt_set_mup();
2313 gen_op_iwmmxt_set_cup();
2315 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2316 case 0x418: case 0x518: case 0x618: case 0x718:
2317 case 0x818: case 0x918: case 0xa18: case 0xb18:
2318 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2319 wrd
= (insn
>> 12) & 0xf;
2320 rd0
= (insn
>> 16) & 0xf;
2321 rd1
= (insn
>> 0) & 0xf;
2322 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2323 switch ((insn
>> 20) & 0xf) {
2325 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2328 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2331 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2334 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2337 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2340 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2343 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2346 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2349 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2354 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2355 gen_op_iwmmxt_set_mup();
2356 gen_op_iwmmxt_set_cup();
2358 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2359 case 0x408: case 0x508: case 0x608: case 0x708:
2360 case 0x808: case 0x908: case 0xa08: case 0xb08:
2361 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2362 wrd
= (insn
>> 12) & 0xf;
2363 rd0
= (insn
>> 16) & 0xf;
2364 rd1
= (insn
>> 0) & 0xf;
2365 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2366 if (!(insn
& (1 << 20)))
2368 switch ((insn
>> 22) & 3) {
2372 if (insn
& (1 << 21))
2373 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2375 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2378 if (insn
& (1 << 21))
2379 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2381 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2384 if (insn
& (1 << 21))
2385 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2387 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2390 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2391 gen_op_iwmmxt_set_mup();
2392 gen_op_iwmmxt_set_cup();
2394 case 0x201: case 0x203: case 0x205: case 0x207:
2395 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2396 case 0x211: case 0x213: case 0x215: case 0x217:
2397 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2398 wrd
= (insn
>> 5) & 0xf;
2399 rd0
= (insn
>> 12) & 0xf;
2400 rd1
= (insn
>> 0) & 0xf;
2401 if (rd0
== 0xf || rd1
== 0xf)
2403 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2404 switch ((insn
>> 16) & 0xf) {
2405 case 0x0: /* TMIA */
2406 gen_movl_T0_reg(s
, rd0
);
2407 gen_movl_T1_reg(s
, rd1
);
2408 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2410 case 0x8: /* TMIAPH */
2411 gen_movl_T0_reg(s
, rd0
);
2412 gen_movl_T1_reg(s
, rd1
);
2413 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2415 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2416 gen_movl_T1_reg(s
, rd0
);
2417 if (insn
& (1 << 16))
2418 gen_op_shrl_T1_im(16);
2419 gen_op_movl_T0_T1();
2420 gen_movl_T1_reg(s
, rd1
);
2421 if (insn
& (1 << 17))
2422 gen_op_shrl_T1_im(16);
2423 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2428 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2429 gen_op_iwmmxt_set_mup();
2438 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2439 (ie. an undefined instruction). */
2440 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2442 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2444 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2445 /* Multiply with Internal Accumulate Format */
2446 rd0
= (insn
>> 12) & 0xf;
2448 acc
= (insn
>> 5) & 7;
2453 switch ((insn
>> 16) & 0xf) {
2455 gen_movl_T0_reg(s
, rd0
);
2456 gen_movl_T1_reg(s
, rd1
);
2457 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2459 case 0x8: /* MIAPH */
2460 gen_movl_T0_reg(s
, rd0
);
2461 gen_movl_T1_reg(s
, rd1
);
2462 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2464 case 0xc: /* MIABB */
2465 case 0xd: /* MIABT */
2466 case 0xe: /* MIATB */
2467 case 0xf: /* MIATT */
2468 gen_movl_T1_reg(s
, rd0
);
2469 if (insn
& (1 << 16))
2470 gen_op_shrl_T1_im(16);
2471 gen_op_movl_T0_T1();
2472 gen_movl_T1_reg(s
, rd1
);
2473 if (insn
& (1 << 17))
2474 gen_op_shrl_T1_im(16);
2475 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2481 gen_op_iwmmxt_movq_wRn_M0(acc
);
2485 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2486 /* Internal Accumulator Access Format */
2487 rdhi
= (insn
>> 16) & 0xf;
2488 rdlo
= (insn
>> 12) & 0xf;
2494 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2495 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2496 gen_movl_reg_T0(s
, rdlo
);
2497 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2498 gen_op_andl_T0_T1();
2499 gen_movl_reg_T0(s
, rdhi
);
2501 gen_movl_T0_reg(s
, rdlo
);
2502 gen_movl_T1_reg(s
, rdhi
);
2503 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2511 /* Disassemble system coprocessor instruction. Return nonzero if
2512 instruction is not defined. */
2513 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2516 uint32_t rd
= (insn
>> 12) & 0xf;
2517 uint32_t cp
= (insn
>> 8) & 0xf;
2522 if (insn
& ARM_CP_RW_BIT
) {
2523 if (!env
->cp
[cp
].cp_read
)
2525 gen_set_pc_im(s
->pc
);
2527 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2528 store_reg(s
, rd
, tmp
);
2530 if (!env
->cp
[cp
].cp_write
)
2532 gen_set_pc_im(s
->pc
);
2533 tmp
= load_reg(s
, rd
);
2534 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2540 static int cp15_user_ok(uint32_t insn
)
2542 int cpn
= (insn
>> 16) & 0xf;
2543 int cpm
= insn
& 0xf;
2544 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2546 if (cpn
== 13 && cpm
== 0) {
2548 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2552 /* ISB, DSB, DMB. */
2553 if ((cpm
== 5 && op
== 4)
2554 || (cpm
== 10 && (op
== 4 || op
== 5)))
2560 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2561 instruction is not defined. */
2562 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2567 /* M profile cores use memory mapped registers instead of cp15. */
2568 if (arm_feature(env
, ARM_FEATURE_M
))
2571 if ((insn
& (1 << 25)) == 0) {
2572 if (insn
& (1 << 20)) {
2576 /* mcrr. Used for block cache operations, so implement as no-op. */
2579 if ((insn
& (1 << 4)) == 0) {
2583 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2586 if ((insn
& 0x0fff0fff) == 0x0e070f90
2587 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2588 /* Wait for interrupt. */
2589 gen_set_pc_im(s
->pc
);
2590 s
->is_jmp
= DISAS_WFI
;
2593 rd
= (insn
>> 12) & 0xf;
2594 if (insn
& ARM_CP_RW_BIT
) {
2596 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2597 /* If the destination register is r15 then sets condition codes. */
2599 store_reg(s
, rd
, tmp
);
2603 tmp
= load_reg(s
, rd
);
2604 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2606 /* Normally we would always end the TB here, but Linux
2607 * arch/arm/mach-pxa/sleep.S expects two instructions following
2608 * an MMU enable to execute from cache. Imitate this behaviour. */
2609 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2610 (insn
& 0x0fff0fff) != 0x0e010f10)
2616 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2617 #define VFP_SREG(insn, bigbit, smallbit) \
2618 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2619 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2620 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2621 reg = (((insn) >> (bigbit)) & 0x0f) \
2622 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2624 if (insn & (1 << (smallbit))) \
2626 reg = ((insn) >> (bigbit)) & 0x0f; \
2629 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2630 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2631 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2632 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2633 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2634 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2636 /* Move between integer and VFP cores. */
2637 static TCGv
gen_vfp_mrs(void)
2639 TCGv tmp
= new_tmp();
2640 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2644 static void gen_vfp_msr(TCGv tmp
)
2646 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2651 vfp_enabled(CPUState
* env
)
2653 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2656 static void gen_neon_dup_u8(TCGv var
, int shift
)
2658 TCGv tmp
= new_tmp();
2660 tcg_gen_shri_i32(var
, var
, shift
);
2661 tcg_gen_ext8u_i32(var
, var
);
2662 tcg_gen_shli_i32(tmp
, var
, 8);
2663 tcg_gen_or_i32(var
, var
, tmp
);
2664 tcg_gen_shli_i32(tmp
, var
, 16);
2665 tcg_gen_or_i32(var
, var
, tmp
);
2669 static void gen_neon_dup_low16(TCGv var
)
2671 TCGv tmp
= new_tmp();
2672 tcg_gen_ext16u_i32(var
, var
);
2673 tcg_gen_shli_i32(tmp
, var
, 16);
2674 tcg_gen_or_i32(var
, var
, tmp
);
2678 static void gen_neon_dup_high16(TCGv var
)
2680 TCGv tmp
= new_tmp();
2681 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2682 tcg_gen_shri_i32(tmp
, var
, 16);
2683 tcg_gen_or_i32(var
, var
, tmp
);
2687 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2688 (ie. an undefined instruction). */
2689 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2691 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2696 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2699 if (!vfp_enabled(env
)) {
2700 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2701 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2703 rn
= (insn
>> 16) & 0xf;
2704 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2705 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2708 dp
= ((insn
& 0xf00) == 0xb00);
2709 switch ((insn
>> 24) & 0xf) {
2711 if (insn
& (1 << 4)) {
2712 /* single register transfer */
2713 rd
= (insn
>> 12) & 0xf;
2718 VFP_DREG_N(rn
, insn
);
2721 if (insn
& 0x00c00060
2722 && !arm_feature(env
, ARM_FEATURE_NEON
))
2725 pass
= (insn
>> 21) & 1;
2726 if (insn
& (1 << 22)) {
2728 offset
= ((insn
>> 5) & 3) * 8;
2729 } else if (insn
& (1 << 5)) {
2731 offset
= (insn
& (1 << 6)) ? 16 : 0;
2736 if (insn
& ARM_CP_RW_BIT
) {
2738 tmp
= neon_load_reg(rn
, pass
);
2742 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2743 if (insn
& (1 << 23))
2749 if (insn
& (1 << 23)) {
2751 tcg_gen_shri_i32(tmp
, tmp
, 16);
2757 tcg_gen_sari_i32(tmp
, tmp
, 16);
2766 store_reg(s
, rd
, tmp
);
2769 tmp
= load_reg(s
, rd
);
2770 if (insn
& (1 << 23)) {
2773 gen_neon_dup_u8(tmp
, 0);
2774 } else if (size
== 1) {
2775 gen_neon_dup_low16(tmp
);
2777 for (n
= 0; n
<= pass
* 2; n
++) {
2779 tcg_gen_mov_i32(tmp2
, tmp
);
2780 neon_store_reg(rn
, n
, tmp2
);
2782 neon_store_reg(rn
, n
, tmp
);
2787 tmp2
= neon_load_reg(rn
, pass
);
2788 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2792 tmp2
= neon_load_reg(rn
, pass
);
2793 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2799 neon_store_reg(rn
, pass
, tmp
);
2803 if ((insn
& 0x6f) != 0x00)
2805 rn
= VFP_SREG_N(insn
);
2806 if (insn
& ARM_CP_RW_BIT
) {
2808 if (insn
& (1 << 21)) {
2809 /* system register */
2814 /* VFP2 allows access to FSID from userspace.
2815 VFP3 restricts all id registers to privileged
2818 && arm_feature(env
, ARM_FEATURE_VFP3
))
2820 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2825 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2827 case ARM_VFP_FPINST
:
2828 case ARM_VFP_FPINST2
:
2829 /* Not present in VFP3. */
2831 || arm_feature(env
, ARM_FEATURE_VFP3
))
2833 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2837 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2838 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2841 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2847 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2849 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2855 gen_mov_F0_vreg(0, rn
);
2856 tmp
= gen_vfp_mrs();
2859 /* Set the 4 flag bits in the CPSR. */
2863 store_reg(s
, rd
, tmp
);
2867 tmp
= load_reg(s
, rd
);
2868 if (insn
& (1 << 21)) {
2870 /* system register */
2875 /* Writes are ignored. */
2878 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2885 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2888 case ARM_VFP_FPINST
:
2889 case ARM_VFP_FPINST2
:
2890 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2897 gen_mov_vreg_F0(0, rn
);
2902 /* data processing */
2903 /* The opcode is in bits 23, 21, 20 and 6. */
2904 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2908 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2910 /* rn is register number */
2911 VFP_DREG_N(rn
, insn
);
2914 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2915 /* Integer or single precision destination. */
2916 rd
= VFP_SREG_D(insn
);
2918 VFP_DREG_D(rd
, insn
);
2921 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2922 /* Integer source. */
2923 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2925 VFP_DREG_M(rm
, insn
);
2928 rn
= VFP_SREG_N(insn
);
2929 if (op
== 15 && rn
== 15) {
2930 /* Double precision destination. */
2931 VFP_DREG_D(rd
, insn
);
2933 rd
= VFP_SREG_D(insn
);
2935 rm
= VFP_SREG_M(insn
);
2938 veclen
= env
->vfp
.vec_len
;
2939 if (op
== 15 && rn
> 3)
2942 /* Shut up compiler warnings. */
2953 /* Figure out what type of vector operation this is. */
2954 if ((rd
& bank_mask
) == 0) {
2959 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2961 delta_d
= env
->vfp
.vec_stride
+ 1;
2963 if ((rm
& bank_mask
) == 0) {
2964 /* mixed scalar/vector */
2973 /* Load the initial operands. */
2978 /* Integer source */
2979 gen_mov_F0_vreg(0, rm
);
2984 gen_mov_F0_vreg(dp
, rd
);
2985 gen_mov_F1_vreg(dp
, rm
);
2989 /* Compare with zero */
2990 gen_mov_F0_vreg(dp
, rd
);
3001 /* Source and destination the same. */
3002 gen_mov_F0_vreg(dp
, rd
);
3005 /* One source operand. */
3006 gen_mov_F0_vreg(dp
, rm
);
3010 /* Two source operands. */
3011 gen_mov_F0_vreg(dp
, rn
);
3012 gen_mov_F1_vreg(dp
, rm
);
3016 /* Perform the calculation. */
3018 case 0: /* mac: fd + (fn * fm) */
3020 gen_mov_F1_vreg(dp
, rd
);
3023 case 1: /* nmac: fd - (fn * fm) */
3026 gen_mov_F1_vreg(dp
, rd
);
3029 case 2: /* msc: -fd + (fn * fm) */
3031 gen_mov_F1_vreg(dp
, rd
);
3034 case 3: /* nmsc: -fd - (fn * fm) */
3037 gen_mov_F1_vreg(dp
, rd
);
3040 case 4: /* mul: fn * fm */
3043 case 5: /* nmul: -(fn * fm) */
3047 case 6: /* add: fn + fm */
3050 case 7: /* sub: fn - fm */
3053 case 8: /* div: fn / fm */
3056 case 14: /* fconst */
3057 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3060 n
= (insn
<< 12) & 0x80000000;
3061 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3068 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3075 tcg_gen_movi_i32(cpu_F0s
, n
);
3078 case 15: /* extension space */
3101 case 11: /* cmpez */
3105 case 15: /* single<->double conversion */
3107 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3109 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3111 case 16: /* fuito */
3114 case 17: /* fsito */
3117 case 20: /* fshto */
3118 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3120 gen_vfp_shto(dp
, 16 - rm
);
3122 case 21: /* fslto */
3123 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3125 gen_vfp_slto(dp
, 32 - rm
);
3127 case 22: /* fuhto */
3128 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3130 gen_vfp_uhto(dp
, 16 - rm
);
3132 case 23: /* fulto */
3133 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3135 gen_vfp_ulto(dp
, 32 - rm
);
3137 case 24: /* ftoui */
3140 case 25: /* ftouiz */
3143 case 26: /* ftosi */
3146 case 27: /* ftosiz */
3149 case 28: /* ftosh */
3150 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3152 gen_vfp_tosh(dp
, 16 - rm
);
3154 case 29: /* ftosl */
3155 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3157 gen_vfp_tosl(dp
, 32 - rm
);
3159 case 30: /* ftouh */
3160 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3162 gen_vfp_touh(dp
, 16 - rm
);
3164 case 31: /* ftoul */
3165 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3167 gen_vfp_toul(dp
, 32 - rm
);
3169 default: /* undefined */
3170 printf ("rn:%d\n", rn
);
3174 default: /* undefined */
3175 printf ("op:%d\n", op
);
3179 /* Write back the result. */
3180 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3181 ; /* Comparison, do nothing. */
3182 else if (op
== 15 && rn
> 17)
3183 /* Integer result. */
3184 gen_mov_vreg_F0(0, rd
);
3185 else if (op
== 15 && rn
== 15)
3187 gen_mov_vreg_F0(!dp
, rd
);
3189 gen_mov_vreg_F0(dp
, rd
);
3191 /* break out of the loop if we have finished */
3195 if (op
== 15 && delta_m
== 0) {
3196 /* single source one-many */
3198 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3200 gen_mov_vreg_F0(dp
, rd
);
3204 /* Setup the next operands. */
3206 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3210 /* One source operand. */
3211 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3213 gen_mov_F0_vreg(dp
, rm
);
3215 /* Two source operands. */
3216 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3218 gen_mov_F0_vreg(dp
, rn
);
3220 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3222 gen_mov_F1_vreg(dp
, rm
);
3230 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3231 /* two-register transfer */
3232 rn
= (insn
>> 16) & 0xf;
3233 rd
= (insn
>> 12) & 0xf;
3235 VFP_DREG_M(rm
, insn
);
3237 rm
= VFP_SREG_M(insn
);
3240 if (insn
& ARM_CP_RW_BIT
) {
3243 gen_mov_F0_vreg(0, rm
* 2);
3244 tmp
= gen_vfp_mrs();
3245 store_reg(s
, rd
, tmp
);
3246 gen_mov_F0_vreg(0, rm
* 2 + 1);
3247 tmp
= gen_vfp_mrs();
3248 store_reg(s
, rn
, tmp
);
3250 gen_mov_F0_vreg(0, rm
);
3251 tmp
= gen_vfp_mrs();
3252 store_reg(s
, rn
, tmp
);
3253 gen_mov_F0_vreg(0, rm
+ 1);
3254 tmp
= gen_vfp_mrs();
3255 store_reg(s
, rd
, tmp
);
3260 tmp
= load_reg(s
, rd
);
3262 gen_mov_vreg_F0(0, rm
* 2);
3263 tmp
= load_reg(s
, rn
);
3265 gen_mov_vreg_F0(0, rm
* 2 + 1);
3267 tmp
= load_reg(s
, rn
);
3269 gen_mov_vreg_F0(0, rm
);
3270 tmp
= load_reg(s
, rd
);
3272 gen_mov_vreg_F0(0, rm
+ 1);
3277 rn
= (insn
>> 16) & 0xf;
3279 VFP_DREG_D(rd
, insn
);
3281 rd
= VFP_SREG_D(insn
);
3282 if (s
->thumb
&& rn
== 15) {
3283 gen_op_movl_T1_im(s
->pc
& ~2);
3285 gen_movl_T1_reg(s
, rn
);
3287 if ((insn
& 0x01200000) == 0x01000000) {
3288 /* Single load/store */
3289 offset
= (insn
& 0xff) << 2;
3290 if ((insn
& (1 << 23)) == 0)
3292 gen_op_addl_T1_im(offset
);
3293 if (insn
& (1 << 20)) {
3295 gen_mov_vreg_F0(dp
, rd
);
3297 gen_mov_F0_vreg(dp
, rd
);
3301 /* load/store multiple */
3303 n
= (insn
>> 1) & 0x7f;
3307 if (insn
& (1 << 24)) /* pre-decrement */
3308 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3314 for (i
= 0; i
< n
; i
++) {
3315 if (insn
& ARM_CP_RW_BIT
) {
3318 gen_mov_vreg_F0(dp
, rd
+ i
);
3321 gen_mov_F0_vreg(dp
, rd
+ i
);
3324 gen_op_addl_T1_im(offset
);
3326 if (insn
& (1 << 21)) {
3328 if (insn
& (1 << 24))
3329 offset
= -offset
* n
;
3330 else if (dp
&& (insn
& 1))
3336 gen_op_addl_T1_im(offset
);
3337 gen_movl_reg_T1(s
, rn
);
3343 /* Should never happen. */
3349 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3351 TranslationBlock
*tb
;
3354 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3356 gen_set_pc_im(dest
);
3357 tcg_gen_exit_tb((long)tb
+ n
);
3359 gen_set_pc_im(dest
);
3364 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3366 if (unlikely(s
->singlestep_enabled
)) {
3367 /* An indirect jump so that we still trigger the debug exception. */
3372 gen_goto_tb(s
, 0, dest
);
3373 s
->is_jmp
= DISAS_TB_JUMP
;
3377 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3380 tcg_gen_sari_i32(t0
, t0
, 16);
3384 tcg_gen_sari_i32(t1
, t1
, 16);
3387 tcg_gen_mul_i32(t0
, t0
, t1
);
3390 /* Return the mask of PSR bits set by a MSR instruction. */
3391 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3395 if (flags
& (1 << 0))
3397 if (flags
& (1 << 1))
3399 if (flags
& (1 << 2))
3401 if (flags
& (1 << 3))
3404 /* Mask out undefined bits. */
3405 mask
&= ~CPSR_RESERVED
;
3406 if (!arm_feature(env
, ARM_FEATURE_V6
))
3407 mask
&= ~(CPSR_E
| CPSR_GE
);
3408 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3410 /* Mask out execution state bits. */
3413 /* Mask out privileged bits. */
3419 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3420 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3424 /* ??? This is also undefined in system mode. */
3428 tmp
= load_cpu_field(spsr
);
3429 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3430 tcg_gen_andi_i32(t0
, t0
, mask
);
3431 tcg_gen_or_i32(tmp
, tmp
, t0
);
3432 store_cpu_field(tmp
, spsr
);
3434 gen_set_cpsr(t0
, mask
);
3441 /* Returns nonzero if access to the PSR is not permitted. */
3442 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3446 tcg_gen_movi_i32(tmp
, val
);
3447 return gen_set_psr(s
, mask
, spsr
, tmp
);
3450 /* Generate an old-style exception return. Marks pc as dead. */
3451 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3454 store_reg(s
, 15, pc
);
3455 tmp
= load_cpu_field(spsr
);
3456 gen_set_cpsr(tmp
, 0xffffffff);
3458 s
->is_jmp
= DISAS_UPDATE
;
3461 /* Generate a v6 exception return. Marks both values as dead. */
3462 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3464 gen_set_cpsr(cpsr
, 0xffffffff);
3466 store_reg(s
, 15, pc
);
3467 s
->is_jmp
= DISAS_UPDATE
;
3471 gen_set_condexec (DisasContext
*s
)
3473 if (s
->condexec_mask
) {
3474 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3475 TCGv tmp
= new_tmp();
3476 tcg_gen_movi_i32(tmp
, val
);
3477 store_cpu_field(tmp
, condexec_bits
);
3481 static void gen_nop_hint(DisasContext
*s
, int val
)
3485 gen_set_pc_im(s
->pc
);
3486 s
->is_jmp
= DISAS_WFI
;
3490 /* TODO: Implement SEV and WFE. May help SMP performance. */
3496 /* These macros help make the code more readable when migrating from the
3497 old dyngen helpers. They should probably be removed when
3498 T0/T1 are removed. */
3499 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3500 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3502 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3504 static inline int gen_neon_add(int size
)
3507 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3508 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3509 case 2: gen_op_addl_T0_T1(); break;
3515 static inline void gen_neon_rsb(int size
)
3518 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3519 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3520 case 2: gen_op_rsbl_T0_T1(); break;
3525 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3526 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3527 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3528 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3529 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3531 /* FIXME: This is wrong. They set the wrong overflow bit. */
3532 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3533 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3534 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3535 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3537 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3538 switch ((size << 1) | u) { \
3540 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3543 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3546 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3549 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3552 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3555 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3557 default: return 1; \
3560 #define GEN_NEON_INTEGER_OP(name) do { \
3561 switch ((size << 1) | u) { \
3563 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3566 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3569 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3572 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3575 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3578 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3580 default: return 1; \
3584 gen_neon_movl_scratch_T0(int scratch
)
3588 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3589 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3593 gen_neon_movl_scratch_T1(int scratch
)
3597 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3598 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3602 gen_neon_movl_T0_scratch(int scratch
)
3606 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3607 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3611 gen_neon_movl_T1_scratch(int scratch
)
3615 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3616 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3619 static inline void gen_neon_get_scalar(int size
, int reg
)
3622 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3624 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3626 gen_neon_dup_low16(cpu_T
[0]);
3628 gen_neon_dup_high16(cpu_T
[0]);
3632 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3640 tcg_gen_andi_i32(rd
, t0
, 0xff);
3641 tcg_gen_shri_i32(tmp
, t0
, 8);
3642 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3643 tcg_gen_or_i32(rd
, rd
, tmp
);
3644 tcg_gen_shli_i32(tmp
, t1
, 16);
3645 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3646 tcg_gen_or_i32(rd
, rd
, tmp
);
3647 tcg_gen_shli_i32(tmp
, t1
, 8);
3648 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3649 tcg_gen_or_i32(rd
, rd
, tmp
);
3651 tcg_gen_shri_i32(rm
, t0
, 8);
3652 tcg_gen_andi_i32(rm
, rm
, 0xff);
3653 tcg_gen_shri_i32(tmp
, t0
, 16);
3654 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3655 tcg_gen_or_i32(rm
, rm
, tmp
);
3656 tcg_gen_shli_i32(tmp
, t1
, 8);
3657 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3658 tcg_gen_or_i32(rm
, rm
, tmp
);
3659 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3660 tcg_gen_or_i32(t1
, rm
, tmp
);
3661 tcg_gen_mov_i32(t0
, rd
);
3668 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3676 tcg_gen_andi_i32(rd
, t0
, 0xff);
3677 tcg_gen_shli_i32(tmp
, t1
, 8);
3678 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3679 tcg_gen_or_i32(rd
, rd
, tmp
);
3680 tcg_gen_shli_i32(tmp
, t0
, 16);
3681 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3682 tcg_gen_or_i32(rd
, rd
, tmp
);
3683 tcg_gen_shli_i32(tmp
, t1
, 24);
3684 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3685 tcg_gen_or_i32(rd
, rd
, tmp
);
3687 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3688 tcg_gen_shri_i32(tmp
, t0
, 8);
3689 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3690 tcg_gen_or_i32(rm
, rm
, tmp
);
3691 tcg_gen_shri_i32(tmp
, t1
, 8);
3692 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3693 tcg_gen_or_i32(rm
, rm
, tmp
);
3694 tcg_gen_shri_i32(tmp
, t0
, 16);
3695 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3696 tcg_gen_or_i32(t1
, rm
, tmp
);
3697 tcg_gen_mov_i32(t0
, rd
);
3704 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3711 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3712 tcg_gen_shli_i32(tmp2
, t1
, 16);
3713 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3714 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3715 tcg_gen_shri_i32(tmp2
, t0
, 16);
3716 tcg_gen_or_i32(t1
, t1
, tmp2
);
3717 tcg_gen_mov_i32(t0
, tmp
);
3723 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3727 for (n
= 0; n
< q
+ 1; n
+= 2) {
3728 NEON_GET_REG(T0
, reg
, n
);
3729 NEON_GET_REG(T1
, reg
, n
+ 1);
3731 case 0: gen_neon_unzip_u8(cpu_T
[0], cpu_T
[1]); break;
3732 case 1: gen_neon_zip_u16(cpu_T
[0], cpu_T
[1]); break; /* zip and unzip are the same. */
3733 case 2: /* no-op */; break;
3736 gen_neon_movl_T0_scratch(tmp
+ n
);
3737 gen_neon_movl_T1_scratch(tmp
+ n
+ 1);
3741 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3748 tcg_gen_shli_i32(rd
, t0
, 8);
3749 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3750 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3751 tcg_gen_or_i32(rd
, rd
, tmp
);
3753 tcg_gen_shri_i32(t1
, t1
, 8);
3754 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3755 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3756 tcg_gen_or_i32(t1
, t1
, tmp
);
3757 tcg_gen_mov_i32(t0
, rd
);
3763 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3770 tcg_gen_shli_i32(rd
, t0
, 16);
3771 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3772 tcg_gen_or_i32(rd
, rd
, tmp
);
3773 tcg_gen_shri_i32(t1
, t1
, 16);
3774 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3775 tcg_gen_or_i32(t1
, t1
, tmp
);
3776 tcg_gen_mov_i32(t0
, rd
);
3787 } neon_ls_element_type
[11] = {
3801 /* Translate a NEON load/store element instruction. Return nonzero if the
3802 instruction is invalid. */
3803 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3819 if (!vfp_enabled(env
))
3821 VFP_DREG_D(rd
, insn
);
3822 rn
= (insn
>> 16) & 0xf;
3824 load
= (insn
& (1 << 21)) != 0;
3825 if ((insn
& (1 << 23)) == 0) {
3826 /* Load store all elements. */
3827 op
= (insn
>> 8) & 0xf;
3828 size
= (insn
>> 6) & 3;
3829 if (op
> 10 || size
== 3)
3831 nregs
= neon_ls_element_type
[op
].nregs
;
3832 interleave
= neon_ls_element_type
[op
].interleave
;
3833 gen_movl_T1_reg(s
, rn
);
3834 stride
= (1 << size
) * interleave
;
3835 for (reg
= 0; reg
< nregs
; reg
++) {
3836 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3837 gen_movl_T1_reg(s
, rn
);
3838 gen_op_addl_T1_im((1 << size
) * reg
);
3839 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3840 gen_movl_T1_reg(s
, rn
);
3841 gen_op_addl_T1_im(1 << size
);
3843 for (pass
= 0; pass
< 2; pass
++) {
3846 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3847 neon_store_reg(rd
, pass
, tmp
);
3849 tmp
= neon_load_reg(rd
, pass
);
3850 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3852 gen_op_addl_T1_im(stride
);
3853 } else if (size
== 1) {
3855 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3856 gen_op_addl_T1_im(stride
);
3857 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3858 gen_op_addl_T1_im(stride
);
3859 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3861 neon_store_reg(rd
, pass
, tmp
);
3863 tmp
= neon_load_reg(rd
, pass
);
3865 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3866 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3867 gen_op_addl_T1_im(stride
);
3868 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3869 gen_op_addl_T1_im(stride
);
3871 } else /* size == 0 */ {
3874 for (n
= 0; n
< 4; n
++) {
3875 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3876 gen_op_addl_T1_im(stride
);
3880 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3884 neon_store_reg(rd
, pass
, tmp2
);
3886 tmp2
= neon_load_reg(rd
, pass
);
3887 for (n
= 0; n
< 4; n
++) {
3890 tcg_gen_mov_i32(tmp
, tmp2
);
3892 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3894 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3895 gen_op_addl_T1_im(stride
);
3901 rd
+= neon_ls_element_type
[op
].spacing
;
3905 size
= (insn
>> 10) & 3;
3907 /* Load single element to all lanes. */
3910 size
= (insn
>> 6) & 3;
3911 nregs
= ((insn
>> 8) & 3) + 1;
3912 stride
= (insn
& (1 << 5)) ? 2 : 1;
3913 gen_movl_T1_reg(s
, rn
);
3914 for (reg
= 0; reg
< nregs
; reg
++) {
3917 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3918 gen_neon_dup_u8(tmp
, 0);
3921 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3922 gen_neon_dup_low16(tmp
);
3925 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3929 default: /* Avoid compiler warnings. */
3932 gen_op_addl_T1_im(1 << size
);
3934 tcg_gen_mov_i32(tmp2
, tmp
);
3935 neon_store_reg(rd
, 0, tmp2
);
3936 neon_store_reg(rd
, 1, tmp
);
3939 stride
= (1 << size
) * nregs
;
3941 /* Single element. */
3942 pass
= (insn
>> 7) & 1;
3945 shift
= ((insn
>> 5) & 3) * 8;
3949 shift
= ((insn
>> 6) & 1) * 16;
3950 stride
= (insn
& (1 << 5)) ? 2 : 1;
3954 stride
= (insn
& (1 << 6)) ? 2 : 1;
3959 nregs
= ((insn
>> 8) & 3) + 1;
3960 gen_movl_T1_reg(s
, rn
);
3961 for (reg
= 0; reg
< nregs
; reg
++) {
3965 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3968 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3971 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3973 default: /* Avoid compiler warnings. */
3977 tmp2
= neon_load_reg(rd
, pass
);
3978 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3981 neon_store_reg(rd
, pass
, tmp
);
3982 } else { /* Store */
3983 tmp
= neon_load_reg(rd
, pass
);
3985 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3988 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3991 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3994 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3999 gen_op_addl_T1_im(1 << size
);
4001 stride
= nregs
* (1 << size
);
4007 base
= load_reg(s
, rn
);
4009 tcg_gen_addi_i32(base
, base
, stride
);
4012 index
= load_reg(s
, rm
);
4013 tcg_gen_add_i32(base
, base
, index
);
4016 store_reg(s
, rn
, base
);
4021 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4022 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4024 tcg_gen_and_i32(t
, t
, c
);
4025 tcg_gen_bic_i32(f
, f
, c
);
4026 tcg_gen_or_i32(dest
, t
, f
);
4029 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4032 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4033 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4034 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4039 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4042 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4043 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4044 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4049 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4052 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4053 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4054 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4059 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4065 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4066 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4071 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4072 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4079 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4080 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4085 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4086 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4093 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4097 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4098 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4099 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4104 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4105 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4106 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4113 static inline void gen_neon_addl(int size
)
4116 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4117 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4118 case 2: tcg_gen_add_i64(CPU_V001
); break;
4123 static inline void gen_neon_subl(int size
)
4126 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4127 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4128 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4133 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4136 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4137 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4138 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4143 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4146 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4147 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4152 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4156 switch ((size
<< 1) | u
) {
4157 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4158 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4159 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4160 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4162 tmp
= gen_muls_i64_i32(a
, b
);
4163 tcg_gen_mov_i64(dest
, tmp
);
4166 tmp
= gen_mulu_i64_i32(a
, b
);
4167 tcg_gen_mov_i64(dest
, tmp
);
4177 /* Translate a NEON data processing instruction. Return nonzero if the
4178 instruction is invalid.
4179 We process data in a mixture of 32-bit and 64-bit chunks.
4180 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4182 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4200 if (!vfp_enabled(env
))
4202 q
= (insn
& (1 << 6)) != 0;
4203 u
= (insn
>> 24) & 1;
4204 VFP_DREG_D(rd
, insn
);
4205 VFP_DREG_N(rn
, insn
);
4206 VFP_DREG_M(rm
, insn
);
4207 size
= (insn
>> 20) & 3;
4208 if ((insn
& (1 << 23)) == 0) {
4209 /* Three register same length. */
4210 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4211 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4212 || op
== 10 || op
== 11 || op
== 16)) {
4213 /* 64-bit element instructions. */
4214 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4215 neon_load_reg64(cpu_V0
, rn
+ pass
);
4216 neon_load_reg64(cpu_V1
, rm
+ pass
);
4220 gen_helper_neon_add_saturate_u64(CPU_V001
);
4222 gen_helper_neon_add_saturate_s64(CPU_V001
);
4227 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4229 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4234 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4236 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4241 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4244 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4248 case 10: /* VRSHL */
4250 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4252 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4255 case 11: /* VQRSHL */
4257 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4260 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4266 tcg_gen_sub_i64(CPU_V001
);
4268 tcg_gen_add_i64(CPU_V001
);
4274 neon_store_reg64(cpu_V0
, rd
+ pass
);
4281 case 10: /* VRSHL */
4282 case 11: /* VQRSHL */
4285 /* Shift instruction operands are reversed. */
4292 case 20: /* VPMAX */
4293 case 21: /* VPMIN */
4294 case 23: /* VPADD */
4297 case 26: /* VPADD (float) */
4298 pairwise
= (u
&& size
< 2);
4300 case 30: /* VPMIN/VPMAX (float) */
4307 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4316 NEON_GET_REG(T0
, rn
, n
);
4317 NEON_GET_REG(T1
, rn
, n
+ 1);
4319 NEON_GET_REG(T0
, rm
, n
);
4320 NEON_GET_REG(T1
, rm
, n
+ 1);
4324 NEON_GET_REG(T0
, rn
, pass
);
4325 NEON_GET_REG(T1
, rm
, pass
);
4329 GEN_NEON_INTEGER_OP(hadd
);
4332 GEN_NEON_INTEGER_OP_ENV(qadd
);
4334 case 2: /* VRHADD */
4335 GEN_NEON_INTEGER_OP(rhadd
);
4337 case 3: /* Logic ops. */
4338 switch ((u
<< 2) | size
) {
4340 gen_op_andl_T0_T1();
4343 gen_op_bicl_T0_T1();
4353 gen_op_xorl_T0_T1();
4356 tmp
= neon_load_reg(rd
, pass
);
4357 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4361 tmp
= neon_load_reg(rd
, pass
);
4362 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4366 tmp
= neon_load_reg(rd
, pass
);
4367 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4373 GEN_NEON_INTEGER_OP(hsub
);
4376 GEN_NEON_INTEGER_OP_ENV(qsub
);
4379 GEN_NEON_INTEGER_OP(cgt
);
4382 GEN_NEON_INTEGER_OP(cge
);
4385 GEN_NEON_INTEGER_OP(shl
);
4388 GEN_NEON_INTEGER_OP_ENV(qshl
);
4390 case 10: /* VRSHL */
4391 GEN_NEON_INTEGER_OP(rshl
);
4393 case 11: /* VQRSHL */
4394 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4397 GEN_NEON_INTEGER_OP(max
);
4400 GEN_NEON_INTEGER_OP(min
);
4403 GEN_NEON_INTEGER_OP(abd
);
4406 GEN_NEON_INTEGER_OP(abd
);
4407 NEON_GET_REG(T1
, rd
, pass
);
4411 if (!u
) { /* VADD */
4412 if (gen_neon_add(size
))
4416 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4417 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4418 case 2: gen_op_subl_T0_T1(); break;
4424 if (!u
) { /* VTST */
4426 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4427 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4428 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4433 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4434 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4435 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4440 case 18: /* Multiply. */
4442 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4443 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4444 case 2: gen_op_mul_T0_T1(); break;
4447 NEON_GET_REG(T1
, rd
, pass
);
4455 if (u
) { /* polynomial */
4456 gen_helper_neon_mul_p8(CPU_T001
);
4457 } else { /* Integer */
4459 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4460 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4461 case 2: gen_op_mul_T0_T1(); break;
4466 case 20: /* VPMAX */
4467 GEN_NEON_INTEGER_OP(pmax
);
4469 case 21: /* VPMIN */
4470 GEN_NEON_INTEGER_OP(pmin
);
4472 case 22: /* Hultiply high. */
4473 if (!u
) { /* VQDMULH */
4475 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4476 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4479 } else { /* VQRDHMUL */
4481 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4482 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4487 case 23: /* VPADD */
4491 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4492 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4493 case 2: gen_op_addl_T0_T1(); break;
4497 case 26: /* Floating point arithnetic. */
4498 switch ((u
<< 2) | size
) {
4500 gen_helper_neon_add_f32(CPU_T001
);
4503 gen_helper_neon_sub_f32(CPU_T001
);
4506 gen_helper_neon_add_f32(CPU_T001
);
4509 gen_helper_neon_abd_f32(CPU_T001
);
4515 case 27: /* Float multiply. */
4516 gen_helper_neon_mul_f32(CPU_T001
);
4518 NEON_GET_REG(T1
, rd
, pass
);
4520 gen_helper_neon_add_f32(CPU_T001
);
4522 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4526 case 28: /* Float compare. */
4528 gen_helper_neon_ceq_f32(CPU_T001
);
4531 gen_helper_neon_cge_f32(CPU_T001
);
4533 gen_helper_neon_cgt_f32(CPU_T001
);
4536 case 29: /* Float compare absolute. */
4540 gen_helper_neon_acge_f32(CPU_T001
);
4542 gen_helper_neon_acgt_f32(CPU_T001
);
4544 case 30: /* Float min/max. */
4546 gen_helper_neon_max_f32(CPU_T001
);
4548 gen_helper_neon_min_f32(CPU_T001
);
4552 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4554 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4559 /* Save the result. For elementwise operations we can put it
4560 straight into the destination register. For pairwise operations
4561 we have to be careful to avoid clobbering the source operands. */
4562 if (pairwise
&& rd
== rm
) {
4563 gen_neon_movl_scratch_T0(pass
);
4565 NEON_SET_REG(T0
, rd
, pass
);
4569 if (pairwise
&& rd
== rm
) {
4570 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4571 gen_neon_movl_T0_scratch(pass
);
4572 NEON_SET_REG(T0
, rd
, pass
);
4575 /* End of 3 register same size operations. */
4576 } else if (insn
& (1 << 4)) {
4577 if ((insn
& 0x00380080) != 0) {
4578 /* Two registers and shift. */
4579 op
= (insn
>> 8) & 0xf;
4580 if (insn
& (1 << 7)) {
4585 while ((insn
& (1 << (size
+ 19))) == 0)
4588 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4589 /* To avoid excessive dumplication of ops we implement shift
4590 by immediate using the variable shift operations. */
4592 /* Shift by immediate:
4593 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4594 /* Right shifts are encoded as N - shift, where N is the
4595 element size in bits. */
4597 shift
= shift
- (1 << (size
+ 3));
4605 imm
= (uint8_t) shift
;
4610 imm
= (uint16_t) shift
;
4621 for (pass
= 0; pass
< count
; pass
++) {
4623 neon_load_reg64(cpu_V0
, rm
+ pass
);
4624 tcg_gen_movi_i64(cpu_V1
, imm
);
4629 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4631 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4636 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4638 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4643 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4645 case 5: /* VSHL, VSLI */
4646 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4650 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4652 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4654 case 7: /* VQSHLU */
4655 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4658 if (op
== 1 || op
== 3) {
4660 neon_load_reg64(cpu_V0
, rd
+ pass
);
4661 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4662 } else if (op
== 4 || (op
== 5 && u
)) {
4664 cpu_abort(env
, "VS[LR]I.64 not implemented");
4666 neon_store_reg64(cpu_V0
, rd
+ pass
);
4667 } else { /* size < 3 */
4668 /* Operands in T0 and T1. */
4669 gen_op_movl_T1_im(imm
);
4670 NEON_GET_REG(T0
, rm
, pass
);
4674 GEN_NEON_INTEGER_OP(shl
);
4678 GEN_NEON_INTEGER_OP(rshl
);
4683 GEN_NEON_INTEGER_OP(shl
);
4685 case 5: /* VSHL, VSLI */
4687 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4688 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4689 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4694 GEN_NEON_INTEGER_OP_ENV(qshl
);
4696 case 7: /* VQSHLU */
4698 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4699 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4700 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4706 if (op
== 1 || op
== 3) {
4708 NEON_GET_REG(T1
, rd
, pass
);
4710 } else if (op
== 4 || (op
== 5 && u
)) {
4715 imm
= 0xff >> -shift
;
4717 imm
= (uint8_t)(0xff << shift
);
4723 imm
= 0xffff >> -shift
;
4725 imm
= (uint16_t)(0xffff << shift
);
4730 imm
= 0xffffffffu
>> -shift
;
4732 imm
= 0xffffffffu
<< shift
;
4737 tmp
= neon_load_reg(rd
, pass
);
4738 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4739 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4740 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4742 NEON_SET_REG(T0
, rd
, pass
);
4745 } else if (op
< 10) {
4746 /* Shift by immediate and narrow:
4747 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4748 shift
= shift
- (1 << (size
+ 3));
4752 imm
= (uint16_t)shift
;
4754 tmp2
= tcg_const_i32(imm
);
4755 TCGV_UNUSED_I64(tmp64
);
4758 imm
= (uint32_t)shift
;
4759 tmp2
= tcg_const_i32(imm
);
4760 TCGV_UNUSED_I64(tmp64
);
4763 tmp64
= tcg_const_i64(shift
);
4770 for (pass
= 0; pass
< 2; pass
++) {
4772 neon_load_reg64(cpu_V0
, rm
+ pass
);
4775 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4777 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4780 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4782 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4785 tmp
= neon_load_reg(rm
+ pass
, 0);
4786 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4787 tmp3
= neon_load_reg(rm
+ pass
, 1);
4788 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4789 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4794 if (op
== 8 && !u
) {
4795 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4798 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4800 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4805 neon_store_reg(rd
, 0, tmp2
);
4806 neon_store_reg(rd
, 1, tmp
);
4809 } else if (op
== 10) {
4813 tmp
= neon_load_reg(rm
, 0);
4814 tmp2
= neon_load_reg(rm
, 1);
4815 for (pass
= 0; pass
< 2; pass
++) {
4819 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4822 /* The shift is less than the width of the source
4823 type, so we can just shift the whole register. */
4824 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4825 if (size
< 2 || !u
) {
4828 imm
= (0xffu
>> (8 - shift
));
4831 imm
= 0xffff >> (16 - shift
);
4833 imm64
= imm
| (((uint64_t)imm
) << 32);
4834 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4837 neon_store_reg64(cpu_V0
, rd
+ pass
);
4839 } else if (op
== 15 || op
== 16) {
4840 /* VCVT fixed-point. */
4841 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4842 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4845 gen_vfp_ulto(0, shift
);
4847 gen_vfp_slto(0, shift
);
4850 gen_vfp_toul(0, shift
);
4852 gen_vfp_tosl(0, shift
);
4854 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4859 } else { /* (insn & 0x00380080) == 0 */
4862 op
= (insn
>> 8) & 0xf;
4863 /* One register and immediate. */
4864 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4865 invert
= (insn
& (1 << 5)) != 0;
4883 imm
= (imm
<< 8) | (imm
<< 24);
4886 imm
= (imm
< 8) | 0xff;
4889 imm
= (imm
<< 16) | 0xffff;
4892 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4897 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4898 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4904 if (op
!= 14 || !invert
)
4905 gen_op_movl_T1_im(imm
);
4907 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4908 if (op
& 1 && op
< 12) {
4909 tmp
= neon_load_reg(rd
, pass
);
4911 /* The immediate value has already been inverted, so
4913 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4915 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4920 if (op
== 14 && invert
) {
4923 for (n
= 0; n
< 4; n
++) {
4924 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4925 val
|= 0xff << (n
* 8);
4927 tcg_gen_movi_i32(tmp
, val
);
4929 tcg_gen_movi_i32(tmp
, imm
);
4932 neon_store_reg(rd
, pass
, tmp
);
4935 } else { /* (insn & 0x00800010 == 0x00800000) */
4937 op
= (insn
>> 8) & 0xf;
4938 if ((insn
& (1 << 6)) == 0) {
4939 /* Three registers of different lengths. */
4943 /* prewiden, src1_wide, src2_wide */
4944 static const int neon_3reg_wide
[16][3] = {
4945 {1, 0, 0}, /* VADDL */
4946 {1, 1, 0}, /* VADDW */
4947 {1, 0, 0}, /* VSUBL */
4948 {1, 1, 0}, /* VSUBW */
4949 {0, 1, 1}, /* VADDHN */
4950 {0, 0, 0}, /* VABAL */
4951 {0, 1, 1}, /* VSUBHN */
4952 {0, 0, 0}, /* VABDL */
4953 {0, 0, 0}, /* VMLAL */
4954 {0, 0, 0}, /* VQDMLAL */
4955 {0, 0, 0}, /* VMLSL */
4956 {0, 0, 0}, /* VQDMLSL */
4957 {0, 0, 0}, /* Integer VMULL */
4958 {0, 0, 0}, /* VQDMULL */
4959 {0, 0, 0} /* Polynomial VMULL */
4962 prewiden
= neon_3reg_wide
[op
][0];
4963 src1_wide
= neon_3reg_wide
[op
][1];
4964 src2_wide
= neon_3reg_wide
[op
][2];
4966 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4969 /* Avoid overlapping operands. Wide source operands are
4970 always aligned so will never overlap with wide
4971 destinations in problematic ways. */
4972 if (rd
== rm
&& !src2_wide
) {
4973 NEON_GET_REG(T0
, rm
, 1);
4974 gen_neon_movl_scratch_T0(2);
4975 } else if (rd
== rn
&& !src1_wide
) {
4976 NEON_GET_REG(T0
, rn
, 1);
4977 gen_neon_movl_scratch_T0(2);
4980 for (pass
= 0; pass
< 2; pass
++) {
4982 neon_load_reg64(cpu_V0
, rn
+ pass
);
4985 if (pass
== 1 && rd
== rn
) {
4986 gen_neon_movl_T0_scratch(2);
4988 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4990 tmp
= neon_load_reg(rn
, pass
);
4993 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4997 neon_load_reg64(cpu_V1
, rm
+ pass
);
5000 if (pass
== 1 && rd
== rm
) {
5001 gen_neon_movl_T0_scratch(2);
5003 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5005 tmp2
= neon_load_reg(rm
, pass
);
5008 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5012 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5013 gen_neon_addl(size
);
5015 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
5016 gen_neon_subl(size
);
5018 case 5: case 7: /* VABAL, VABDL */
5019 switch ((size
<< 1) | u
) {
5021 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5024 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5027 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5030 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5033 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5036 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5043 case 8: case 9: case 10: case 11: case 12: case 13:
5044 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5045 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5047 case 14: /* Polynomial VMULL */
5048 cpu_abort(env
, "Polynomial VMULL not implemented");
5050 default: /* 15 is RESERVED. */
5053 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5055 if (op
== 10 || op
== 11) {
5056 gen_neon_negl(cpu_V0
, size
);
5060 neon_load_reg64(cpu_V1
, rd
+ pass
);
5064 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5065 gen_neon_addl(size
);
5067 case 9: case 11: /* VQDMLAL, VQDMLSL */
5068 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5069 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5072 case 13: /* VQDMULL */
5073 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5078 neon_store_reg64(cpu_V0
, rd
+ pass
);
5079 } else if (op
== 4 || op
== 6) {
5080 /* Narrowing operation. */
5085 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5088 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5091 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5092 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5099 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5102 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5105 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5106 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5107 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5115 neon_store_reg(rd
, 0, tmp3
);
5116 neon_store_reg(rd
, 1, tmp
);
5119 /* Write back the result. */
5120 neon_store_reg64(cpu_V0
, rd
+ pass
);
5124 /* Two registers and a scalar. */
5126 case 0: /* Integer VMLA scalar */
5127 case 1: /* Float VMLA scalar */
5128 case 4: /* Integer VMLS scalar */
5129 case 5: /* Floating point VMLS scalar */
5130 case 8: /* Integer VMUL scalar */
5131 case 9: /* Floating point VMUL scalar */
5132 case 12: /* VQDMULH scalar */
5133 case 13: /* VQRDMULH scalar */
5134 gen_neon_get_scalar(size
, rm
);
5135 gen_neon_movl_scratch_T0(0);
5136 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5138 gen_neon_movl_T0_scratch(0);
5139 NEON_GET_REG(T1
, rn
, pass
);
5142 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5144 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5146 } else if (op
== 13) {
5148 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5150 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5152 } else if (op
& 1) {
5153 gen_helper_neon_mul_f32(CPU_T001
);
5156 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5157 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5158 case 2: gen_op_mul_T0_T1(); break;
5164 NEON_GET_REG(T1
, rd
, pass
);
5170 gen_helper_neon_add_f32(CPU_T001
);
5176 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5182 NEON_SET_REG(T0
, rd
, pass
);
5185 case 2: /* VMLAL sclar */
5186 case 3: /* VQDMLAL scalar */
5187 case 6: /* VMLSL scalar */
5188 case 7: /* VQDMLSL scalar */
5189 case 10: /* VMULL scalar */
5190 case 11: /* VQDMULL scalar */
5191 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5194 gen_neon_get_scalar(size
, rm
);
5195 NEON_GET_REG(T1
, rn
, 1);
5197 for (pass
= 0; pass
< 2; pass
++) {
5199 tmp
= neon_load_reg(rn
, 0);
5202 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5205 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5206 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5207 if (op
== 6 || op
== 7) {
5208 gen_neon_negl(cpu_V0
, size
);
5211 neon_load_reg64(cpu_V1
, rd
+ pass
);
5215 gen_neon_addl(size
);
5218 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5219 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5225 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5230 neon_store_reg64(cpu_V0
, rd
+ pass
);
5233 default: /* 14 and 15 are RESERVED */
5237 } else { /* size == 3 */
5240 imm
= (insn
>> 8) & 0xf;
5247 neon_load_reg64(cpu_V0
, rn
);
5249 neon_load_reg64(cpu_V1
, rn
+ 1);
5251 } else if (imm
== 8) {
5252 neon_load_reg64(cpu_V0
, rn
+ 1);
5254 neon_load_reg64(cpu_V1
, rm
);
5257 tmp64
= tcg_temp_new_i64();
5259 neon_load_reg64(cpu_V0
, rn
);
5260 neon_load_reg64(tmp64
, rn
+ 1);
5262 neon_load_reg64(cpu_V0
, rn
+ 1);
5263 neon_load_reg64(tmp64
, rm
);
5265 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5266 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5267 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5269 neon_load_reg64(cpu_V1
, rm
);
5271 neon_load_reg64(cpu_V1
, rm
+ 1);
5274 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5275 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5276 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5279 neon_load_reg64(cpu_V0
, rn
);
5280 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5281 neon_load_reg64(cpu_V1
, rm
);
5282 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5283 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5285 neon_store_reg64(cpu_V0
, rd
);
5287 neon_store_reg64(cpu_V1
, rd
+ 1);
5289 } else if ((insn
& (1 << 11)) == 0) {
5290 /* Two register misc. */
5291 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5292 size
= (insn
>> 18) & 3;
5294 case 0: /* VREV64 */
5297 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5298 NEON_GET_REG(T0
, rm
, pass
* 2);
5299 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5301 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5302 case 1: gen_swap_half(cpu_T
[0]); break;
5303 case 2: /* no-op */ break;
5306 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5308 NEON_SET_REG(T1
, rd
, pass
* 2);
5310 gen_op_movl_T0_T1();
5312 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5313 case 1: gen_swap_half(cpu_T
[0]); break;
5316 NEON_SET_REG(T0
, rd
, pass
* 2);
5320 case 4: case 5: /* VPADDL */
5321 case 12: case 13: /* VPADAL */
5324 for (pass
= 0; pass
< q
+ 1; pass
++) {
5325 tmp
= neon_load_reg(rm
, pass
* 2);
5326 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5327 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5328 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5330 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5331 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5332 case 2: tcg_gen_add_i64(CPU_V001
); break;
5337 neon_load_reg64(cpu_V1
, rd
+ pass
);
5338 gen_neon_addl(size
);
5340 neon_store_reg64(cpu_V0
, rd
+ pass
);
5345 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5346 NEON_GET_REG(T0
, rm
, n
);
5347 NEON_GET_REG(T1
, rd
, n
+ 1);
5348 NEON_SET_REG(T1
, rm
, n
);
5349 NEON_SET_REG(T0
, rd
, n
+ 1);
5357 Rd A3 A2 A1 A0 B2 B0 A2 A0
5358 Rm B3 B2 B1 B0 B3 B1 A3 A1
5362 gen_neon_unzip(rd
, q
, 0, size
);
5363 gen_neon_unzip(rm
, q
, 4, size
);
5365 static int unzip_order_q
[8] =
5366 {0, 2, 4, 6, 1, 3, 5, 7};
5367 for (n
= 0; n
< 8; n
++) {
5368 int reg
= (n
< 4) ? rd
: rm
;
5369 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5370 NEON_SET_REG(T0
, reg
, n
% 4);
5373 static int unzip_order
[4] =
5375 for (n
= 0; n
< 4; n
++) {
5376 int reg
= (n
< 2) ? rd
: rm
;
5377 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5378 NEON_SET_REG(T0
, reg
, n
% 2);
5384 Rd A3 A2 A1 A0 B1 A1 B0 A0
5385 Rm B3 B2 B1 B0 B3 A3 B2 A2
5389 count
= (q
? 4 : 2);
5390 for (n
= 0; n
< count
; n
++) {
5391 NEON_GET_REG(T0
, rd
, n
);
5392 NEON_GET_REG(T1
, rd
, n
);
5394 case 0: gen_neon_zip_u8(cpu_T
[0], cpu_T
[1]); break;
5395 case 1: gen_neon_zip_u16(cpu_T
[0], cpu_T
[1]); break;
5396 case 2: /* no-op */; break;
5399 gen_neon_movl_scratch_T0(n
* 2);
5400 gen_neon_movl_scratch_T1(n
* 2 + 1);
5402 for (n
= 0; n
< count
* 2; n
++) {
5403 int reg
= (n
< count
) ? rd
: rm
;
5404 gen_neon_movl_T0_scratch(n
);
5405 NEON_SET_REG(T0
, reg
, n
% count
);
5408 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5412 for (pass
= 0; pass
< 2; pass
++) {
5413 neon_load_reg64(cpu_V0
, rm
+ pass
);
5415 if (op
== 36 && q
== 0) {
5416 gen_neon_narrow(size
, tmp
, cpu_V0
);
5418 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5420 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5425 neon_store_reg(rd
, 0, tmp2
);
5426 neon_store_reg(rd
, 1, tmp
);
5430 case 38: /* VSHLL */
5433 tmp
= neon_load_reg(rm
, 0);
5434 tmp2
= neon_load_reg(rm
, 1);
5435 for (pass
= 0; pass
< 2; pass
++) {
5438 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5439 neon_store_reg64(cpu_V0
, rd
+ pass
);
5444 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5445 if (op
== 30 || op
== 31 || op
>= 58) {
5446 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5447 neon_reg_offset(rm
, pass
));
5449 NEON_GET_REG(T0
, rm
, pass
);
5452 case 1: /* VREV32 */
5454 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5455 case 1: gen_swap_half(cpu_T
[0]); break;
5459 case 2: /* VREV16 */
5462 gen_rev16(cpu_T
[0]);
5466 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5467 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5468 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5474 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5475 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5476 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5483 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5490 case 14: /* VQABS */
5492 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5493 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5494 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5498 case 15: /* VQNEG */
5500 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5501 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5502 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5506 case 16: case 19: /* VCGT #0, VCLE #0 */
5507 gen_op_movl_T1_im(0);
5509 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5510 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5511 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5517 case 17: case 20: /* VCGE #0, VCLT #0 */
5518 gen_op_movl_T1_im(0);
5520 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5521 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5522 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5528 case 18: /* VCEQ #0 */
5529 gen_op_movl_T1_im(0);
5531 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5532 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5533 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5539 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5540 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5541 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5546 gen_op_movl_T1_im(0);
5551 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5552 gen_op_movl_T1_im(0);
5553 gen_helper_neon_cgt_f32(CPU_T001
);
5557 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5558 gen_op_movl_T1_im(0);
5559 gen_helper_neon_cge_f32(CPU_T001
);
5563 case 26: /* Float VCEQ #0 */
5564 gen_op_movl_T1_im(0);
5565 gen_helper_neon_ceq_f32(CPU_T001
);
5567 case 30: /* Float VABS */
5570 case 31: /* Float VNEG */
5574 NEON_GET_REG(T1
, rd
, pass
);
5575 NEON_SET_REG(T1
, rm
, pass
);
5578 NEON_GET_REG(T1
, rd
, pass
);
5580 case 0: gen_neon_trn_u8(cpu_T
[0], cpu_T
[1]); break;
5581 case 1: gen_neon_trn_u16(cpu_T
[0], cpu_T
[1]); break;
5585 NEON_SET_REG(T1
, rm
, pass
);
5587 case 56: /* Integer VRECPE */
5588 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5590 case 57: /* Integer VRSQRTE */
5591 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5593 case 58: /* Float VRECPE */
5594 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5596 case 59: /* Float VRSQRTE */
5597 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5599 case 60: /* VCVT.F32.S32 */
5602 case 61: /* VCVT.F32.U32 */
5605 case 62: /* VCVT.S32.F32 */
5608 case 63: /* VCVT.U32.F32 */
5612 /* Reserved: 21, 29, 39-56 */
5615 if (op
== 30 || op
== 31 || op
>= 58) {
5616 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5617 neon_reg_offset(rd
, pass
));
5619 NEON_SET_REG(T0
, rd
, pass
);
5624 } else if ((insn
& (1 << 10)) == 0) {
5626 n
= ((insn
>> 5) & 0x18) + 8;
5627 if (insn
& (1 << 6)) {
5628 tmp
= neon_load_reg(rd
, 0);
5631 tcg_gen_movi_i32(tmp
, 0);
5633 tmp2
= neon_load_reg(rm
, 0);
5634 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5637 if (insn
& (1 << 6)) {
5638 tmp
= neon_load_reg(rd
, 1);
5641 tcg_gen_movi_i32(tmp
, 0);
5643 tmp3
= neon_load_reg(rm
, 1);
5644 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5646 neon_store_reg(rd
, 0, tmp2
);
5647 neon_store_reg(rd
, 1, tmp3
);
5649 } else if ((insn
& 0x380) == 0) {
5651 if (insn
& (1 << 19)) {
5652 NEON_SET_REG(T0
, rm
, 1);
5654 NEON_SET_REG(T0
, rm
, 0);
5656 if (insn
& (1 << 16)) {
5657 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5658 } else if (insn
& (1 << 17)) {
5659 if ((insn
>> 18) & 1)
5660 gen_neon_dup_high16(cpu_T
[0]);
5662 gen_neon_dup_low16(cpu_T
[0]);
5664 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5665 NEON_SET_REG(T0
, rd
, pass
);
5675 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5677 int crn
= (insn
>> 16) & 0xf;
5678 int crm
= insn
& 0xf;
5679 int op1
= (insn
>> 21) & 7;
5680 int op2
= (insn
>> 5) & 7;
5681 int rt
= (insn
>> 12) & 0xf;
5684 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5685 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5689 tmp
= load_cpu_field(teecr
);
5690 store_reg(s
, rt
, tmp
);
5693 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5695 if (IS_USER(s
) && (env
->teecr
& 1))
5697 tmp
= load_cpu_field(teehbr
);
5698 store_reg(s
, rt
, tmp
);
5702 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5703 op1
, crn
, crm
, op2
);
5707 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5709 int crn
= (insn
>> 16) & 0xf;
5710 int crm
= insn
& 0xf;
5711 int op1
= (insn
>> 21) & 7;
5712 int op2
= (insn
>> 5) & 7;
5713 int rt
= (insn
>> 12) & 0xf;
5716 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5717 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5721 tmp
= load_reg(s
, rt
);
5722 gen_helper_set_teecr(cpu_env
, tmp
);
5726 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5728 if (IS_USER(s
) && (env
->teecr
& 1))
5730 tmp
= load_reg(s
, rt
);
5731 store_cpu_field(tmp
, teehbr
);
5735 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5736 op1
, crn
, crm
, op2
);
5740 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5744 cpnum
= (insn
>> 8) & 0xf;
5745 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5746 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5752 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5753 return disas_iwmmxt_insn(env
, s
, insn
);
5754 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5755 return disas_dsp_insn(env
, s
, insn
);
5760 return disas_vfp_insn (env
, s
, insn
);
5762 /* Coprocessors 7-15 are architecturally reserved by ARM.
5763 Unfortunately Intel decided to ignore this. */
5764 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5766 if (insn
& (1 << 20))
5767 return disas_cp14_read(env
, s
, insn
);
5769 return disas_cp14_write(env
, s
, insn
);
5771 return disas_cp15_insn (env
, s
, insn
);
5774 /* Unknown coprocessor. See if the board has hooked it. */
5775 return disas_cp_insn (env
, s
, insn
);
5780 /* Store a 64-bit value to a register pair. Clobbers val. */
5781 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5785 tcg_gen_trunc_i64_i32(tmp
, val
);
5786 store_reg(s
, rlow
, tmp
);
5788 tcg_gen_shri_i64(val
, val
, 32);
5789 tcg_gen_trunc_i64_i32(tmp
, val
);
5790 store_reg(s
, rhigh
, tmp
);
5793 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5794 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5799 /* Load value and extend to 64 bits. */
5800 tmp
= tcg_temp_new_i64();
5801 tmp2
= load_reg(s
, rlow
);
5802 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5804 tcg_gen_add_i64(val
, val
, tmp
);
5807 /* load and add a 64-bit value from a register pair. */
5808 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5814 /* Load 64-bit value rd:rn. */
5815 tmpl
= load_reg(s
, rlow
);
5816 tmph
= load_reg(s
, rhigh
);
5817 tmp
= tcg_temp_new_i64();
5818 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5821 tcg_gen_add_i64(val
, val
, tmp
);
5824 /* Set N and Z flags from a 64-bit value. */
5825 static void gen_logicq_cc(TCGv_i64 val
)
5827 TCGv tmp
= new_tmp();
5828 gen_helper_logicq_cc(tmp
, val
);
5833 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5835 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5842 insn
= ldl_code(s
->pc
);
5845 /* M variants do not implement ARM mode. */
5850 /* Unconditional instructions. */
5851 if (((insn
>> 25) & 7) == 1) {
5852 /* NEON Data processing. */
5853 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5856 if (disas_neon_data_insn(env
, s
, insn
))
5860 if ((insn
& 0x0f100000) == 0x04000000) {
5861 /* NEON load/store. */
5862 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5865 if (disas_neon_ls_insn(env
, s
, insn
))
5869 if ((insn
& 0x0d70f000) == 0x0550f000)
5871 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5874 if (insn
& (1 << 9)) {
5875 /* BE8 mode not implemented. */
5879 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5880 switch ((insn
>> 4) & 0xf) {
5883 gen_helper_clrex(cpu_env
);
5889 /* We don't emulate caches so these are a no-op. */
5894 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5900 op1
= (insn
& 0x1f);
5901 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5902 addr
= load_reg(s
, 13);
5905 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5907 i
= (insn
>> 23) & 3;
5909 case 0: offset
= -4; break; /* DA */
5910 case 1: offset
= 0; break; /* IA */
5911 case 2: offset
= -8; break; /* DB */
5912 case 3: offset
= 4; break; /* IB */
5916 tcg_gen_addi_i32(addr
, addr
, offset
);
5917 tmp
= load_reg(s
, 14);
5918 gen_st32(tmp
, addr
, 0);
5919 tmp
= load_cpu_field(spsr
);
5920 tcg_gen_addi_i32(addr
, addr
, 4);
5921 gen_st32(tmp
, addr
, 0);
5922 if (insn
& (1 << 21)) {
5923 /* Base writeback. */
5925 case 0: offset
= -8; break;
5926 case 1: offset
= 4; break;
5927 case 2: offset
= -4; break;
5928 case 3: offset
= 0; break;
5932 tcg_gen_addi_i32(addr
, addr
, offset
);
5933 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5934 store_reg(s
, 13, addr
);
5936 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5942 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5948 rn
= (insn
>> 16) & 0xf;
5949 addr
= load_reg(s
, rn
);
5950 i
= (insn
>> 23) & 3;
5952 case 0: offset
= -4; break; /* DA */
5953 case 1: offset
= 0; break; /* IA */
5954 case 2: offset
= -8; break; /* DB */
5955 case 3: offset
= 4; break; /* IB */
5959 tcg_gen_addi_i32(addr
, addr
, offset
);
5960 /* Load PC into tmp and CPSR into tmp2. */
5961 tmp
= gen_ld32(addr
, 0);
5962 tcg_gen_addi_i32(addr
, addr
, 4);
5963 tmp2
= gen_ld32(addr
, 0);
5964 if (insn
& (1 << 21)) {
5965 /* Base writeback. */
5967 case 0: offset
= -8; break;
5968 case 1: offset
= 4; break;
5969 case 2: offset
= -4; break;
5970 case 3: offset
= 0; break;
5974 tcg_gen_addi_i32(addr
, addr
, offset
);
5975 store_reg(s
, rn
, addr
);
5979 gen_rfe(s
, tmp
, tmp2
);
5981 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5982 /* branch link and change to thumb (blx <offset>) */
5985 val
= (uint32_t)s
->pc
;
5987 tcg_gen_movi_i32(tmp
, val
);
5988 store_reg(s
, 14, tmp
);
5989 /* Sign-extend the 24-bit offset */
5990 offset
= (((int32_t)insn
) << 8) >> 8;
5991 /* offset * 4 + bit24 * 2 + (thumb bit) */
5992 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5993 /* pipeline offset */
5997 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5998 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5999 /* iWMMXt register transfer. */
6000 if (env
->cp15
.c15_cpar
& (1 << 1))
6001 if (!disas_iwmmxt_insn(env
, s
, insn
))
6004 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6005 /* Coprocessor double register transfer. */
6006 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6007 /* Additional coprocessor register transfer. */
6008 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6011 /* cps (privileged) */
6015 if (insn
& (1 << 19)) {
6016 if (insn
& (1 << 8))
6018 if (insn
& (1 << 7))
6020 if (insn
& (1 << 6))
6022 if (insn
& (1 << 18))
6025 if (insn
& (1 << 17)) {
6027 val
|= (insn
& 0x1f);
6030 gen_set_psr_im(s
, mask
, 0, val
);
6037 /* if not always execute, we generate a conditional jump to
6039 s
->condlabel
= gen_new_label();
6040 gen_test_cc(cond
^ 1, s
->condlabel
);
6043 if ((insn
& 0x0f900000) == 0x03000000) {
6044 if ((insn
& (1 << 21)) == 0) {
6046 rd
= (insn
>> 12) & 0xf;
6047 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6048 if ((insn
& (1 << 22)) == 0) {
6051 tcg_gen_movi_i32(tmp
, val
);
6054 tmp
= load_reg(s
, rd
);
6055 tcg_gen_ext16u_i32(tmp
, tmp
);
6056 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6058 store_reg(s
, rd
, tmp
);
6060 if (((insn
>> 12) & 0xf) != 0xf)
6062 if (((insn
>> 16) & 0xf) == 0) {
6063 gen_nop_hint(s
, insn
& 0xff);
6065 /* CPSR = immediate */
6067 shift
= ((insn
>> 8) & 0xf) * 2;
6069 val
= (val
>> shift
) | (val
<< (32 - shift
));
6070 i
= ((insn
& (1 << 22)) != 0);
6071 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6075 } else if ((insn
& 0x0f900000) == 0x01000000
6076 && (insn
& 0x00000090) != 0x00000090) {
6077 /* miscellaneous instructions */
6078 op1
= (insn
>> 21) & 3;
6079 sh
= (insn
>> 4) & 0xf;
6082 case 0x0: /* move program status register */
6085 tmp
= load_reg(s
, rm
);
6086 i
= ((op1
& 2) != 0);
6087 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6091 rd
= (insn
>> 12) & 0xf;
6095 tmp
= load_cpu_field(spsr
);
6098 gen_helper_cpsr_read(tmp
);
6100 store_reg(s
, rd
, tmp
);
6105 /* branch/exchange thumb (bx). */
6106 tmp
= load_reg(s
, rm
);
6108 } else if (op1
== 3) {
6110 rd
= (insn
>> 12) & 0xf;
6111 tmp
= load_reg(s
, rm
);
6112 gen_helper_clz(tmp
, tmp
);
6113 store_reg(s
, rd
, tmp
);
6121 /* Trivial implementation equivalent to bx. */
6122 tmp
= load_reg(s
, rm
);
6132 /* branch link/exchange thumb (blx) */
6133 tmp
= load_reg(s
, rm
);
6135 tcg_gen_movi_i32(tmp2
, s
->pc
);
6136 store_reg(s
, 14, tmp2
);
6139 case 0x5: /* saturating add/subtract */
6140 rd
= (insn
>> 12) & 0xf;
6141 rn
= (insn
>> 16) & 0xf;
6142 tmp
= load_reg(s
, rm
);
6143 tmp2
= load_reg(s
, rn
);
6145 gen_helper_double_saturate(tmp2
, tmp2
);
6147 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6149 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6151 store_reg(s
, rd
, tmp
);
6154 gen_set_condexec(s
);
6155 gen_set_pc_im(s
->pc
- 4);
6156 gen_exception(EXCP_BKPT
);
6157 s
->is_jmp
= DISAS_JUMP
;
6159 case 0x8: /* signed multiply */
6163 rs
= (insn
>> 8) & 0xf;
6164 rn
= (insn
>> 12) & 0xf;
6165 rd
= (insn
>> 16) & 0xf;
6167 /* (32 * 16) >> 16 */
6168 tmp
= load_reg(s
, rm
);
6169 tmp2
= load_reg(s
, rs
);
6171 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6174 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6175 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6177 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6178 if ((sh
& 2) == 0) {
6179 tmp2
= load_reg(s
, rn
);
6180 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6183 store_reg(s
, rd
, tmp
);
6186 tmp
= load_reg(s
, rm
);
6187 tmp2
= load_reg(s
, rs
);
6188 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6191 tmp64
= tcg_temp_new_i64();
6192 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6194 gen_addq(s
, tmp64
, rn
, rd
);
6195 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6198 tmp2
= load_reg(s
, rn
);
6199 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6202 store_reg(s
, rd
, tmp
);
6209 } else if (((insn
& 0x0e000000) == 0 &&
6210 (insn
& 0x00000090) != 0x90) ||
6211 ((insn
& 0x0e000000) == (1 << 25))) {
6212 int set_cc
, logic_cc
, shiftop
;
6214 op1
= (insn
>> 21) & 0xf;
6215 set_cc
= (insn
>> 20) & 1;
6216 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6218 /* data processing instruction */
6219 if (insn
& (1 << 25)) {
6220 /* immediate operand */
6222 shift
= ((insn
>> 8) & 0xf) * 2;
6224 val
= (val
>> shift
) | (val
<< (32 - shift
));
6227 tcg_gen_movi_i32(tmp2
, val
);
6228 if (logic_cc
&& shift
) {
6229 gen_set_CF_bit31(tmp2
);
6234 tmp2
= load_reg(s
, rm
);
6235 shiftop
= (insn
>> 5) & 3;
6236 if (!(insn
& (1 << 4))) {
6237 shift
= (insn
>> 7) & 0x1f;
6238 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6240 rs
= (insn
>> 8) & 0xf;
6241 tmp
= load_reg(s
, rs
);
6242 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6245 if (op1
!= 0x0f && op1
!= 0x0d) {
6246 rn
= (insn
>> 16) & 0xf;
6247 tmp
= load_reg(s
, rn
);
6251 rd
= (insn
>> 12) & 0xf;
6254 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6258 store_reg_bx(env
, s
, rd
, tmp
);
6261 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6265 store_reg_bx(env
, s
, rd
, tmp
);
6268 if (set_cc
&& rd
== 15) {
6269 /* SUBS r15, ... is used for exception return. */
6273 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6274 gen_exception_return(s
, tmp
);
6277 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6279 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6281 store_reg_bx(env
, s
, rd
, tmp
);
6286 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6288 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6290 store_reg_bx(env
, s
, rd
, tmp
);
6294 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6296 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6298 store_reg_bx(env
, s
, rd
, tmp
);
6302 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6304 gen_add_carry(tmp
, tmp
, tmp2
);
6306 store_reg_bx(env
, s
, rd
, tmp
);
6310 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6312 gen_sub_carry(tmp
, tmp
, tmp2
);
6314 store_reg_bx(env
, s
, rd
, tmp
);
6318 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6320 gen_sub_carry(tmp
, tmp2
, tmp
);
6322 store_reg_bx(env
, s
, rd
, tmp
);
6326 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6333 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6340 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6346 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6351 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6355 store_reg_bx(env
, s
, rd
, tmp
);
6358 if (logic_cc
&& rd
== 15) {
6359 /* MOVS r15, ... is used for exception return. */
6363 gen_exception_return(s
, tmp2
);
6368 store_reg_bx(env
, s
, rd
, tmp2
);
6372 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6376 store_reg_bx(env
, s
, rd
, tmp
);
6380 tcg_gen_not_i32(tmp2
, tmp2
);
6384 store_reg_bx(env
, s
, rd
, tmp2
);
6387 if (op1
!= 0x0f && op1
!= 0x0d) {
6391 /* other instructions */
6392 op1
= (insn
>> 24) & 0xf;
6396 /* multiplies, extra load/stores */
6397 sh
= (insn
>> 5) & 3;
6400 rd
= (insn
>> 16) & 0xf;
6401 rn
= (insn
>> 12) & 0xf;
6402 rs
= (insn
>> 8) & 0xf;
6404 op1
= (insn
>> 20) & 0xf;
6406 case 0: case 1: case 2: case 3: case 6:
6408 tmp
= load_reg(s
, rs
);
6409 tmp2
= load_reg(s
, rm
);
6410 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6412 if (insn
& (1 << 22)) {
6413 /* Subtract (mls) */
6415 tmp2
= load_reg(s
, rn
);
6416 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6418 } else if (insn
& (1 << 21)) {
6420 tmp2
= load_reg(s
, rn
);
6421 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6424 if (insn
& (1 << 20))
6426 store_reg(s
, rd
, tmp
);
6430 tmp
= load_reg(s
, rs
);
6431 tmp2
= load_reg(s
, rm
);
6432 if (insn
& (1 << 22))
6433 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6435 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6436 if (insn
& (1 << 21)) /* mult accumulate */
6437 gen_addq(s
, tmp64
, rn
, rd
);
6438 if (!(insn
& (1 << 23))) { /* double accumulate */
6440 gen_addq_lo(s
, tmp64
, rn
);
6441 gen_addq_lo(s
, tmp64
, rd
);
6443 if (insn
& (1 << 20))
6444 gen_logicq_cc(tmp64
);
6445 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6449 rn
= (insn
>> 16) & 0xf;
6450 rd
= (insn
>> 12) & 0xf;
6451 if (insn
& (1 << 23)) {
6452 /* load/store exclusive */
6453 op1
= (insn
>> 21) & 0x3;
6458 gen_movl_T1_reg(s
, rn
);
6460 if (insn
& (1 << 20)) {
6461 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6464 tmp
= gen_ld32(addr
, IS_USER(s
));
6466 case 1: /* ldrexd */
6467 tmp
= gen_ld32(addr
, IS_USER(s
));
6468 store_reg(s
, rd
, tmp
);
6469 tcg_gen_addi_i32(addr
, addr
, 4);
6470 tmp
= gen_ld32(addr
, IS_USER(s
));
6473 case 2: /* ldrexb */
6474 tmp
= gen_ld8u(addr
, IS_USER(s
));
6476 case 3: /* ldrexh */
6477 tmp
= gen_ld16u(addr
, IS_USER(s
));
6482 store_reg(s
, rd
, tmp
);
6484 int label
= gen_new_label();
6486 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6487 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6489 tmp
= load_reg(s
,rm
);
6492 gen_st32(tmp
, addr
, IS_USER(s
));
6494 case 1: /* strexd */
6495 gen_st32(tmp
, addr
, IS_USER(s
));
6496 tcg_gen_addi_i32(addr
, addr
, 4);
6497 tmp
= load_reg(s
, rm
+ 1);
6498 gen_st32(tmp
, addr
, IS_USER(s
));
6500 case 2: /* strexb */
6501 gen_st8(tmp
, addr
, IS_USER(s
));
6503 case 3: /* strexh */
6504 gen_st16(tmp
, addr
, IS_USER(s
));
6509 gen_set_label(label
);
6510 gen_movl_reg_T0(s
, rd
);
6513 /* SWP instruction */
6516 /* ??? This is not really atomic. However we know
6517 we never have multiple CPUs running in parallel,
6518 so it is good enough. */
6519 addr
= load_reg(s
, rn
);
6520 tmp
= load_reg(s
, rm
);
6521 if (insn
& (1 << 22)) {
6522 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6523 gen_st8(tmp
, addr
, IS_USER(s
));
6525 tmp2
= gen_ld32(addr
, IS_USER(s
));
6526 gen_st32(tmp
, addr
, IS_USER(s
));
6529 store_reg(s
, rd
, tmp2
);
6535 /* Misc load/store */
6536 rn
= (insn
>> 16) & 0xf;
6537 rd
= (insn
>> 12) & 0xf;
6538 addr
= load_reg(s
, rn
);
6539 if (insn
& (1 << 24))
6540 gen_add_datah_offset(s
, insn
, 0, addr
);
6542 if (insn
& (1 << 20)) {
6546 tmp
= gen_ld16u(addr
, IS_USER(s
));
6549 tmp
= gen_ld8s(addr
, IS_USER(s
));
6553 tmp
= gen_ld16s(addr
, IS_USER(s
));
6557 } else if (sh
& 2) {
6561 tmp
= load_reg(s
, rd
);
6562 gen_st32(tmp
, addr
, IS_USER(s
));
6563 tcg_gen_addi_i32(addr
, addr
, 4);
6564 tmp
= load_reg(s
, rd
+ 1);
6565 gen_st32(tmp
, addr
, IS_USER(s
));
6569 tmp
= gen_ld32(addr
, IS_USER(s
));
6570 store_reg(s
, rd
, tmp
);
6571 tcg_gen_addi_i32(addr
, addr
, 4);
6572 tmp
= gen_ld32(addr
, IS_USER(s
));
6576 address_offset
= -4;
6579 tmp
= load_reg(s
, rd
);
6580 gen_st16(tmp
, addr
, IS_USER(s
));
6583 /* Perform base writeback before the loaded value to
6584 ensure correct behavior with overlapping index registers.
6585 ldrd with base writeback is is undefined if the
6586 destination and index registers overlap. */
6587 if (!(insn
& (1 << 24))) {
6588 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6589 store_reg(s
, rn
, addr
);
6590 } else if (insn
& (1 << 21)) {
6592 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6593 store_reg(s
, rn
, addr
);
6598 /* Complete the load. */
6599 store_reg(s
, rd
, tmp
);
6608 if (insn
& (1 << 4)) {
6610 /* Armv6 Media instructions. */
6612 rn
= (insn
>> 16) & 0xf;
6613 rd
= (insn
>> 12) & 0xf;
6614 rs
= (insn
>> 8) & 0xf;
6615 switch ((insn
>> 23) & 3) {
6616 case 0: /* Parallel add/subtract. */
6617 op1
= (insn
>> 20) & 7;
6618 tmp
= load_reg(s
, rn
);
6619 tmp2
= load_reg(s
, rm
);
6620 sh
= (insn
>> 5) & 7;
6621 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6623 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6625 store_reg(s
, rd
, tmp
);
6628 if ((insn
& 0x00700020) == 0) {
6629 /* Halfword pack. */
6630 tmp
= load_reg(s
, rn
);
6631 tmp2
= load_reg(s
, rm
);
6632 shift
= (insn
>> 7) & 0x1f;
6633 if (insn
& (1 << 6)) {
6637 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6638 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6639 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6643 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6644 tcg_gen_ext16u_i32(tmp
, tmp
);
6645 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6647 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6649 store_reg(s
, rd
, tmp
);
6650 } else if ((insn
& 0x00200020) == 0x00200000) {
6652 tmp
= load_reg(s
, rm
);
6653 shift
= (insn
>> 7) & 0x1f;
6654 if (insn
& (1 << 6)) {
6657 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6659 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6661 sh
= (insn
>> 16) & 0x1f;
6663 if (insn
& (1 << 22))
6664 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6666 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6668 store_reg(s
, rd
, tmp
);
6669 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6671 tmp
= load_reg(s
, rm
);
6672 sh
= (insn
>> 16) & 0x1f;
6674 if (insn
& (1 << 22))
6675 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6677 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6679 store_reg(s
, rd
, tmp
);
6680 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6682 tmp
= load_reg(s
, rn
);
6683 tmp2
= load_reg(s
, rm
);
6685 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6686 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6689 store_reg(s
, rd
, tmp
);
6690 } else if ((insn
& 0x000003e0) == 0x00000060) {
6691 tmp
= load_reg(s
, rm
);
6692 shift
= (insn
>> 10) & 3;
6693 /* ??? In many cases it's not neccessary to do a
6694 rotate, a shift is sufficient. */
6696 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6697 op1
= (insn
>> 20) & 7;
6699 case 0: gen_sxtb16(tmp
); break;
6700 case 2: gen_sxtb(tmp
); break;
6701 case 3: gen_sxth(tmp
); break;
6702 case 4: gen_uxtb16(tmp
); break;
6703 case 6: gen_uxtb(tmp
); break;
6704 case 7: gen_uxth(tmp
); break;
6705 default: goto illegal_op
;
6708 tmp2
= load_reg(s
, rn
);
6709 if ((op1
& 3) == 0) {
6710 gen_add16(tmp
, tmp2
);
6712 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6716 store_reg(s
, rd
, tmp
);
6717 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6719 tmp
= load_reg(s
, rm
);
6720 if (insn
& (1 << 22)) {
6721 if (insn
& (1 << 7)) {
6725 gen_helper_rbit(tmp
, tmp
);
6728 if (insn
& (1 << 7))
6731 tcg_gen_bswap32_i32(tmp
, tmp
);
6733 store_reg(s
, rd
, tmp
);
6738 case 2: /* Multiplies (Type 3). */
6739 tmp
= load_reg(s
, rm
);
6740 tmp2
= load_reg(s
, rs
);
6741 if (insn
& (1 << 20)) {
6742 /* Signed multiply most significant [accumulate]. */
6743 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6744 if (insn
& (1 << 5))
6745 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6746 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6748 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6750 tmp2
= load_reg(s
, rd
);
6751 if (insn
& (1 << 6)) {
6752 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6754 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6758 store_reg(s
, rn
, tmp
);
6760 if (insn
& (1 << 5))
6761 gen_swap_half(tmp2
);
6762 gen_smul_dual(tmp
, tmp2
);
6763 /* This addition cannot overflow. */
6764 if (insn
& (1 << 6)) {
6765 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6767 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6770 if (insn
& (1 << 22)) {
6771 /* smlald, smlsld */
6772 tmp64
= tcg_temp_new_i64();
6773 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6775 gen_addq(s
, tmp64
, rd
, rn
);
6776 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6778 /* smuad, smusd, smlad, smlsd */
6781 tmp2
= load_reg(s
, rd
);
6782 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6785 store_reg(s
, rn
, tmp
);
6790 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6792 case 0: /* Unsigned sum of absolute differences. */
6794 tmp
= load_reg(s
, rm
);
6795 tmp2
= load_reg(s
, rs
);
6796 gen_helper_usad8(tmp
, tmp
, tmp2
);
6799 tmp2
= load_reg(s
, rd
);
6800 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6803 store_reg(s
, rn
, tmp
);
6805 case 0x20: case 0x24: case 0x28: case 0x2c:
6806 /* Bitfield insert/clear. */
6808 shift
= (insn
>> 7) & 0x1f;
6809 i
= (insn
>> 16) & 0x1f;
6813 tcg_gen_movi_i32(tmp
, 0);
6815 tmp
= load_reg(s
, rm
);
6818 tmp2
= load_reg(s
, rd
);
6819 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6822 store_reg(s
, rd
, tmp
);
6824 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6825 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6827 tmp
= load_reg(s
, rm
);
6828 shift
= (insn
>> 7) & 0x1f;
6829 i
= ((insn
>> 16) & 0x1f) + 1;
6834 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6836 gen_sbfx(tmp
, shift
, i
);
6839 store_reg(s
, rd
, tmp
);
6849 /* Check for undefined extension instructions
6850 * per the ARM Bible IE:
6851 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6853 sh
= (0xf << 20) | (0xf << 4);
6854 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6858 /* load/store byte/word */
6859 rn
= (insn
>> 16) & 0xf;
6860 rd
= (insn
>> 12) & 0xf;
6861 tmp2
= load_reg(s
, rn
);
6862 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6863 if (insn
& (1 << 24))
6864 gen_add_data_offset(s
, insn
, tmp2
);
6865 if (insn
& (1 << 20)) {
6867 if (insn
& (1 << 22)) {
6868 tmp
= gen_ld8u(tmp2
, i
);
6870 tmp
= gen_ld32(tmp2
, i
);
6874 tmp
= load_reg(s
, rd
);
6875 if (insn
& (1 << 22))
6876 gen_st8(tmp
, tmp2
, i
);
6878 gen_st32(tmp
, tmp2
, i
);
6880 if (!(insn
& (1 << 24))) {
6881 gen_add_data_offset(s
, insn
, tmp2
);
6882 store_reg(s
, rn
, tmp2
);
6883 } else if (insn
& (1 << 21)) {
6884 store_reg(s
, rn
, tmp2
);
6888 if (insn
& (1 << 20)) {
6889 /* Complete the load. */
6893 store_reg(s
, rd
, tmp
);
6899 int j
, n
, user
, loaded_base
;
6901 /* load/store multiple words */
6902 /* XXX: store correct base if write back */
6904 if (insn
& (1 << 22)) {
6906 goto illegal_op
; /* only usable in supervisor mode */
6908 if ((insn
& (1 << 15)) == 0)
6911 rn
= (insn
>> 16) & 0xf;
6912 addr
= load_reg(s
, rn
);
6914 /* compute total size */
6916 TCGV_UNUSED(loaded_var
);
6919 if (insn
& (1 << i
))
6922 /* XXX: test invalid n == 0 case ? */
6923 if (insn
& (1 << 23)) {
6924 if (insn
& (1 << 24)) {
6926 tcg_gen_addi_i32(addr
, addr
, 4);
6928 /* post increment */
6931 if (insn
& (1 << 24)) {
6933 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6935 /* post decrement */
6937 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6942 if (insn
& (1 << i
)) {
6943 if (insn
& (1 << 20)) {
6945 tmp
= gen_ld32(addr
, IS_USER(s
));
6949 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6951 } else if (i
== rn
) {
6955 store_reg(s
, i
, tmp
);
6960 /* special case: r15 = PC + 8 */
6961 val
= (long)s
->pc
+ 4;
6963 tcg_gen_movi_i32(tmp
, val
);
6966 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6968 tmp
= load_reg(s
, i
);
6970 gen_st32(tmp
, addr
, IS_USER(s
));
6973 /* no need to add after the last transfer */
6975 tcg_gen_addi_i32(addr
, addr
, 4);
6978 if (insn
& (1 << 21)) {
6980 if (insn
& (1 << 23)) {
6981 if (insn
& (1 << 24)) {
6984 /* post increment */
6985 tcg_gen_addi_i32(addr
, addr
, 4);
6988 if (insn
& (1 << 24)) {
6991 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6993 /* post decrement */
6994 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6997 store_reg(s
, rn
, addr
);
7002 store_reg(s
, rn
, loaded_var
);
7004 if ((insn
& (1 << 22)) && !user
) {
7005 /* Restore CPSR from SPSR. */
7006 tmp
= load_cpu_field(spsr
);
7007 gen_set_cpsr(tmp
, 0xffffffff);
7009 s
->is_jmp
= DISAS_UPDATE
;
7018 /* branch (and link) */
7019 val
= (int32_t)s
->pc
;
7020 if (insn
& (1 << 24)) {
7022 tcg_gen_movi_i32(tmp
, val
);
7023 store_reg(s
, 14, tmp
);
7025 offset
= (((int32_t)insn
<< 8) >> 8);
7026 val
+= (offset
<< 2) + 4;
7034 if (disas_coproc_insn(env
, s
, insn
))
7039 gen_set_pc_im(s
->pc
);
7040 s
->is_jmp
= DISAS_SWI
;
7044 gen_set_condexec(s
);
7045 gen_set_pc_im(s
->pc
- 4);
7046 gen_exception(EXCP_UDEF
);
7047 s
->is_jmp
= DISAS_JUMP
;
7053 /* Return true if this is a Thumb-2 logical op. */
7055 thumb2_logic_op(int op
)
7060 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7061 then set condition code flags based on the result of the operation.
7062 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7063 to the high bit of T1.
7064 Returns zero if the opcode is valid. */
7067 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
7074 gen_op_andl_T0_T1();
7078 gen_op_bicl_T0_T1();
7091 gen_op_xorl_T0_T1();
7096 gen_op_addl_T0_T1_cc();
7098 gen_op_addl_T0_T1();
7102 gen_op_adcl_T0_T1_cc();
7108 gen_op_sbcl_T0_T1_cc();
7114 gen_op_subl_T0_T1_cc();
7116 gen_op_subl_T0_T1();
7120 gen_op_rsbl_T0_T1_cc();
7122 gen_op_rsbl_T0_T1();
7124 default: /* 5, 6, 7, 9, 12, 15. */
7128 gen_op_logic_T0_cc();
7130 gen_set_CF_bit31(cpu_T
[1]);
7135 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7137 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7139 uint32_t insn
, imm
, shift
, offset
;
7140 uint32_t rd
, rn
, rm
, rs
;
7151 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7152 || arm_feature (env
, ARM_FEATURE_M
))) {
7153 /* Thumb-1 cores may need to treat bl and blx as a pair of
7154 16-bit instructions to get correct prefetch abort behavior. */
7156 if ((insn
& (1 << 12)) == 0) {
7157 /* Second half of blx. */
7158 offset
= ((insn
& 0x7ff) << 1);
7159 tmp
= load_reg(s
, 14);
7160 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7161 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7164 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7165 store_reg(s
, 14, tmp2
);
7169 if (insn
& (1 << 11)) {
7170 /* Second half of bl. */
7171 offset
= ((insn
& 0x7ff) << 1) | 1;
7172 tmp
= load_reg(s
, 14);
7173 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7176 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7177 store_reg(s
, 14, tmp2
);
7181 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7182 /* Instruction spans a page boundary. Implement it as two
7183 16-bit instructions in case the second half causes an
7185 offset
= ((int32_t)insn
<< 21) >> 9;
7186 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
7187 gen_movl_reg_T0(s
, 14);
7190 /* Fall through to 32-bit decode. */
7193 insn
= lduw_code(s
->pc
);
7195 insn
|= (uint32_t)insn_hw1
<< 16;
7197 if ((insn
& 0xf800e800) != 0xf000e800) {
7201 rn
= (insn
>> 16) & 0xf;
7202 rs
= (insn
>> 12) & 0xf;
7203 rd
= (insn
>> 8) & 0xf;
7205 switch ((insn
>> 25) & 0xf) {
7206 case 0: case 1: case 2: case 3:
7207 /* 16-bit instructions. Should never happen. */
7210 if (insn
& (1 << 22)) {
7211 /* Other load/store, table branch. */
7212 if (insn
& 0x01200000) {
7213 /* Load/store doubleword. */
7216 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7218 addr
= load_reg(s
, rn
);
7220 offset
= (insn
& 0xff) * 4;
7221 if ((insn
& (1 << 23)) == 0)
7223 if (insn
& (1 << 24)) {
7224 tcg_gen_addi_i32(addr
, addr
, offset
);
7227 if (insn
& (1 << 20)) {
7229 tmp
= gen_ld32(addr
, IS_USER(s
));
7230 store_reg(s
, rs
, tmp
);
7231 tcg_gen_addi_i32(addr
, addr
, 4);
7232 tmp
= gen_ld32(addr
, IS_USER(s
));
7233 store_reg(s
, rd
, tmp
);
7236 tmp
= load_reg(s
, rs
);
7237 gen_st32(tmp
, addr
, IS_USER(s
));
7238 tcg_gen_addi_i32(addr
, addr
, 4);
7239 tmp
= load_reg(s
, rd
);
7240 gen_st32(tmp
, addr
, IS_USER(s
));
7242 if (insn
& (1 << 21)) {
7243 /* Base writeback. */
7246 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7247 store_reg(s
, rn
, addr
);
7251 } else if ((insn
& (1 << 23)) == 0) {
7252 /* Load/store exclusive word. */
7253 gen_movl_T1_reg(s
, rn
);
7255 if (insn
& (1 << 20)) {
7256 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
7257 tmp
= gen_ld32(addr
, IS_USER(s
));
7258 store_reg(s
, rd
, tmp
);
7260 int label
= gen_new_label();
7261 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7262 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
7264 tmp
= load_reg(s
, rs
);
7265 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7266 gen_set_label(label
);
7267 gen_movl_reg_T0(s
, rd
);
7269 } else if ((insn
& (1 << 6)) == 0) {
7273 tcg_gen_movi_i32(addr
, s
->pc
);
7275 addr
= load_reg(s
, rn
);
7277 tmp
= load_reg(s
, rm
);
7278 tcg_gen_add_i32(addr
, addr
, tmp
);
7279 if (insn
& (1 << 4)) {
7281 tcg_gen_add_i32(addr
, addr
, tmp
);
7283 tmp
= gen_ld16u(addr
, IS_USER(s
));
7286 tmp
= gen_ld8u(addr
, IS_USER(s
));
7289 tcg_gen_shli_i32(tmp
, tmp
, 1);
7290 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7291 store_reg(s
, 15, tmp
);
7293 /* Load/store exclusive byte/halfword/doubleword. */
7294 /* ??? These are not really atomic. However we know
7295 we never have multiple CPUs running in parallel,
7296 so it is good enough. */
7297 op
= (insn
>> 4) & 0x3;
7298 /* Must use a global reg for the address because we have
7299 a conditional branch in the store instruction. */
7300 gen_movl_T1_reg(s
, rn
);
7302 if (insn
& (1 << 20)) {
7303 gen_helper_mark_exclusive(cpu_env
, addr
);
7306 tmp
= gen_ld8u(addr
, IS_USER(s
));
7309 tmp
= gen_ld16u(addr
, IS_USER(s
));
7312 tmp
= gen_ld32(addr
, IS_USER(s
));
7313 tcg_gen_addi_i32(addr
, addr
, 4);
7314 tmp2
= gen_ld32(addr
, IS_USER(s
));
7315 store_reg(s
, rd
, tmp2
);
7320 store_reg(s
, rs
, tmp
);
7322 int label
= gen_new_label();
7323 /* Must use a global that is not killed by the branch. */
7324 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7325 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7326 tmp
= load_reg(s
, rs
);
7329 gen_st8(tmp
, addr
, IS_USER(s
));
7332 gen_st16(tmp
, addr
, IS_USER(s
));
7335 gen_st32(tmp
, addr
, IS_USER(s
));
7336 tcg_gen_addi_i32(addr
, addr
, 4);
7337 tmp
= load_reg(s
, rd
);
7338 gen_st32(tmp
, addr
, IS_USER(s
));
7343 gen_set_label(label
);
7344 gen_movl_reg_T0(s
, rm
);
7348 /* Load/store multiple, RFE, SRS. */
7349 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7350 /* Not available in user mode. */
7353 if (insn
& (1 << 20)) {
7355 addr
= load_reg(s
, rn
);
7356 if ((insn
& (1 << 24)) == 0)
7357 tcg_gen_addi_i32(addr
, addr
, -8);
7358 /* Load PC into tmp and CPSR into tmp2. */
7359 tmp
= gen_ld32(addr
, 0);
7360 tcg_gen_addi_i32(addr
, addr
, 4);
7361 tmp2
= gen_ld32(addr
, 0);
7362 if (insn
& (1 << 21)) {
7363 /* Base writeback. */
7364 if (insn
& (1 << 24)) {
7365 tcg_gen_addi_i32(addr
, addr
, 4);
7367 tcg_gen_addi_i32(addr
, addr
, -4);
7369 store_reg(s
, rn
, addr
);
7373 gen_rfe(s
, tmp
, tmp2
);
7377 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7378 addr
= load_reg(s
, 13);
7381 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7383 if ((insn
& (1 << 24)) == 0) {
7384 tcg_gen_addi_i32(addr
, addr
, -8);
7386 tmp
= load_reg(s
, 14);
7387 gen_st32(tmp
, addr
, 0);
7388 tcg_gen_addi_i32(addr
, addr
, 4);
7390 gen_helper_cpsr_read(tmp
);
7391 gen_st32(tmp
, addr
, 0);
7392 if (insn
& (1 << 21)) {
7393 if ((insn
& (1 << 24)) == 0) {
7394 tcg_gen_addi_i32(addr
, addr
, -4);
7396 tcg_gen_addi_i32(addr
, addr
, 4);
7398 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7399 store_reg(s
, 13, addr
);
7401 gen_helper_set_r13_banked(cpu_env
,
7402 tcg_const_i32(op
), addr
);
7410 /* Load/store multiple. */
7411 addr
= load_reg(s
, rn
);
7413 for (i
= 0; i
< 16; i
++) {
7414 if (insn
& (1 << i
))
7417 if (insn
& (1 << 24)) {
7418 tcg_gen_addi_i32(addr
, addr
, -offset
);
7421 for (i
= 0; i
< 16; i
++) {
7422 if ((insn
& (1 << i
)) == 0)
7424 if (insn
& (1 << 20)) {
7426 tmp
= gen_ld32(addr
, IS_USER(s
));
7430 store_reg(s
, i
, tmp
);
7434 tmp
= load_reg(s
, i
);
7435 gen_st32(tmp
, addr
, IS_USER(s
));
7437 tcg_gen_addi_i32(addr
, addr
, 4);
7439 if (insn
& (1 << 21)) {
7440 /* Base register writeback. */
7441 if (insn
& (1 << 24)) {
7442 tcg_gen_addi_i32(addr
, addr
, -offset
);
7444 /* Fault if writeback register is in register list. */
7445 if (insn
& (1 << rn
))
7447 store_reg(s
, rn
, addr
);
7454 case 5: /* Data processing register constant shift. */
7456 gen_op_movl_T0_im(0);
7458 gen_movl_T0_reg(s
, rn
);
7459 gen_movl_T1_reg(s
, rm
);
7460 op
= (insn
>> 21) & 0xf;
7461 shiftop
= (insn
>> 4) & 3;
7462 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7463 conds
= (insn
& (1 << 20)) != 0;
7464 logic_cc
= (conds
&& thumb2_logic_op(op
));
7465 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7466 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7469 gen_movl_reg_T0(s
, rd
);
7471 case 13: /* Misc data processing. */
7472 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7473 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7476 case 0: /* Register controlled shift. */
7477 tmp
= load_reg(s
, rn
);
7478 tmp2
= load_reg(s
, rm
);
7479 if ((insn
& 0x70) != 0)
7481 op
= (insn
>> 21) & 3;
7482 logic_cc
= (insn
& (1 << 20)) != 0;
7483 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7486 store_reg_bx(env
, s
, rd
, tmp
);
7488 case 1: /* Sign/zero extend. */
7489 tmp
= load_reg(s
, rm
);
7490 shift
= (insn
>> 4) & 3;
7491 /* ??? In many cases it's not neccessary to do a
7492 rotate, a shift is sufficient. */
7494 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7495 op
= (insn
>> 20) & 7;
7497 case 0: gen_sxth(tmp
); break;
7498 case 1: gen_uxth(tmp
); break;
7499 case 2: gen_sxtb16(tmp
); break;
7500 case 3: gen_uxtb16(tmp
); break;
7501 case 4: gen_sxtb(tmp
); break;
7502 case 5: gen_uxtb(tmp
); break;
7503 default: goto illegal_op
;
7506 tmp2
= load_reg(s
, rn
);
7507 if ((op
>> 1) == 1) {
7508 gen_add16(tmp
, tmp2
);
7510 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7514 store_reg(s
, rd
, tmp
);
7516 case 2: /* SIMD add/subtract. */
7517 op
= (insn
>> 20) & 7;
7518 shift
= (insn
>> 4) & 7;
7519 if ((op
& 3) == 3 || (shift
& 3) == 3)
7521 tmp
= load_reg(s
, rn
);
7522 tmp2
= load_reg(s
, rm
);
7523 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7525 store_reg(s
, rd
, tmp
);
7527 case 3: /* Other data processing. */
7528 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7530 /* Saturating add/subtract. */
7531 tmp
= load_reg(s
, rn
);
7532 tmp2
= load_reg(s
, rm
);
7534 gen_helper_double_saturate(tmp
, tmp
);
7536 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7538 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7541 tmp
= load_reg(s
, rn
);
7543 case 0x0a: /* rbit */
7544 gen_helper_rbit(tmp
, tmp
);
7546 case 0x08: /* rev */
7547 tcg_gen_bswap32_i32(tmp
, tmp
);
7549 case 0x09: /* rev16 */
7552 case 0x0b: /* revsh */
7555 case 0x10: /* sel */
7556 tmp2
= load_reg(s
, rm
);
7558 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7559 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7563 case 0x18: /* clz */
7564 gen_helper_clz(tmp
, tmp
);
7570 store_reg(s
, rd
, tmp
);
7572 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7573 op
= (insn
>> 4) & 0xf;
7574 tmp
= load_reg(s
, rn
);
7575 tmp2
= load_reg(s
, rm
);
7576 switch ((insn
>> 20) & 7) {
7577 case 0: /* 32 x 32 -> 32 */
7578 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7581 tmp2
= load_reg(s
, rs
);
7583 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7585 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7589 case 1: /* 16 x 16 -> 32 */
7590 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7593 tmp2
= load_reg(s
, rs
);
7594 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7598 case 2: /* Dual multiply add. */
7599 case 4: /* Dual multiply subtract. */
7601 gen_swap_half(tmp2
);
7602 gen_smul_dual(tmp
, tmp2
);
7603 /* This addition cannot overflow. */
7604 if (insn
& (1 << 22)) {
7605 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7607 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7612 tmp2
= load_reg(s
, rs
);
7613 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7617 case 3: /* 32 * 16 -> 32msb */
7619 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7622 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7623 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7625 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7628 tmp2
= load_reg(s
, rs
);
7629 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7633 case 5: case 6: /* 32 * 32 -> 32msb */
7634 gen_imull(tmp
, tmp2
);
7635 if (insn
& (1 << 5)) {
7636 gen_roundqd(tmp
, tmp2
);
7643 tmp2
= load_reg(s
, rs
);
7644 if (insn
& (1 << 21)) {
7645 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7647 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7652 case 7: /* Unsigned sum of absolute differences. */
7653 gen_helper_usad8(tmp
, tmp
, tmp2
);
7656 tmp2
= load_reg(s
, rs
);
7657 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7662 store_reg(s
, rd
, tmp
);
7664 case 6: case 7: /* 64-bit multiply, Divide. */
7665 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7666 tmp
= load_reg(s
, rn
);
7667 tmp2
= load_reg(s
, rm
);
7668 if ((op
& 0x50) == 0x10) {
7670 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7673 gen_helper_udiv(tmp
, tmp
, tmp2
);
7675 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7677 store_reg(s
, rd
, tmp
);
7678 } else if ((op
& 0xe) == 0xc) {
7679 /* Dual multiply accumulate long. */
7681 gen_swap_half(tmp2
);
7682 gen_smul_dual(tmp
, tmp2
);
7684 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7686 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7690 tmp64
= tcg_temp_new_i64();
7691 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7693 gen_addq(s
, tmp64
, rs
, rd
);
7694 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7697 /* Unsigned 64-bit multiply */
7698 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7702 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7704 tmp64
= tcg_temp_new_i64();
7705 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7708 /* Signed 64-bit multiply */
7709 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7714 gen_addq_lo(s
, tmp64
, rs
);
7715 gen_addq_lo(s
, tmp64
, rd
);
7716 } else if (op
& 0x40) {
7717 /* 64-bit accumulate. */
7718 gen_addq(s
, tmp64
, rs
, rd
);
7720 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7725 case 6: case 7: case 14: case 15:
7727 if (((insn
>> 24) & 3) == 3) {
7728 /* Translate into the equivalent ARM encoding. */
7729 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7730 if (disas_neon_data_insn(env
, s
, insn
))
7733 if (insn
& (1 << 28))
7735 if (disas_coproc_insn (env
, s
, insn
))
7739 case 8: case 9: case 10: case 11:
7740 if (insn
& (1 << 15)) {
7741 /* Branches, misc control. */
7742 if (insn
& 0x5000) {
7743 /* Unconditional branch. */
7744 /* signextend(hw1[10:0]) -> offset[:12]. */
7745 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7746 /* hw1[10:0] -> offset[11:1]. */
7747 offset
|= (insn
& 0x7ff) << 1;
7748 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7749 offset[24:22] already have the same value because of the
7750 sign extension above. */
7751 offset
^= ((~insn
) & (1 << 13)) << 10;
7752 offset
^= ((~insn
) & (1 << 11)) << 11;
7754 if (insn
& (1 << 14)) {
7755 /* Branch and link. */
7756 gen_op_movl_T1_im(s
->pc
| 1);
7757 gen_movl_reg_T1(s
, 14);
7761 if (insn
& (1 << 12)) {
7766 offset
&= ~(uint32_t)2;
7767 gen_bx_im(s
, offset
);
7769 } else if (((insn
>> 23) & 7) == 7) {
7771 if (insn
& (1 << 13))
7774 if (insn
& (1 << 26)) {
7775 /* Secure monitor call (v6Z) */
7776 goto illegal_op
; /* not implemented. */
7778 op
= (insn
>> 20) & 7;
7780 case 0: /* msr cpsr. */
7782 tmp
= load_reg(s
, rn
);
7783 addr
= tcg_const_i32(insn
& 0xff);
7784 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7789 case 1: /* msr spsr. */
7792 tmp
= load_reg(s
, rn
);
7794 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7798 case 2: /* cps, nop-hint. */
7799 if (((insn
>> 8) & 7) == 0) {
7800 gen_nop_hint(s
, insn
& 0xff);
7802 /* Implemented as NOP in user mode. */
7807 if (insn
& (1 << 10)) {
7808 if (insn
& (1 << 7))
7810 if (insn
& (1 << 6))
7812 if (insn
& (1 << 5))
7814 if (insn
& (1 << 9))
7815 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7817 if (insn
& (1 << 8)) {
7819 imm
|= (insn
& 0x1f);
7822 gen_set_psr_im(s
, offset
, 0, imm
);
7825 case 3: /* Special control operations. */
7826 op
= (insn
>> 4) & 0xf;
7829 gen_helper_clrex(cpu_env
);
7834 /* These execute as NOPs. */
7842 /* Trivial implementation equivalent to bx. */
7843 tmp
= load_reg(s
, rn
);
7846 case 5: /* Exception return. */
7847 /* Unpredictable in user mode. */
7849 case 6: /* mrs cpsr. */
7852 addr
= tcg_const_i32(insn
& 0xff);
7853 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7855 gen_helper_cpsr_read(tmp
);
7857 store_reg(s
, rd
, tmp
);
7859 case 7: /* mrs spsr. */
7860 /* Not accessible in user mode. */
7861 if (IS_USER(s
) || IS_M(env
))
7863 tmp
= load_cpu_field(spsr
);
7864 store_reg(s
, rd
, tmp
);
7869 /* Conditional branch. */
7870 op
= (insn
>> 22) & 0xf;
7871 /* Generate a conditional jump to next instruction. */
7872 s
->condlabel
= gen_new_label();
7873 gen_test_cc(op
^ 1, s
->condlabel
);
7876 /* offset[11:1] = insn[10:0] */
7877 offset
= (insn
& 0x7ff) << 1;
7878 /* offset[17:12] = insn[21:16]. */
7879 offset
|= (insn
& 0x003f0000) >> 4;
7880 /* offset[31:20] = insn[26]. */
7881 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7882 /* offset[18] = insn[13]. */
7883 offset
|= (insn
& (1 << 13)) << 5;
7884 /* offset[19] = insn[11]. */
7885 offset
|= (insn
& (1 << 11)) << 8;
7887 /* jump to the offset */
7888 gen_jmp(s
, s
->pc
+ offset
);
7891 /* Data processing immediate. */
7892 if (insn
& (1 << 25)) {
7893 if (insn
& (1 << 24)) {
7894 if (insn
& (1 << 20))
7896 /* Bitfield/Saturate. */
7897 op
= (insn
>> 21) & 7;
7899 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7902 tcg_gen_movi_i32(tmp
, 0);
7904 tmp
= load_reg(s
, rn
);
7907 case 2: /* Signed bitfield extract. */
7909 if (shift
+ imm
> 32)
7912 gen_sbfx(tmp
, shift
, imm
);
7914 case 6: /* Unsigned bitfield extract. */
7916 if (shift
+ imm
> 32)
7919 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7921 case 3: /* Bitfield insert/clear. */
7924 imm
= imm
+ 1 - shift
;
7926 tmp2
= load_reg(s
, rd
);
7927 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7933 default: /* Saturate. */
7936 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7938 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7940 tmp2
= tcg_const_i32(imm
);
7943 if ((op
& 1) && shift
== 0)
7944 gen_helper_usat16(tmp
, tmp
, tmp2
);
7946 gen_helper_usat(tmp
, tmp
, tmp2
);
7949 if ((op
& 1) && shift
== 0)
7950 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7952 gen_helper_ssat(tmp
, tmp
, tmp2
);
7956 store_reg(s
, rd
, tmp
);
7958 imm
= ((insn
& 0x04000000) >> 15)
7959 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7960 if (insn
& (1 << 22)) {
7961 /* 16-bit immediate. */
7962 imm
|= (insn
>> 4) & 0xf000;
7963 if (insn
& (1 << 23)) {
7965 tmp
= load_reg(s
, rd
);
7966 tcg_gen_ext16u_i32(tmp
, tmp
);
7967 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7971 tcg_gen_movi_i32(tmp
, imm
);
7974 /* Add/sub 12-bit immediate. */
7976 offset
= s
->pc
& ~(uint32_t)3;
7977 if (insn
& (1 << 23))
7982 tcg_gen_movi_i32(tmp
, offset
);
7984 tmp
= load_reg(s
, rn
);
7985 if (insn
& (1 << 23))
7986 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7988 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7991 store_reg(s
, rd
, tmp
);
7994 int shifter_out
= 0;
7995 /* modified 12-bit immediate. */
7996 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7997 imm
= (insn
& 0xff);
8000 /* Nothing to do. */
8002 case 1: /* 00XY00XY */
8005 case 2: /* XY00XY00 */
8009 case 3: /* XYXYXYXY */
8013 default: /* Rotated constant. */
8014 shift
= (shift
<< 1) | (imm
>> 7);
8016 imm
= imm
<< (32 - shift
);
8020 gen_op_movl_T1_im(imm
);
8021 rn
= (insn
>> 16) & 0xf;
8023 gen_op_movl_T0_im(0);
8025 gen_movl_T0_reg(s
, rn
);
8026 op
= (insn
>> 21) & 0xf;
8027 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8030 rd
= (insn
>> 8) & 0xf;
8032 gen_movl_reg_T0(s
, rd
);
8037 case 12: /* Load/store single data item. */
8042 if ((insn
& 0x01100000) == 0x01000000) {
8043 if (disas_neon_ls_insn(env
, s
, insn
))
8051 /* s->pc has already been incremented by 4. */
8052 imm
= s
->pc
& 0xfffffffc;
8053 if (insn
& (1 << 23))
8054 imm
+= insn
& 0xfff;
8056 imm
-= insn
& 0xfff;
8057 tcg_gen_movi_i32(addr
, imm
);
8059 addr
= load_reg(s
, rn
);
8060 if (insn
& (1 << 23)) {
8061 /* Positive offset. */
8063 tcg_gen_addi_i32(addr
, addr
, imm
);
8065 op
= (insn
>> 8) & 7;
8068 case 0: case 8: /* Shifted Register. */
8069 shift
= (insn
>> 4) & 0xf;
8072 tmp
= load_reg(s
, rm
);
8074 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8075 tcg_gen_add_i32(addr
, addr
, tmp
);
8078 case 4: /* Negative offset. */
8079 tcg_gen_addi_i32(addr
, addr
, -imm
);
8081 case 6: /* User privilege. */
8082 tcg_gen_addi_i32(addr
, addr
, imm
);
8085 case 1: /* Post-decrement. */
8088 case 3: /* Post-increment. */
8092 case 5: /* Pre-decrement. */
8095 case 7: /* Pre-increment. */
8096 tcg_gen_addi_i32(addr
, addr
, imm
);
8104 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8105 if (insn
& (1 << 20)) {
8107 if (rs
== 15 && op
!= 2) {
8110 /* Memory hint. Implemented as NOP. */
8113 case 0: tmp
= gen_ld8u(addr
, user
); break;
8114 case 4: tmp
= gen_ld8s(addr
, user
); break;
8115 case 1: tmp
= gen_ld16u(addr
, user
); break;
8116 case 5: tmp
= gen_ld16s(addr
, user
); break;
8117 case 2: tmp
= gen_ld32(addr
, user
); break;
8118 default: goto illegal_op
;
8123 store_reg(s
, rs
, tmp
);
8130 tmp
= load_reg(s
, rs
);
8132 case 0: gen_st8(tmp
, addr
, user
); break;
8133 case 1: gen_st16(tmp
, addr
, user
); break;
8134 case 2: gen_st32(tmp
, addr
, user
); break;
8135 default: goto illegal_op
;
8139 tcg_gen_addi_i32(addr
, addr
, imm
);
8141 store_reg(s
, rn
, addr
);
8155 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8157 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8164 if (s
->condexec_mask
) {
8165 cond
= s
->condexec_cond
;
8166 s
->condlabel
= gen_new_label();
8167 gen_test_cc(cond
^ 1, s
->condlabel
);
8171 insn
= lduw_code(s
->pc
);
8174 switch (insn
>> 12) {
8177 op
= (insn
>> 11) & 3;
8180 rn
= (insn
>> 3) & 7;
8181 gen_movl_T0_reg(s
, rn
);
8182 if (insn
& (1 << 10)) {
8184 gen_op_movl_T1_im((insn
>> 6) & 7);
8187 rm
= (insn
>> 6) & 7;
8188 gen_movl_T1_reg(s
, rm
);
8190 if (insn
& (1 << 9)) {
8191 if (s
->condexec_mask
)
8192 gen_op_subl_T0_T1();
8194 gen_op_subl_T0_T1_cc();
8196 if (s
->condexec_mask
)
8197 gen_op_addl_T0_T1();
8199 gen_op_addl_T0_T1_cc();
8201 gen_movl_reg_T0(s
, rd
);
8203 /* shift immediate */
8204 rm
= (insn
>> 3) & 7;
8205 shift
= (insn
>> 6) & 0x1f;
8206 tmp
= load_reg(s
, rm
);
8207 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8208 if (!s
->condexec_mask
)
8210 store_reg(s
, rd
, tmp
);
8214 /* arithmetic large immediate */
8215 op
= (insn
>> 11) & 3;
8216 rd
= (insn
>> 8) & 0x7;
8218 gen_op_movl_T0_im(insn
& 0xff);
8220 gen_movl_T0_reg(s
, rd
);
8221 gen_op_movl_T1_im(insn
& 0xff);
8225 if (!s
->condexec_mask
)
8226 gen_op_logic_T0_cc();
8229 gen_op_subl_T0_T1_cc();
8232 if (s
->condexec_mask
)
8233 gen_op_addl_T0_T1();
8235 gen_op_addl_T0_T1_cc();
8238 if (s
->condexec_mask
)
8239 gen_op_subl_T0_T1();
8241 gen_op_subl_T0_T1_cc();
8245 gen_movl_reg_T0(s
, rd
);
8248 if (insn
& (1 << 11)) {
8249 rd
= (insn
>> 8) & 7;
8250 /* load pc-relative. Bit 1 of PC is ignored. */
8251 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8252 val
&= ~(uint32_t)2;
8254 tcg_gen_movi_i32(addr
, val
);
8255 tmp
= gen_ld32(addr
, IS_USER(s
));
8257 store_reg(s
, rd
, tmp
);
8260 if (insn
& (1 << 10)) {
8261 /* data processing extended or blx */
8262 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8263 rm
= (insn
>> 3) & 0xf;
8264 op
= (insn
>> 8) & 3;
8267 gen_movl_T0_reg(s
, rd
);
8268 gen_movl_T1_reg(s
, rm
);
8269 gen_op_addl_T0_T1();
8270 gen_movl_reg_T0(s
, rd
);
8273 gen_movl_T0_reg(s
, rd
);
8274 gen_movl_T1_reg(s
, rm
);
8275 gen_op_subl_T0_T1_cc();
8277 case 2: /* mov/cpy */
8278 gen_movl_T0_reg(s
, rm
);
8279 gen_movl_reg_T0(s
, rd
);
8281 case 3:/* branch [and link] exchange thumb register */
8282 tmp
= load_reg(s
, rm
);
8283 if (insn
& (1 << 7)) {
8284 val
= (uint32_t)s
->pc
| 1;
8286 tcg_gen_movi_i32(tmp2
, val
);
8287 store_reg(s
, 14, tmp2
);
8295 /* data processing register */
8297 rm
= (insn
>> 3) & 7;
8298 op
= (insn
>> 6) & 0xf;
8299 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8300 /* the shift/rotate ops want the operands backwards */
8309 if (op
== 9) /* neg */
8310 gen_op_movl_T0_im(0);
8311 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8312 gen_movl_T0_reg(s
, rd
);
8314 gen_movl_T1_reg(s
, rm
);
8317 gen_op_andl_T0_T1();
8318 if (!s
->condexec_mask
)
8319 gen_op_logic_T0_cc();
8322 gen_op_xorl_T0_T1();
8323 if (!s
->condexec_mask
)
8324 gen_op_logic_T0_cc();
8327 if (s
->condexec_mask
) {
8328 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8330 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8331 gen_op_logic_T1_cc();
8335 if (s
->condexec_mask
) {
8336 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8338 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8339 gen_op_logic_T1_cc();
8343 if (s
->condexec_mask
) {
8344 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8346 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8347 gen_op_logic_T1_cc();
8351 if (s
->condexec_mask
)
8354 gen_op_adcl_T0_T1_cc();
8357 if (s
->condexec_mask
)
8360 gen_op_sbcl_T0_T1_cc();
8363 if (s
->condexec_mask
) {
8364 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8366 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8367 gen_op_logic_T1_cc();
8371 gen_op_andl_T0_T1();
8372 gen_op_logic_T0_cc();
8376 if (s
->condexec_mask
)
8377 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8379 gen_op_subl_T0_T1_cc();
8382 gen_op_subl_T0_T1_cc();
8386 gen_op_addl_T0_T1_cc();
8391 if (!s
->condexec_mask
)
8392 gen_op_logic_T0_cc();
8395 gen_op_mull_T0_T1();
8396 if (!s
->condexec_mask
)
8397 gen_op_logic_T0_cc();
8400 gen_op_bicl_T0_T1();
8401 if (!s
->condexec_mask
)
8402 gen_op_logic_T0_cc();
8406 if (!s
->condexec_mask
)
8407 gen_op_logic_T1_cc();
8414 gen_movl_reg_T1(s
, rm
);
8416 gen_movl_reg_T0(s
, rd
);
8421 /* load/store register offset. */
8423 rn
= (insn
>> 3) & 7;
8424 rm
= (insn
>> 6) & 7;
8425 op
= (insn
>> 9) & 7;
8426 addr
= load_reg(s
, rn
);
8427 tmp
= load_reg(s
, rm
);
8428 tcg_gen_add_i32(addr
, addr
, tmp
);
8431 if (op
< 3) /* store */
8432 tmp
= load_reg(s
, rd
);
8436 gen_st32(tmp
, addr
, IS_USER(s
));
8439 gen_st16(tmp
, addr
, IS_USER(s
));
8442 gen_st8(tmp
, addr
, IS_USER(s
));
8445 tmp
= gen_ld8s(addr
, IS_USER(s
));
8448 tmp
= gen_ld32(addr
, IS_USER(s
));
8451 tmp
= gen_ld16u(addr
, IS_USER(s
));
8454 tmp
= gen_ld8u(addr
, IS_USER(s
));
8457 tmp
= gen_ld16s(addr
, IS_USER(s
));
8460 if (op
>= 3) /* load */
8461 store_reg(s
, rd
, tmp
);
8466 /* load/store word immediate offset */
8468 rn
= (insn
>> 3) & 7;
8469 addr
= load_reg(s
, rn
);
8470 val
= (insn
>> 4) & 0x7c;
8471 tcg_gen_addi_i32(addr
, addr
, val
);
8473 if (insn
& (1 << 11)) {
8475 tmp
= gen_ld32(addr
, IS_USER(s
));
8476 store_reg(s
, rd
, tmp
);
8479 tmp
= load_reg(s
, rd
);
8480 gen_st32(tmp
, addr
, IS_USER(s
));
8486 /* load/store byte immediate offset */
8488 rn
= (insn
>> 3) & 7;
8489 addr
= load_reg(s
, rn
);
8490 val
= (insn
>> 6) & 0x1f;
8491 tcg_gen_addi_i32(addr
, addr
, val
);
8493 if (insn
& (1 << 11)) {
8495 tmp
= gen_ld8u(addr
, IS_USER(s
));
8496 store_reg(s
, rd
, tmp
);
8499 tmp
= load_reg(s
, rd
);
8500 gen_st8(tmp
, addr
, IS_USER(s
));
8506 /* load/store halfword immediate offset */
8508 rn
= (insn
>> 3) & 7;
8509 addr
= load_reg(s
, rn
);
8510 val
= (insn
>> 5) & 0x3e;
8511 tcg_gen_addi_i32(addr
, addr
, val
);
8513 if (insn
& (1 << 11)) {
8515 tmp
= gen_ld16u(addr
, IS_USER(s
));
8516 store_reg(s
, rd
, tmp
);
8519 tmp
= load_reg(s
, rd
);
8520 gen_st16(tmp
, addr
, IS_USER(s
));
8526 /* load/store from stack */
8527 rd
= (insn
>> 8) & 7;
8528 addr
= load_reg(s
, 13);
8529 val
= (insn
& 0xff) * 4;
8530 tcg_gen_addi_i32(addr
, addr
, val
);
8532 if (insn
& (1 << 11)) {
8534 tmp
= gen_ld32(addr
, IS_USER(s
));
8535 store_reg(s
, rd
, tmp
);
8538 tmp
= load_reg(s
, rd
);
8539 gen_st32(tmp
, addr
, IS_USER(s
));
8545 /* add to high reg */
8546 rd
= (insn
>> 8) & 7;
8547 if (insn
& (1 << 11)) {
8549 tmp
= load_reg(s
, 13);
8551 /* PC. bit 1 is ignored. */
8553 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8555 val
= (insn
& 0xff) * 4;
8556 tcg_gen_addi_i32(tmp
, tmp
, val
);
8557 store_reg(s
, rd
, tmp
);
8562 op
= (insn
>> 8) & 0xf;
8565 /* adjust stack pointer */
8566 tmp
= load_reg(s
, 13);
8567 val
= (insn
& 0x7f) * 4;
8568 if (insn
& (1 << 7))
8569 val
= -(int32_t)val
;
8570 tcg_gen_addi_i32(tmp
, tmp
, val
);
8571 store_reg(s
, 13, tmp
);
8574 case 2: /* sign/zero extend. */
8577 rm
= (insn
>> 3) & 7;
8578 tmp
= load_reg(s
, rm
);
8579 switch ((insn
>> 6) & 3) {
8580 case 0: gen_sxth(tmp
); break;
8581 case 1: gen_sxtb(tmp
); break;
8582 case 2: gen_uxth(tmp
); break;
8583 case 3: gen_uxtb(tmp
); break;
8585 store_reg(s
, rd
, tmp
);
8587 case 4: case 5: case 0xc: case 0xd:
8589 addr
= load_reg(s
, 13);
8590 if (insn
& (1 << 8))
8594 for (i
= 0; i
< 8; i
++) {
8595 if (insn
& (1 << i
))
8598 if ((insn
& (1 << 11)) == 0) {
8599 tcg_gen_addi_i32(addr
, addr
, -offset
);
8601 for (i
= 0; i
< 8; i
++) {
8602 if (insn
& (1 << i
)) {
8603 if (insn
& (1 << 11)) {
8605 tmp
= gen_ld32(addr
, IS_USER(s
));
8606 store_reg(s
, i
, tmp
);
8609 tmp
= load_reg(s
, i
);
8610 gen_st32(tmp
, addr
, IS_USER(s
));
8612 /* advance to the next address. */
8613 tcg_gen_addi_i32(addr
, addr
, 4);
8617 if (insn
& (1 << 8)) {
8618 if (insn
& (1 << 11)) {
8620 tmp
= gen_ld32(addr
, IS_USER(s
));
8621 /* don't set the pc until the rest of the instruction
8625 tmp
= load_reg(s
, 14);
8626 gen_st32(tmp
, addr
, IS_USER(s
));
8628 tcg_gen_addi_i32(addr
, addr
, 4);
8630 if ((insn
& (1 << 11)) == 0) {
8631 tcg_gen_addi_i32(addr
, addr
, -offset
);
8633 /* write back the new stack pointer */
8634 store_reg(s
, 13, addr
);
8635 /* set the new PC value */
8636 if ((insn
& 0x0900) == 0x0900)
8640 case 1: case 3: case 9: case 11: /* czb */
8642 tmp
= load_reg(s
, rm
);
8643 s
->condlabel
= gen_new_label();
8645 if (insn
& (1 << 11))
8646 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8648 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8650 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8651 val
= (uint32_t)s
->pc
+ 2;
8656 case 15: /* IT, nop-hint. */
8657 if ((insn
& 0xf) == 0) {
8658 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8662 s
->condexec_cond
= (insn
>> 4) & 0xe;
8663 s
->condexec_mask
= insn
& 0x1f;
8664 /* No actual code generated for this insn, just setup state. */
8667 case 0xe: /* bkpt */
8668 gen_set_condexec(s
);
8669 gen_set_pc_im(s
->pc
- 2);
8670 gen_exception(EXCP_BKPT
);
8671 s
->is_jmp
= DISAS_JUMP
;
8676 rn
= (insn
>> 3) & 0x7;
8678 tmp
= load_reg(s
, rn
);
8679 switch ((insn
>> 6) & 3) {
8680 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8681 case 1: gen_rev16(tmp
); break;
8682 case 3: gen_revsh(tmp
); break;
8683 default: goto illegal_op
;
8685 store_reg(s
, rd
, tmp
);
8693 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8696 addr
= tcg_const_i32(16);
8697 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8701 addr
= tcg_const_i32(17);
8702 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8706 if (insn
& (1 << 4))
8707 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8710 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8720 /* load/store multiple */
8721 rn
= (insn
>> 8) & 0x7;
8722 addr
= load_reg(s
, rn
);
8723 for (i
= 0; i
< 8; i
++) {
8724 if (insn
& (1 << i
)) {
8725 if (insn
& (1 << 11)) {
8727 tmp
= gen_ld32(addr
, IS_USER(s
));
8728 store_reg(s
, i
, tmp
);
8731 tmp
= load_reg(s
, i
);
8732 gen_st32(tmp
, addr
, IS_USER(s
));
8734 /* advance to the next address */
8735 tcg_gen_addi_i32(addr
, addr
, 4);
8738 /* Base register writeback. */
8739 if ((insn
& (1 << rn
)) == 0) {
8740 store_reg(s
, rn
, addr
);
8747 /* conditional branch or swi */
8748 cond
= (insn
>> 8) & 0xf;
8754 gen_set_condexec(s
);
8755 gen_set_pc_im(s
->pc
);
8756 s
->is_jmp
= DISAS_SWI
;
8759 /* generate a conditional jump to next instruction */
8760 s
->condlabel
= gen_new_label();
8761 gen_test_cc(cond
^ 1, s
->condlabel
);
8764 /* jump to the offset */
8765 val
= (uint32_t)s
->pc
+ 2;
8766 offset
= ((int32_t)insn
<< 24) >> 24;
8772 if (insn
& (1 << 11)) {
8773 if (disas_thumb2_insn(env
, s
, insn
))
8777 /* unconditional branch */
8778 val
= (uint32_t)s
->pc
;
8779 offset
= ((int32_t)insn
<< 21) >> 21;
8780 val
+= (offset
<< 1) + 2;
8785 if (disas_thumb2_insn(env
, s
, insn
))
8791 gen_set_condexec(s
);
8792 gen_set_pc_im(s
->pc
- 4);
8793 gen_exception(EXCP_UDEF
);
8794 s
->is_jmp
= DISAS_JUMP
;
8798 gen_set_condexec(s
);
8799 gen_set_pc_im(s
->pc
- 2);
8800 gen_exception(EXCP_UDEF
);
8801 s
->is_jmp
= DISAS_JUMP
;
8804 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8805 basic block 'tb'. If search_pc is TRUE, also generate PC
8806 information for each intermediate instruction. */
8807 static inline void gen_intermediate_code_internal(CPUState
*env
,
8808 TranslationBlock
*tb
,
8811 DisasContext dc1
, *dc
= &dc1
;
8813 uint16_t *gen_opc_end
;
8815 target_ulong pc_start
;
8816 uint32_t next_page_start
;
8820 /* generate intermediate code */
8827 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8829 dc
->is_jmp
= DISAS_NEXT
;
8831 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8833 dc
->thumb
= env
->thumb
;
8834 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8835 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8836 #if !defined(CONFIG_USER_ONLY)
8838 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8840 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8843 cpu_F0s
= tcg_temp_new_i32();
8844 cpu_F1s
= tcg_temp_new_i32();
8845 cpu_F0d
= tcg_temp_new_i64();
8846 cpu_F1d
= tcg_temp_new_i64();
8849 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8850 cpu_M0
= tcg_temp_new_i64();
8851 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8854 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8856 max_insns
= CF_COUNT_MASK
;
8859 /* Reset the conditional execution bits immediately. This avoids
8860 complications trying to do it at the end of the block. */
8861 if (env
->condexec_bits
)
8863 TCGv tmp
= new_tmp();
8864 tcg_gen_movi_i32(tmp
, 0);
8865 store_cpu_field(tmp
, condexec_bits
);
8868 #ifdef CONFIG_USER_ONLY
8869 /* Intercept jump to the magic kernel page. */
8870 if (dc
->pc
>= 0xffff0000) {
8871 /* We always get here via a jump, so know we are not in a
8872 conditional execution block. */
8873 gen_exception(EXCP_KERNEL_TRAP
);
8874 dc
->is_jmp
= DISAS_UPDATE
;
8878 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8879 /* We always get here via a jump, so know we are not in a
8880 conditional execution block. */
8881 gen_exception(EXCP_EXCEPTION_EXIT
);
8882 dc
->is_jmp
= DISAS_UPDATE
;
8887 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8888 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8889 if (bp
->pc
== dc
->pc
) {
8890 gen_set_condexec(dc
);
8891 gen_set_pc_im(dc
->pc
);
8892 gen_exception(EXCP_DEBUG
);
8893 dc
->is_jmp
= DISAS_JUMP
;
8894 /* Advance PC so that clearing the breakpoint will
8895 invalidate this TB. */
8897 goto done_generating
;
8903 j
= gen_opc_ptr
- gen_opc_buf
;
8907 gen_opc_instr_start
[lj
++] = 0;
8909 gen_opc_pc
[lj
] = dc
->pc
;
8910 gen_opc_instr_start
[lj
] = 1;
8911 gen_opc_icount
[lj
] = num_insns
;
8914 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8918 disas_thumb_insn(env
, dc
);
8919 if (dc
->condexec_mask
) {
8920 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8921 | ((dc
->condexec_mask
>> 4) & 1);
8922 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8923 if (dc
->condexec_mask
== 0) {
8924 dc
->condexec_cond
= 0;
8928 disas_arm_insn(env
, dc
);
8931 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8935 if (dc
->condjmp
&& !dc
->is_jmp
) {
8936 gen_set_label(dc
->condlabel
);
8939 /* Translation stops when a conditional branch is encountered.
8940 * Otherwise the subsequent code could get translated several times.
8941 * Also stop translation when a page boundary is reached. This
8942 * ensures prefetch aborts occur at the right place. */
8944 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8945 !env
->singlestep_enabled
&&
8947 dc
->pc
< next_page_start
&&
8948 num_insns
< max_insns
);
8950 if (tb
->cflags
& CF_LAST_IO
) {
8952 /* FIXME: This can theoretically happen with self-modifying
8954 cpu_abort(env
, "IO on conditional branch instruction");
8959 /* At this stage dc->condjmp will only be set when the skipped
8960 instruction was a conditional branch or trap, and the PC has
8961 already been written. */
8962 if (unlikely(env
->singlestep_enabled
)) {
8963 /* Make sure the pc is updated, and raise a debug exception. */
8965 gen_set_condexec(dc
);
8966 if (dc
->is_jmp
== DISAS_SWI
) {
8967 gen_exception(EXCP_SWI
);
8969 gen_exception(EXCP_DEBUG
);
8971 gen_set_label(dc
->condlabel
);
8973 if (dc
->condjmp
|| !dc
->is_jmp
) {
8974 gen_set_pc_im(dc
->pc
);
8977 gen_set_condexec(dc
);
8978 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8979 gen_exception(EXCP_SWI
);
8981 /* FIXME: Single stepping a WFI insn will not halt
8983 gen_exception(EXCP_DEBUG
);
8986 /* While branches must always occur at the end of an IT block,
8987 there are a few other things that can cause us to terminate
8988 the TB in the middel of an IT block:
8989 - Exception generating instructions (bkpt, swi, undefined).
8991 - Hardware watchpoints.
8992 Hardware breakpoints have already been handled and skip this code.
8994 gen_set_condexec(dc
);
8995 switch(dc
->is_jmp
) {
8997 gen_goto_tb(dc
, 1, dc
->pc
);
9002 /* indicate that the hash table must be used to find the next TB */
9006 /* nothing more to generate */
9012 gen_exception(EXCP_SWI
);
9016 gen_set_label(dc
->condlabel
);
9017 gen_set_condexec(dc
);
9018 gen_goto_tb(dc
, 1, dc
->pc
);
9024 gen_icount_end(tb
, num_insns
);
9025 *gen_opc_ptr
= INDEX_op_end
;
9028 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9029 qemu_log("----------------\n");
9030 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9031 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9036 j
= gen_opc_ptr
- gen_opc_buf
;
9039 gen_opc_instr_start
[lj
++] = 0;
9041 tb
->size
= dc
->pc
- pc_start
;
9042 tb
->icount
= num_insns
;
9046 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9048 gen_intermediate_code_internal(env
, tb
, 0);
9051 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9053 gen_intermediate_code_internal(env
, tb
, 1);
9056 static const char *cpu_mode_names
[16] = {
9057 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9058 "???", "???", "???", "und", "???", "???", "???", "sys"
9061 void cpu_dump_state(CPUState
*env
, FILE *f
,
9062 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9072 /* ??? This assumes float64 and double have the same layout.
9073 Oh well, it's only debug dumps. */
9082 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9084 cpu_fprintf(f
, "\n");
9086 cpu_fprintf(f
, " ");
9088 psr
= cpsr_read(env
);
9089 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9091 psr
& (1 << 31) ? 'N' : '-',
9092 psr
& (1 << 30) ? 'Z' : '-',
9093 psr
& (1 << 29) ? 'C' : '-',
9094 psr
& (1 << 28) ? 'V' : '-',
9095 psr
& CPSR_T
? 'T' : 'A',
9096 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9099 for (i
= 0; i
< 16; i
++) {
9100 d
.d
= env
->vfp
.regs
[i
];
9104 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9105 i
* 2, (int)s0
.i
, s0
.s
,
9106 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9107 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9110 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9114 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9115 unsigned long searched_pc
, int pc_pos
, void *puc
)
9117 env
->regs
[15] = gen_opc_pc
[pc_pos
];