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_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
194 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
195 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
196 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
197 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
199 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
200 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
202 /* Value extensions. */
203 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
204 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
205 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
206 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
208 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
209 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
211 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
214 /* Set NZCV flags from the high 4 bits of var. */
215 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
217 static void gen_exception(int excp
)
219 TCGv tmp
= new_tmp();
220 tcg_gen_movi_i32(tmp
, excp
);
221 gen_helper_exception(tmp
);
225 static void gen_smul_dual(TCGv a
, TCGv b
)
227 TCGv tmp1
= new_tmp();
228 TCGv tmp2
= new_tmp();
229 tcg_gen_ext16s_i32(tmp1
, a
);
230 tcg_gen_ext16s_i32(tmp2
, b
);
231 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
233 tcg_gen_sari_i32(a
, a
, 16);
234 tcg_gen_sari_i32(b
, b
, 16);
235 tcg_gen_mul_i32(b
, b
, a
);
236 tcg_gen_mov_i32(a
, tmp1
);
240 /* Byteswap each halfword. */
241 static void gen_rev16(TCGv var
)
243 TCGv tmp
= new_tmp();
244 tcg_gen_shri_i32(tmp
, var
, 8);
245 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
246 tcg_gen_shli_i32(var
, var
, 8);
247 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
248 tcg_gen_or_i32(var
, var
, tmp
);
252 /* Byteswap low halfword and sign extend. */
253 static void gen_revsh(TCGv var
)
255 TCGv tmp
= new_tmp();
256 tcg_gen_shri_i32(tmp
, var
, 8);
257 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
258 tcg_gen_shli_i32(var
, var
, 8);
259 tcg_gen_ext8s_i32(var
, var
);
260 tcg_gen_or_i32(var
, var
, tmp
);
264 /* Unsigned bitfield extract. */
265 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
268 tcg_gen_shri_i32(var
, var
, shift
);
269 tcg_gen_andi_i32(var
, var
, mask
);
272 /* Signed bitfield extract. */
273 static void gen_sbfx(TCGv var
, int shift
, int width
)
278 tcg_gen_sari_i32(var
, var
, shift
);
279 if (shift
+ width
< 32) {
280 signbit
= 1u << (width
- 1);
281 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
282 tcg_gen_xori_i32(var
, var
, signbit
);
283 tcg_gen_subi_i32(var
, var
, signbit
);
287 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
288 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
290 tcg_gen_andi_i32(val
, val
, mask
);
291 tcg_gen_shli_i32(val
, val
, shift
);
292 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
293 tcg_gen_or_i32(dest
, base
, val
);
296 /* Round the top 32 bits of a 64-bit value. */
297 static void gen_roundqd(TCGv a
, TCGv b
)
299 tcg_gen_shri_i32(a
, a
, 31);
300 tcg_gen_add_i32(a
, a
, b
);
303 /* FIXME: Most targets have native widening multiplication.
304 It would be good to use that instead of a full wide multiply. */
305 /* 32x32->64 multiply. Marks inputs as dead. */
306 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
308 TCGv_i64 tmp1
= tcg_temp_new_i64();
309 TCGv_i64 tmp2
= tcg_temp_new_i64();
311 tcg_gen_extu_i32_i64(tmp1
, a
);
313 tcg_gen_extu_i32_i64(tmp2
, b
);
315 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
319 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
321 TCGv_i64 tmp1
= tcg_temp_new_i64();
322 TCGv_i64 tmp2
= tcg_temp_new_i64();
324 tcg_gen_ext_i32_i64(tmp1
, a
);
326 tcg_gen_ext_i32_i64(tmp2
, b
);
328 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
332 /* Unsigned 32x32->64 multiply. */
333 static void gen_mull(TCGv a
, TCGv b
)
335 TCGv_i64 tmp1
= tcg_temp_new_i64();
336 TCGv_i64 tmp2
= tcg_temp_new_i64();
338 tcg_gen_extu_i32_i64(tmp1
, a
);
339 tcg_gen_extu_i32_i64(tmp2
, b
);
340 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
341 tcg_gen_trunc_i64_i32(a
, tmp1
);
342 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
343 tcg_gen_trunc_i64_i32(b
, tmp1
);
346 /* Signed 32x32->64 multiply. */
347 static void gen_imull(TCGv a
, TCGv b
)
349 TCGv_i64 tmp1
= tcg_temp_new_i64();
350 TCGv_i64 tmp2
= tcg_temp_new_i64();
352 tcg_gen_ext_i32_i64(tmp1
, a
);
353 tcg_gen_ext_i32_i64(tmp2
, b
);
354 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
355 tcg_gen_trunc_i64_i32(a
, tmp1
);
356 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
357 tcg_gen_trunc_i64_i32(b
, tmp1
);
360 /* Swap low and high halfwords. */
361 static void gen_swap_half(TCGv var
)
363 TCGv tmp
= new_tmp();
364 tcg_gen_shri_i32(tmp
, var
, 16);
365 tcg_gen_shli_i32(var
, var
, 16);
366 tcg_gen_or_i32(var
, var
, tmp
);
370 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
371 tmp = (t0 ^ t1) & 0x8000;
374 t0 = (t0 + t1) ^ tmp;
377 static void gen_add16(TCGv t0
, TCGv t1
)
379 TCGv tmp
= new_tmp();
380 tcg_gen_xor_i32(tmp
, t0
, t1
);
381 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
382 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
383 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
384 tcg_gen_add_i32(t0
, t0
, t1
);
385 tcg_gen_xor_i32(t0
, t0
, tmp
);
390 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
392 /* Set CF to the top bit of var. */
393 static void gen_set_CF_bit31(TCGv var
)
395 TCGv tmp
= new_tmp();
396 tcg_gen_shri_i32(tmp
, var
, 31);
401 /* Set N and Z flags from var. */
402 static inline void gen_logic_CC(TCGv var
)
404 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
405 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
409 static void gen_adc(TCGv t0
, TCGv t1
)
412 tcg_gen_add_i32(t0
, t0
, t1
);
413 tmp
= load_cpu_field(CF
);
414 tcg_gen_add_i32(t0
, t0
, tmp
);
418 /* dest = T0 + T1 + CF. */
419 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
422 tcg_gen_add_i32(dest
, t0
, t1
);
423 tmp
= load_cpu_field(CF
);
424 tcg_gen_add_i32(dest
, dest
, tmp
);
428 /* dest = T0 - T1 + CF - 1. */
429 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
432 tcg_gen_sub_i32(dest
, t0
, t1
);
433 tmp
= load_cpu_field(CF
);
434 tcg_gen_add_i32(dest
, dest
, tmp
);
435 tcg_gen_subi_i32(dest
, dest
, 1);
439 /* T0 &= ~T1. Clobbers T1. */
440 /* FIXME: Implement bic natively. */
441 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
443 TCGv tmp
= new_tmp();
444 tcg_gen_not_i32(tmp
, t1
);
445 tcg_gen_and_i32(dest
, t0
, tmp
);
448 static inline void gen_op_bicl_T0_T1(void)
454 /* FIXME: Implement this natively. */
455 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
457 /* FIXME: Implement this natively. */
458 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
466 tcg_gen_shri_i32(tmp
, t1
, i
);
467 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
468 tcg_gen_or_i32(t0
, t1
, tmp
);
472 static void shifter_out_im(TCGv var
, int shift
)
474 TCGv tmp
= new_tmp();
476 tcg_gen_andi_i32(tmp
, var
, 1);
478 tcg_gen_shri_i32(tmp
, var
, shift
);
480 tcg_gen_andi_i32(tmp
, tmp
, 1);
486 /* Shift by immediate. Includes special handling for shift == 0. */
487 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
493 shifter_out_im(var
, 32 - shift
);
494 tcg_gen_shli_i32(var
, var
, shift
);
500 tcg_gen_shri_i32(var
, var
, 31);
503 tcg_gen_movi_i32(var
, 0);
506 shifter_out_im(var
, shift
- 1);
507 tcg_gen_shri_i32(var
, var
, shift
);
514 shifter_out_im(var
, shift
- 1);
517 tcg_gen_sari_i32(var
, var
, shift
);
519 case 3: /* ROR/RRX */
522 shifter_out_im(var
, shift
- 1);
523 tcg_gen_rori_i32(var
, var
, shift
); break;
525 TCGv tmp
= load_cpu_field(CF
);
527 shifter_out_im(var
, 0);
528 tcg_gen_shri_i32(var
, var
, 1);
529 tcg_gen_shli_i32(tmp
, tmp
, 31);
530 tcg_gen_or_i32(var
, var
, tmp
);
536 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
537 TCGv shift
, int flags
)
541 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
542 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
543 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
544 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
548 case 0: gen_helper_shl(var
, var
, shift
); break;
549 case 1: gen_helper_shr(var
, var
, shift
); break;
550 case 2: gen_helper_sar(var
, var
, shift
); break;
551 case 3: gen_helper_ror(var
, var
, shift
); break;
557 #define PAS_OP(pfx) \
559 case 0: gen_pas_helper(glue(pfx,add16)); break; \
560 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
561 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
562 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
563 case 4: gen_pas_helper(glue(pfx,add8)); break; \
564 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
566 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
571 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
573 tmp
= tcg_temp_new_ptr();
574 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
578 tmp
= tcg_temp_new_ptr();
579 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
582 #undef gen_pas_helper
583 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
596 #undef gen_pas_helper
601 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
602 #define PAS_OP(pfx) \
604 case 0: gen_pas_helper(glue(pfx,add8)); break; \
605 case 1: gen_pas_helper(glue(pfx,add16)); break; \
606 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
607 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
608 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
609 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
611 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
616 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
618 tmp
= tcg_temp_new_ptr();
619 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
623 tmp
= tcg_temp_new_ptr();
624 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
627 #undef gen_pas_helper
628 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
641 #undef gen_pas_helper
646 static void gen_test_cc(int cc
, int label
)
654 tmp
= load_cpu_field(ZF
);
655 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
658 tmp
= load_cpu_field(ZF
);
659 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
662 tmp
= load_cpu_field(CF
);
663 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
666 tmp
= load_cpu_field(CF
);
667 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
670 tmp
= load_cpu_field(NF
);
671 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
674 tmp
= load_cpu_field(NF
);
675 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
678 tmp
= load_cpu_field(VF
);
679 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
682 tmp
= load_cpu_field(VF
);
683 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
685 case 8: /* hi: C && !Z */
686 inv
= gen_new_label();
687 tmp
= load_cpu_field(CF
);
688 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
690 tmp
= load_cpu_field(ZF
);
691 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
694 case 9: /* ls: !C || Z */
695 tmp
= load_cpu_field(CF
);
696 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
698 tmp
= load_cpu_field(ZF
);
699 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
701 case 10: /* ge: N == V -> N ^ V == 0 */
702 tmp
= load_cpu_field(VF
);
703 tmp2
= load_cpu_field(NF
);
704 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
706 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
708 case 11: /* lt: N != V -> N ^ V != 0 */
709 tmp
= load_cpu_field(VF
);
710 tmp2
= load_cpu_field(NF
);
711 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
713 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
715 case 12: /* gt: !Z && N == V */
716 inv
= gen_new_label();
717 tmp
= load_cpu_field(ZF
);
718 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
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_GE
, tmp
, 0, label
);
727 case 13: /* le: Z || N != V */
728 tmp
= load_cpu_field(ZF
);
729 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
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_LT
, tmp
, 0, label
);
738 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
744 static const uint8_t table_logic_cc
[16] = {
763 /* Set PC and Thumb state from an immediate address. */
764 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
768 s
->is_jmp
= DISAS_UPDATE
;
769 if (s
->thumb
!= (addr
& 1)) {
771 tcg_gen_movi_i32(tmp
, addr
& 1);
772 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
775 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
778 /* Set PC and Thumb state from var. var is marked as dead. */
779 static inline void gen_bx(DisasContext
*s
, TCGv var
)
781 s
->is_jmp
= DISAS_UPDATE
;
782 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
783 tcg_gen_andi_i32(var
, var
, 1);
784 store_cpu_field(var
, thumb
);
787 /* Variant of store_reg which uses branch&exchange logic when storing
788 to r15 in ARM architecture v7 and above. The source must be a temporary
789 and will be marked as dead. */
790 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
793 if (reg
== 15 && ENABLE_ARCH_7
) {
796 store_reg(s
, reg
, var
);
800 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
802 TCGv tmp
= new_tmp();
803 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
806 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
808 TCGv tmp
= new_tmp();
809 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
812 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
814 TCGv tmp
= new_tmp();
815 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
818 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
820 TCGv tmp
= new_tmp();
821 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
824 static inline TCGv
gen_ld32(TCGv addr
, int index
)
826 TCGv tmp
= new_tmp();
827 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
830 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
832 tcg_gen_qemu_st8(val
, addr
, index
);
835 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
837 tcg_gen_qemu_st16(val
, addr
, index
);
840 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
842 tcg_gen_qemu_st32(val
, addr
, index
);
846 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
848 load_reg_var(s
, cpu_T
[0], reg
);
851 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
853 load_reg_var(s
, cpu_T
[1], reg
);
856 static inline void gen_set_pc_im(uint32_t val
)
858 tcg_gen_movi_i32(cpu_R
[15], val
);
861 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
866 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
870 tcg_gen_mov_i32(cpu_R
[reg
], tmp
);
873 s
->is_jmp
= DISAS_JUMP
;
877 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
879 gen_movl_reg_TN(s
, reg
, 0);
882 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
884 gen_movl_reg_TN(s
, reg
, 1);
887 /* Force a TB lookup after an instruction that changes the CPU state. */
888 static inline void gen_lookup_tb(DisasContext
*s
)
890 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
891 s
->is_jmp
= DISAS_UPDATE
;
894 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
897 int val
, rm
, shift
, shiftop
;
900 if (!(insn
& (1 << 25))) {
903 if (!(insn
& (1 << 23)))
906 tcg_gen_addi_i32(var
, var
, val
);
910 shift
= (insn
>> 7) & 0x1f;
911 shiftop
= (insn
>> 5) & 3;
912 offset
= load_reg(s
, rm
);
913 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
914 if (!(insn
& (1 << 23)))
915 tcg_gen_sub_i32(var
, var
, offset
);
917 tcg_gen_add_i32(var
, var
, offset
);
922 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
928 if (insn
& (1 << 22)) {
930 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
931 if (!(insn
& (1 << 23)))
935 tcg_gen_addi_i32(var
, var
, val
);
939 tcg_gen_addi_i32(var
, var
, extra
);
941 offset
= load_reg(s
, rm
);
942 if (!(insn
& (1 << 23)))
943 tcg_gen_sub_i32(var
, var
, offset
);
945 tcg_gen_add_i32(var
, var
, offset
);
950 #define VFP_OP2(name) \
951 static inline void gen_vfp_##name(int dp) \
954 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
956 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
966 static inline void gen_vfp_abs(int dp
)
969 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
971 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
974 static inline void gen_vfp_neg(int dp
)
977 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
979 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
982 static inline void gen_vfp_sqrt(int dp
)
985 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
987 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
990 static inline void gen_vfp_cmp(int dp
)
993 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
995 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
998 static inline void gen_vfp_cmpe(int dp
)
1001 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1003 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1006 static inline void gen_vfp_F1_ld0(int dp
)
1009 tcg_gen_movi_i64(cpu_F1d
, 0);
1011 tcg_gen_movi_i32(cpu_F1s
, 0);
1014 static inline void gen_vfp_uito(int dp
)
1017 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1019 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1022 static inline void gen_vfp_sito(int dp
)
1025 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1027 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1030 static inline void gen_vfp_toui(int dp
)
1033 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1035 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1038 static inline void gen_vfp_touiz(int dp
)
1041 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1043 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1046 static inline void gen_vfp_tosi(int dp
)
1049 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1051 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1054 static inline void gen_vfp_tosiz(int dp
)
1057 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1059 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1062 #define VFP_GEN_FIX(name) \
1063 static inline void gen_vfp_##name(int dp, int shift) \
1066 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1068 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1080 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1083 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1085 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1088 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1091 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1093 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1097 vfp_reg_offset (int dp
, int reg
)
1100 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1102 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1103 + offsetof(CPU_DoubleU
, l
.upper
);
1105 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1106 + offsetof(CPU_DoubleU
, l
.lower
);
1110 /* Return the offset of a 32-bit piece of a NEON register.
1111 zero is the least significant end of the register. */
1113 neon_reg_offset (int reg
, int n
)
1117 return vfp_reg_offset(0, sreg
);
1120 /* FIXME: Remove these. */
1121 #define neon_T0 cpu_T[0]
1122 #define neon_T1 cpu_T[1]
1123 #define NEON_GET_REG(T, reg, n) \
1124 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1125 #define NEON_SET_REG(T, reg, n) \
1126 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1128 static TCGv
neon_load_reg(int reg
, int pass
)
1130 TCGv tmp
= new_tmp();
1131 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1135 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1137 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1141 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1143 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1146 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1148 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1151 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1152 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1153 #define tcg_gen_st_f32 tcg_gen_st_i32
1154 #define tcg_gen_st_f64 tcg_gen_st_i64
1156 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1159 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1161 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1164 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1167 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1169 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1172 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1175 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1177 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1180 #define ARM_CP_RW_BIT (1 << 20)
1182 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1184 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1187 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1189 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1192 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1194 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1197 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1199 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1202 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1204 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1207 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1209 iwmmxt_store_reg(cpu_M0
, rn
);
1212 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1214 iwmmxt_load_reg(cpu_M0
, rn
);
1217 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1219 iwmmxt_load_reg(cpu_V1
, rn
);
1220 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1223 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1225 iwmmxt_load_reg(cpu_V1
, rn
);
1226 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1229 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1231 iwmmxt_load_reg(cpu_V1
, rn
);
1232 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1235 #define IWMMXT_OP(name) \
1236 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1238 iwmmxt_load_reg(cpu_V1, rn); \
1239 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1242 #define IWMMXT_OP_ENV(name) \
1243 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1245 iwmmxt_load_reg(cpu_V1, rn); \
1246 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1249 #define IWMMXT_OP_ENV_SIZE(name) \
1250 IWMMXT_OP_ENV(name##b) \
1251 IWMMXT_OP_ENV(name##w) \
1252 IWMMXT_OP_ENV(name##l)
1254 #define IWMMXT_OP_ENV1(name) \
1255 static inline void gen_op_iwmmxt_##name##_M0(void) \
1257 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1271 IWMMXT_OP_ENV_SIZE(unpackl
)
1272 IWMMXT_OP_ENV_SIZE(unpackh
)
1274 IWMMXT_OP_ENV1(unpacklub
)
1275 IWMMXT_OP_ENV1(unpackluw
)
1276 IWMMXT_OP_ENV1(unpacklul
)
1277 IWMMXT_OP_ENV1(unpackhub
)
1278 IWMMXT_OP_ENV1(unpackhuw
)
1279 IWMMXT_OP_ENV1(unpackhul
)
1280 IWMMXT_OP_ENV1(unpacklsb
)
1281 IWMMXT_OP_ENV1(unpacklsw
)
1282 IWMMXT_OP_ENV1(unpacklsl
)
1283 IWMMXT_OP_ENV1(unpackhsb
)
1284 IWMMXT_OP_ENV1(unpackhsw
)
1285 IWMMXT_OP_ENV1(unpackhsl
)
1287 IWMMXT_OP_ENV_SIZE(cmpeq
)
1288 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1289 IWMMXT_OP_ENV_SIZE(cmpgts
)
1291 IWMMXT_OP_ENV_SIZE(mins
)
1292 IWMMXT_OP_ENV_SIZE(minu
)
1293 IWMMXT_OP_ENV_SIZE(maxs
)
1294 IWMMXT_OP_ENV_SIZE(maxu
)
1296 IWMMXT_OP_ENV_SIZE(subn
)
1297 IWMMXT_OP_ENV_SIZE(addn
)
1298 IWMMXT_OP_ENV_SIZE(subu
)
1299 IWMMXT_OP_ENV_SIZE(addu
)
1300 IWMMXT_OP_ENV_SIZE(subs
)
1301 IWMMXT_OP_ENV_SIZE(adds
)
1303 IWMMXT_OP_ENV(avgb0
)
1304 IWMMXT_OP_ENV(avgb1
)
1305 IWMMXT_OP_ENV(avgw0
)
1306 IWMMXT_OP_ENV(avgw1
)
1310 IWMMXT_OP_ENV(packuw
)
1311 IWMMXT_OP_ENV(packul
)
1312 IWMMXT_OP_ENV(packuq
)
1313 IWMMXT_OP_ENV(packsw
)
1314 IWMMXT_OP_ENV(packsl
)
1315 IWMMXT_OP_ENV(packsq
)
1317 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1319 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1322 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1324 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1327 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1329 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1332 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1334 iwmmxt_load_reg(cpu_V1
, rn
);
1335 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1338 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1340 TCGv tmp
= tcg_const_i32(shift
);
1341 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1344 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1346 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1347 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1348 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1351 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1353 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1354 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1355 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1358 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1360 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1361 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1363 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1366 static void gen_op_iwmmxt_set_mup(void)
1369 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1370 tcg_gen_ori_i32(tmp
, tmp
, 2);
1371 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1374 static void gen_op_iwmmxt_set_cup(void)
1377 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1378 tcg_gen_ori_i32(tmp
, tmp
, 1);
1379 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1382 static void gen_op_iwmmxt_setpsr_nz(void)
1384 TCGv tmp
= new_tmp();
1385 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1386 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1389 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1391 iwmmxt_load_reg(cpu_V1
, rn
);
1392 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1393 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1397 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1399 iwmmxt_load_reg(cpu_V0
, rn
);
1400 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1401 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1402 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1405 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1407 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1408 iwmmxt_store_reg(cpu_V0
, rn
);
1411 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1416 rd
= (insn
>> 16) & 0xf;
1417 gen_movl_T1_reg(s
, rd
);
1419 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1420 if (insn
& (1 << 24)) {
1422 if (insn
& (1 << 23))
1423 gen_op_addl_T1_im(offset
);
1425 gen_op_addl_T1_im(-offset
);
1427 if (insn
& (1 << 21))
1428 gen_movl_reg_T1(s
, rd
);
1429 } else if (insn
& (1 << 21)) {
1431 if (insn
& (1 << 23))
1432 gen_op_movl_T0_im(offset
);
1434 gen_op_movl_T0_im(- offset
);
1435 gen_op_addl_T0_T1();
1436 gen_movl_reg_T0(s
, rd
);
1437 } else if (!(insn
& (1 << 23)))
1442 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1444 int rd
= (insn
>> 0) & 0xf;
1446 if (insn
& (1 << 8))
1447 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1450 gen_op_iwmmxt_movl_T0_wCx(rd
);
1452 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1454 gen_op_movl_T1_im(mask
);
1455 gen_op_andl_T0_T1();
1459 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1460 (ie. an undefined instruction). */
1461 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1464 int rdhi
, rdlo
, rd0
, rd1
, i
;
1467 if ((insn
& 0x0e000e00) == 0x0c000000) {
1468 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1470 rdlo
= (insn
>> 12) & 0xf;
1471 rdhi
= (insn
>> 16) & 0xf;
1472 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1473 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1474 gen_movl_reg_T0(s
, rdlo
);
1475 gen_movl_reg_T1(s
, rdhi
);
1476 } else { /* TMCRR */
1477 gen_movl_T0_reg(s
, rdlo
);
1478 gen_movl_T1_reg(s
, rdhi
);
1479 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1480 gen_op_iwmmxt_set_mup();
1485 wrd
= (insn
>> 12) & 0xf;
1486 if (gen_iwmmxt_address(s
, insn
))
1488 if (insn
& ARM_CP_RW_BIT
) {
1489 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1490 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1491 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1493 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1496 if (insn
& (1 << 8)) {
1497 if (insn
& (1 << 22)) { /* WLDRD */
1498 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1500 } else { /* WLDRW wRd */
1501 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1504 if (insn
& (1 << 22)) { /* WLDRH */
1505 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1506 } else { /* WLDRB */
1507 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1511 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1514 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1517 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1518 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1520 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1521 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1523 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1525 if (insn
& (1 << 8)) {
1526 if (insn
& (1 << 22)) { /* WSTRD */
1528 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1529 } else { /* WSTRW wRd */
1530 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1531 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1534 if (insn
& (1 << 22)) { /* WSTRH */
1535 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1536 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1537 } else { /* WSTRB */
1538 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1539 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1547 if ((insn
& 0x0f000000) != 0x0e000000)
1550 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1551 case 0x000: /* WOR */
1552 wrd
= (insn
>> 12) & 0xf;
1553 rd0
= (insn
>> 0) & 0xf;
1554 rd1
= (insn
>> 16) & 0xf;
1555 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1556 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1557 gen_op_iwmmxt_setpsr_nz();
1558 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1559 gen_op_iwmmxt_set_mup();
1560 gen_op_iwmmxt_set_cup();
1562 case 0x011: /* TMCR */
1565 rd
= (insn
>> 12) & 0xf;
1566 wrd
= (insn
>> 16) & 0xf;
1568 case ARM_IWMMXT_wCID
:
1569 case ARM_IWMMXT_wCASF
:
1571 case ARM_IWMMXT_wCon
:
1572 gen_op_iwmmxt_set_cup();
1574 case ARM_IWMMXT_wCSSF
:
1575 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1576 gen_movl_T1_reg(s
, rd
);
1577 gen_op_bicl_T0_T1();
1578 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1580 case ARM_IWMMXT_wCGR0
:
1581 case ARM_IWMMXT_wCGR1
:
1582 case ARM_IWMMXT_wCGR2
:
1583 case ARM_IWMMXT_wCGR3
:
1584 gen_op_iwmmxt_set_cup();
1585 gen_movl_reg_T0(s
, rd
);
1586 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1592 case 0x100: /* WXOR */
1593 wrd
= (insn
>> 12) & 0xf;
1594 rd0
= (insn
>> 0) & 0xf;
1595 rd1
= (insn
>> 16) & 0xf;
1596 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1597 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1598 gen_op_iwmmxt_setpsr_nz();
1599 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1600 gen_op_iwmmxt_set_mup();
1601 gen_op_iwmmxt_set_cup();
1603 case 0x111: /* TMRC */
1606 rd
= (insn
>> 12) & 0xf;
1607 wrd
= (insn
>> 16) & 0xf;
1608 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1609 gen_movl_reg_T0(s
, rd
);
1611 case 0x300: /* WANDN */
1612 wrd
= (insn
>> 12) & 0xf;
1613 rd0
= (insn
>> 0) & 0xf;
1614 rd1
= (insn
>> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1616 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1617 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1618 gen_op_iwmmxt_setpsr_nz();
1619 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1620 gen_op_iwmmxt_set_mup();
1621 gen_op_iwmmxt_set_cup();
1623 case 0x200: /* WAND */
1624 wrd
= (insn
>> 12) & 0xf;
1625 rd0
= (insn
>> 0) & 0xf;
1626 rd1
= (insn
>> 16) & 0xf;
1627 gen_op_iwmmxt_movq_M0_wRn(rd0
);
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 0x810: case 0xa10: /* WMADD */
1635 wrd
= (insn
>> 12) & 0xf;
1636 rd0
= (insn
>> 0) & 0xf;
1637 rd1
= (insn
>> 16) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1639 if (insn
& (1 << 21))
1640 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1642 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1643 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1644 gen_op_iwmmxt_set_mup();
1646 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1647 wrd
= (insn
>> 12) & 0xf;
1648 rd0
= (insn
>> 16) & 0xf;
1649 rd1
= (insn
>> 0) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1651 switch ((insn
>> 22) & 3) {
1653 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1656 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1659 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1664 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1665 gen_op_iwmmxt_set_mup();
1666 gen_op_iwmmxt_set_cup();
1668 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1669 wrd
= (insn
>> 12) & 0xf;
1670 rd0
= (insn
>> 16) & 0xf;
1671 rd1
= (insn
>> 0) & 0xf;
1672 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1673 switch ((insn
>> 22) & 3) {
1675 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1678 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1681 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1686 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1687 gen_op_iwmmxt_set_mup();
1688 gen_op_iwmmxt_set_cup();
1690 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1691 wrd
= (insn
>> 12) & 0xf;
1692 rd0
= (insn
>> 16) & 0xf;
1693 rd1
= (insn
>> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1695 if (insn
& (1 << 22))
1696 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1698 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1699 if (!(insn
& (1 << 20)))
1700 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1701 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1702 gen_op_iwmmxt_set_mup();
1704 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1705 wrd
= (insn
>> 12) & 0xf;
1706 rd0
= (insn
>> 16) & 0xf;
1707 rd1
= (insn
>> 0) & 0xf;
1708 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1709 if (insn
& (1 << 21)) {
1710 if (insn
& (1 << 20))
1711 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1713 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1715 if (insn
& (1 << 20))
1716 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1718 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1720 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1721 gen_op_iwmmxt_set_mup();
1723 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1724 wrd
= (insn
>> 12) & 0xf;
1725 rd0
= (insn
>> 16) & 0xf;
1726 rd1
= (insn
>> 0) & 0xf;
1727 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1728 if (insn
& (1 << 21))
1729 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1731 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1732 if (!(insn
& (1 << 20))) {
1733 iwmmxt_load_reg(cpu_V1
, wrd
);
1734 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1736 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1737 gen_op_iwmmxt_set_mup();
1739 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1740 wrd
= (insn
>> 12) & 0xf;
1741 rd0
= (insn
>> 16) & 0xf;
1742 rd1
= (insn
>> 0) & 0xf;
1743 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1744 switch ((insn
>> 22) & 3) {
1746 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1749 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1752 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1757 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1758 gen_op_iwmmxt_set_mup();
1759 gen_op_iwmmxt_set_cup();
1761 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1762 wrd
= (insn
>> 12) & 0xf;
1763 rd0
= (insn
>> 16) & 0xf;
1764 rd1
= (insn
>> 0) & 0xf;
1765 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1766 if (insn
& (1 << 22)) {
1767 if (insn
& (1 << 20))
1768 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1770 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1772 if (insn
& (1 << 20))
1773 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1775 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1777 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1778 gen_op_iwmmxt_set_mup();
1779 gen_op_iwmmxt_set_cup();
1781 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1782 wrd
= (insn
>> 12) & 0xf;
1783 rd0
= (insn
>> 16) & 0xf;
1784 rd1
= (insn
>> 0) & 0xf;
1785 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1786 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1787 gen_op_movl_T1_im(7);
1788 gen_op_andl_T0_T1();
1789 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1790 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1791 gen_op_iwmmxt_set_mup();
1793 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1794 rd
= (insn
>> 12) & 0xf;
1795 wrd
= (insn
>> 16) & 0xf;
1796 gen_movl_T0_reg(s
, rd
);
1797 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1798 switch ((insn
>> 6) & 3) {
1800 gen_op_movl_T1_im(0xff);
1801 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1804 gen_op_movl_T1_im(0xffff);
1805 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1808 gen_op_movl_T1_im(0xffffffff);
1809 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1814 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1815 gen_op_iwmmxt_set_mup();
1817 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1818 rd
= (insn
>> 12) & 0xf;
1819 wrd
= (insn
>> 16) & 0xf;
1822 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1823 switch ((insn
>> 22) & 3) {
1826 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1828 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1833 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1835 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1839 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1844 gen_movl_reg_T0(s
, rd
);
1846 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1847 if ((insn
& 0x000ff008) != 0x0003f000)
1849 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1850 switch ((insn
>> 22) & 3) {
1852 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1855 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1858 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1863 gen_op_shll_T1_im(28);
1864 gen_set_nzcv(cpu_T
[1]);
1866 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1867 rd
= (insn
>> 12) & 0xf;
1868 wrd
= (insn
>> 16) & 0xf;
1869 gen_movl_T0_reg(s
, rd
);
1870 switch ((insn
>> 6) & 3) {
1872 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1875 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1878 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1883 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1884 gen_op_iwmmxt_set_mup();
1886 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1887 if ((insn
& 0x000ff00f) != 0x0003f000)
1889 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1890 gen_op_movl_T0_T1();
1891 switch ((insn
>> 22) & 3) {
1893 for (i
= 0; i
< 7; i
++) {
1894 gen_op_shll_T1_im(4);
1895 gen_op_andl_T0_T1();
1899 for (i
= 0; i
< 3; i
++) {
1900 gen_op_shll_T1_im(8);
1901 gen_op_andl_T0_T1();
1905 gen_op_shll_T1_im(16);
1906 gen_op_andl_T0_T1();
1911 gen_set_nzcv(cpu_T
[0]);
1913 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1914 wrd
= (insn
>> 12) & 0xf;
1915 rd0
= (insn
>> 16) & 0xf;
1916 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1917 switch ((insn
>> 22) & 3) {
1919 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1922 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1925 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1930 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1931 gen_op_iwmmxt_set_mup();
1933 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1934 if ((insn
& 0x000ff00f) != 0x0003f000)
1936 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1937 gen_op_movl_T0_T1();
1938 switch ((insn
>> 22) & 3) {
1940 for (i
= 0; i
< 7; i
++) {
1941 gen_op_shll_T1_im(4);
1946 for (i
= 0; i
< 3; i
++) {
1947 gen_op_shll_T1_im(8);
1952 gen_op_shll_T1_im(16);
1958 gen_set_nzcv(cpu_T
[0]);
1960 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1961 rd
= (insn
>> 12) & 0xf;
1962 rd0
= (insn
>> 16) & 0xf;
1963 if ((insn
& 0xf) != 0)
1965 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1966 switch ((insn
>> 22) & 3) {
1968 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
1971 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
1974 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
1979 gen_movl_reg_T0(s
, rd
);
1981 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1982 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1983 wrd
= (insn
>> 12) & 0xf;
1984 rd0
= (insn
>> 16) & 0xf;
1985 rd1
= (insn
>> 0) & 0xf;
1986 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1987 switch ((insn
>> 22) & 3) {
1989 if (insn
& (1 << 21))
1990 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1992 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1995 if (insn
& (1 << 21))
1996 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1998 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2001 if (insn
& (1 << 21))
2002 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2004 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2009 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2010 gen_op_iwmmxt_set_mup();
2011 gen_op_iwmmxt_set_cup();
2013 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2014 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2015 wrd
= (insn
>> 12) & 0xf;
2016 rd0
= (insn
>> 16) & 0xf;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2018 switch ((insn
>> 22) & 3) {
2020 if (insn
& (1 << 21))
2021 gen_op_iwmmxt_unpacklsb_M0();
2023 gen_op_iwmmxt_unpacklub_M0();
2026 if (insn
& (1 << 21))
2027 gen_op_iwmmxt_unpacklsw_M0();
2029 gen_op_iwmmxt_unpackluw_M0();
2032 if (insn
& (1 << 21))
2033 gen_op_iwmmxt_unpacklsl_M0();
2035 gen_op_iwmmxt_unpacklul_M0();
2040 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2041 gen_op_iwmmxt_set_mup();
2042 gen_op_iwmmxt_set_cup();
2044 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2045 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2046 wrd
= (insn
>> 12) & 0xf;
2047 rd0
= (insn
>> 16) & 0xf;
2048 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2049 switch ((insn
>> 22) & 3) {
2051 if (insn
& (1 << 21))
2052 gen_op_iwmmxt_unpackhsb_M0();
2054 gen_op_iwmmxt_unpackhub_M0();
2057 if (insn
& (1 << 21))
2058 gen_op_iwmmxt_unpackhsw_M0();
2060 gen_op_iwmmxt_unpackhuw_M0();
2063 if (insn
& (1 << 21))
2064 gen_op_iwmmxt_unpackhsl_M0();
2066 gen_op_iwmmxt_unpackhul_M0();
2071 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2072 gen_op_iwmmxt_set_mup();
2073 gen_op_iwmmxt_set_cup();
2075 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2076 case 0x214: case 0x614: case 0xa14: case 0xe14:
2077 wrd
= (insn
>> 12) & 0xf;
2078 rd0
= (insn
>> 16) & 0xf;
2079 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2080 if (gen_iwmmxt_shift(insn
, 0xff))
2082 switch ((insn
>> 22) & 3) {
2086 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2089 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2092 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2095 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2096 gen_op_iwmmxt_set_mup();
2097 gen_op_iwmmxt_set_cup();
2099 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2100 case 0x014: case 0x414: case 0x814: case 0xc14:
2101 wrd
= (insn
>> 12) & 0xf;
2102 rd0
= (insn
>> 16) & 0xf;
2103 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2104 if (gen_iwmmxt_shift(insn
, 0xff))
2106 switch ((insn
>> 22) & 3) {
2110 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2113 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2116 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2119 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2120 gen_op_iwmmxt_set_mup();
2121 gen_op_iwmmxt_set_cup();
2123 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2124 case 0x114: case 0x514: case 0x914: case 0xd14:
2125 wrd
= (insn
>> 12) & 0xf;
2126 rd0
= (insn
>> 16) & 0xf;
2127 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2128 if (gen_iwmmxt_shift(insn
, 0xff))
2130 switch ((insn
>> 22) & 3) {
2134 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2137 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2140 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2143 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2144 gen_op_iwmmxt_set_mup();
2145 gen_op_iwmmxt_set_cup();
2147 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2148 case 0x314: case 0x714: case 0xb14: case 0xf14:
2149 wrd
= (insn
>> 12) & 0xf;
2150 rd0
= (insn
>> 16) & 0xf;
2151 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2152 switch ((insn
>> 22) & 3) {
2156 if (gen_iwmmxt_shift(insn
, 0xf))
2158 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2161 if (gen_iwmmxt_shift(insn
, 0x1f))
2163 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2166 if (gen_iwmmxt_shift(insn
, 0x3f))
2168 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2171 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2172 gen_op_iwmmxt_set_mup();
2173 gen_op_iwmmxt_set_cup();
2175 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2176 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2177 wrd
= (insn
>> 12) & 0xf;
2178 rd0
= (insn
>> 16) & 0xf;
2179 rd1
= (insn
>> 0) & 0xf;
2180 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2181 switch ((insn
>> 22) & 3) {
2183 if (insn
& (1 << 21))
2184 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2186 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2189 if (insn
& (1 << 21))
2190 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2192 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2195 if (insn
& (1 << 21))
2196 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2198 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2203 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2204 gen_op_iwmmxt_set_mup();
2206 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2207 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2208 wrd
= (insn
>> 12) & 0xf;
2209 rd0
= (insn
>> 16) & 0xf;
2210 rd1
= (insn
>> 0) & 0xf;
2211 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2212 switch ((insn
>> 22) & 3) {
2214 if (insn
& (1 << 21))
2215 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2217 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2220 if (insn
& (1 << 21))
2221 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2223 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2226 if (insn
& (1 << 21))
2227 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2229 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2234 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2235 gen_op_iwmmxt_set_mup();
2237 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2238 case 0x402: case 0x502: case 0x602: case 0x702:
2239 wrd
= (insn
>> 12) & 0xf;
2240 rd0
= (insn
>> 16) & 0xf;
2241 rd1
= (insn
>> 0) & 0xf;
2242 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2243 gen_op_movl_T0_im((insn
>> 20) & 3);
2244 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2245 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2246 gen_op_iwmmxt_set_mup();
2248 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2249 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2250 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2251 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2252 wrd
= (insn
>> 12) & 0xf;
2253 rd0
= (insn
>> 16) & 0xf;
2254 rd1
= (insn
>> 0) & 0xf;
2255 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2256 switch ((insn
>> 20) & 0xf) {
2258 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2261 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2264 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2267 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2270 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2273 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2276 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2279 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2282 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2288 gen_op_iwmmxt_set_mup();
2289 gen_op_iwmmxt_set_cup();
2291 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2292 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2293 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2294 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2295 wrd
= (insn
>> 12) & 0xf;
2296 rd0
= (insn
>> 16) & 0xf;
2297 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2298 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2299 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2300 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2301 gen_op_iwmmxt_set_mup();
2302 gen_op_iwmmxt_set_cup();
2304 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2305 case 0x418: case 0x518: case 0x618: case 0x718:
2306 case 0x818: case 0x918: case 0xa18: case 0xb18:
2307 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2308 wrd
= (insn
>> 12) & 0xf;
2309 rd0
= (insn
>> 16) & 0xf;
2310 rd1
= (insn
>> 0) & 0xf;
2311 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2312 switch ((insn
>> 20) & 0xf) {
2314 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2317 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2320 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2323 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2326 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2329 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2332 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2335 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2338 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2343 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2344 gen_op_iwmmxt_set_mup();
2345 gen_op_iwmmxt_set_cup();
2347 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2348 case 0x408: case 0x508: case 0x608: case 0x708:
2349 case 0x808: case 0x908: case 0xa08: case 0xb08:
2350 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2351 wrd
= (insn
>> 12) & 0xf;
2352 rd0
= (insn
>> 16) & 0xf;
2353 rd1
= (insn
>> 0) & 0xf;
2354 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2355 if (!(insn
& (1 << 20)))
2357 switch ((insn
>> 22) & 3) {
2361 if (insn
& (1 << 21))
2362 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2364 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2367 if (insn
& (1 << 21))
2368 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2370 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2373 if (insn
& (1 << 21))
2374 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2376 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2379 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2380 gen_op_iwmmxt_set_mup();
2381 gen_op_iwmmxt_set_cup();
2383 case 0x201: case 0x203: case 0x205: case 0x207:
2384 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2385 case 0x211: case 0x213: case 0x215: case 0x217:
2386 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2387 wrd
= (insn
>> 5) & 0xf;
2388 rd0
= (insn
>> 12) & 0xf;
2389 rd1
= (insn
>> 0) & 0xf;
2390 if (rd0
== 0xf || rd1
== 0xf)
2392 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2393 switch ((insn
>> 16) & 0xf) {
2394 case 0x0: /* TMIA */
2395 gen_movl_T0_reg(s
, rd0
);
2396 gen_movl_T1_reg(s
, rd1
);
2397 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2399 case 0x8: /* TMIAPH */
2400 gen_movl_T0_reg(s
, rd0
);
2401 gen_movl_T1_reg(s
, rd1
);
2402 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2404 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2405 gen_movl_T1_reg(s
, rd0
);
2406 if (insn
& (1 << 16))
2407 gen_op_shrl_T1_im(16);
2408 gen_op_movl_T0_T1();
2409 gen_movl_T1_reg(s
, rd1
);
2410 if (insn
& (1 << 17))
2411 gen_op_shrl_T1_im(16);
2412 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2417 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2418 gen_op_iwmmxt_set_mup();
2427 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2428 (ie. an undefined instruction). */
2429 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2431 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2433 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2434 /* Multiply with Internal Accumulate Format */
2435 rd0
= (insn
>> 12) & 0xf;
2437 acc
= (insn
>> 5) & 7;
2442 switch ((insn
>> 16) & 0xf) {
2444 gen_movl_T0_reg(s
, rd0
);
2445 gen_movl_T1_reg(s
, rd1
);
2446 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2448 case 0x8: /* MIAPH */
2449 gen_movl_T0_reg(s
, rd0
);
2450 gen_movl_T1_reg(s
, rd1
);
2451 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2453 case 0xc: /* MIABB */
2454 case 0xd: /* MIABT */
2455 case 0xe: /* MIATB */
2456 case 0xf: /* MIATT */
2457 gen_movl_T1_reg(s
, rd0
);
2458 if (insn
& (1 << 16))
2459 gen_op_shrl_T1_im(16);
2460 gen_op_movl_T0_T1();
2461 gen_movl_T1_reg(s
, rd1
);
2462 if (insn
& (1 << 17))
2463 gen_op_shrl_T1_im(16);
2464 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2470 gen_op_iwmmxt_movq_wRn_M0(acc
);
2474 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2475 /* Internal Accumulator Access Format */
2476 rdhi
= (insn
>> 16) & 0xf;
2477 rdlo
= (insn
>> 12) & 0xf;
2483 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2484 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2485 gen_movl_reg_T0(s
, rdlo
);
2486 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2487 gen_op_andl_T0_T1();
2488 gen_movl_reg_T0(s
, rdhi
);
2490 gen_movl_T0_reg(s
, rdlo
);
2491 gen_movl_T1_reg(s
, rdhi
);
2492 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2500 /* Disassemble system coprocessor instruction. Return nonzero if
2501 instruction is not defined. */
2502 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2505 uint32_t rd
= (insn
>> 12) & 0xf;
2506 uint32_t cp
= (insn
>> 8) & 0xf;
2511 if (insn
& ARM_CP_RW_BIT
) {
2512 if (!env
->cp
[cp
].cp_read
)
2514 gen_set_pc_im(s
->pc
);
2516 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2517 store_reg(s
, rd
, tmp
);
2519 if (!env
->cp
[cp
].cp_write
)
2521 gen_set_pc_im(s
->pc
);
2522 tmp
= load_reg(s
, rd
);
2523 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2529 static int cp15_user_ok(uint32_t insn
)
2531 int cpn
= (insn
>> 16) & 0xf;
2532 int cpm
= insn
& 0xf;
2533 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2535 if (cpn
== 13 && cpm
== 0) {
2537 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2541 /* ISB, DSB, DMB. */
2542 if ((cpm
== 5 && op
== 4)
2543 || (cpm
== 10 && (op
== 4 || op
== 5)))
2549 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2550 instruction is not defined. */
2551 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2556 /* M profile cores use memory mapped registers instead of cp15. */
2557 if (arm_feature(env
, ARM_FEATURE_M
))
2560 if ((insn
& (1 << 25)) == 0) {
2561 if (insn
& (1 << 20)) {
2565 /* mcrr. Used for block cache operations, so implement as no-op. */
2568 if ((insn
& (1 << 4)) == 0) {
2572 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2575 if ((insn
& 0x0fff0fff) == 0x0e070f90
2576 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2577 /* Wait for interrupt. */
2578 gen_set_pc_im(s
->pc
);
2579 s
->is_jmp
= DISAS_WFI
;
2582 rd
= (insn
>> 12) & 0xf;
2583 if (insn
& ARM_CP_RW_BIT
) {
2585 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2586 /* If the destination register is r15 then sets condition codes. */
2588 store_reg(s
, rd
, tmp
);
2592 tmp
= load_reg(s
, rd
);
2593 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2595 /* Normally we would always end the TB here, but Linux
2596 * arch/arm/mach-pxa/sleep.S expects two instructions following
2597 * an MMU enable to execute from cache. Imitate this behaviour. */
2598 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2599 (insn
& 0x0fff0fff) != 0x0e010f10)
2605 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2606 #define VFP_SREG(insn, bigbit, smallbit) \
2607 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2608 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2609 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2610 reg = (((insn) >> (bigbit)) & 0x0f) \
2611 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2613 if (insn & (1 << (smallbit))) \
2615 reg = ((insn) >> (bigbit)) & 0x0f; \
2618 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2619 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2620 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2621 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2622 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2623 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2625 /* Move between integer and VFP cores. */
2626 static TCGv
gen_vfp_mrs(void)
2628 TCGv tmp
= new_tmp();
2629 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2633 static void gen_vfp_msr(TCGv tmp
)
2635 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2640 vfp_enabled(CPUState
* env
)
2642 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2645 static void gen_neon_dup_u8(TCGv var
, int shift
)
2647 TCGv tmp
= new_tmp();
2649 tcg_gen_shri_i32(var
, var
, shift
);
2650 tcg_gen_ext8u_i32(var
, var
);
2651 tcg_gen_shli_i32(tmp
, var
, 8);
2652 tcg_gen_or_i32(var
, var
, tmp
);
2653 tcg_gen_shli_i32(tmp
, var
, 16);
2654 tcg_gen_or_i32(var
, var
, tmp
);
2658 static void gen_neon_dup_low16(TCGv var
)
2660 TCGv tmp
= new_tmp();
2661 tcg_gen_ext16u_i32(var
, var
);
2662 tcg_gen_shli_i32(tmp
, var
, 16);
2663 tcg_gen_or_i32(var
, var
, tmp
);
2667 static void gen_neon_dup_high16(TCGv var
)
2669 TCGv tmp
= new_tmp();
2670 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2671 tcg_gen_shri_i32(tmp
, var
, 16);
2672 tcg_gen_or_i32(var
, var
, tmp
);
2676 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2677 (ie. an undefined instruction). */
2678 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2680 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2685 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2688 if (!vfp_enabled(env
)) {
2689 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2690 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2692 rn
= (insn
>> 16) & 0xf;
2693 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2694 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2697 dp
= ((insn
& 0xf00) == 0xb00);
2698 switch ((insn
>> 24) & 0xf) {
2700 if (insn
& (1 << 4)) {
2701 /* single register transfer */
2702 rd
= (insn
>> 12) & 0xf;
2707 VFP_DREG_N(rn
, insn
);
2710 if (insn
& 0x00c00060
2711 && !arm_feature(env
, ARM_FEATURE_NEON
))
2714 pass
= (insn
>> 21) & 1;
2715 if (insn
& (1 << 22)) {
2717 offset
= ((insn
>> 5) & 3) * 8;
2718 } else if (insn
& (1 << 5)) {
2720 offset
= (insn
& (1 << 6)) ? 16 : 0;
2725 if (insn
& ARM_CP_RW_BIT
) {
2727 tmp
= neon_load_reg(rn
, pass
);
2731 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2732 if (insn
& (1 << 23))
2738 if (insn
& (1 << 23)) {
2740 tcg_gen_shri_i32(tmp
, tmp
, 16);
2746 tcg_gen_sari_i32(tmp
, tmp
, 16);
2755 store_reg(s
, rd
, tmp
);
2758 tmp
= load_reg(s
, rd
);
2759 if (insn
& (1 << 23)) {
2762 gen_neon_dup_u8(tmp
, 0);
2763 } else if (size
== 1) {
2764 gen_neon_dup_low16(tmp
);
2766 for (n
= 0; n
<= pass
* 2; n
++) {
2768 tcg_gen_mov_i32(tmp2
, tmp
);
2769 neon_store_reg(rn
, n
, tmp2
);
2771 neon_store_reg(rn
, n
, tmp
);
2776 tmp2
= neon_load_reg(rn
, pass
);
2777 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2781 tmp2
= neon_load_reg(rn
, pass
);
2782 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2788 neon_store_reg(rn
, pass
, tmp
);
2792 if ((insn
& 0x6f) != 0x00)
2794 rn
= VFP_SREG_N(insn
);
2795 if (insn
& ARM_CP_RW_BIT
) {
2797 if (insn
& (1 << 21)) {
2798 /* system register */
2803 /* VFP2 allows access to FSID from userspace.
2804 VFP3 restricts all id registers to privileged
2807 && arm_feature(env
, ARM_FEATURE_VFP3
))
2809 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2814 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2816 case ARM_VFP_FPINST
:
2817 case ARM_VFP_FPINST2
:
2818 /* Not present in VFP3. */
2820 || arm_feature(env
, ARM_FEATURE_VFP3
))
2822 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2826 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2827 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2830 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2836 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2838 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2844 gen_mov_F0_vreg(0, rn
);
2845 tmp
= gen_vfp_mrs();
2848 /* Set the 4 flag bits in the CPSR. */
2852 store_reg(s
, rd
, tmp
);
2856 tmp
= load_reg(s
, rd
);
2857 if (insn
& (1 << 21)) {
2859 /* system register */
2864 /* Writes are ignored. */
2867 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2874 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2877 case ARM_VFP_FPINST
:
2878 case ARM_VFP_FPINST2
:
2879 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2886 gen_mov_vreg_F0(0, rn
);
2891 /* data processing */
2892 /* The opcode is in bits 23, 21, 20 and 6. */
2893 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2897 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2899 /* rn is register number */
2900 VFP_DREG_N(rn
, insn
);
2903 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2904 /* Integer or single precision destination. */
2905 rd
= VFP_SREG_D(insn
);
2907 VFP_DREG_D(rd
, insn
);
2910 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2911 /* Integer source. */
2912 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2914 VFP_DREG_M(rm
, insn
);
2917 rn
= VFP_SREG_N(insn
);
2918 if (op
== 15 && rn
== 15) {
2919 /* Double precision destination. */
2920 VFP_DREG_D(rd
, insn
);
2922 rd
= VFP_SREG_D(insn
);
2924 rm
= VFP_SREG_M(insn
);
2927 veclen
= env
->vfp
.vec_len
;
2928 if (op
== 15 && rn
> 3)
2931 /* Shut up compiler warnings. */
2942 /* Figure out what type of vector operation this is. */
2943 if ((rd
& bank_mask
) == 0) {
2948 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2950 delta_d
= env
->vfp
.vec_stride
+ 1;
2952 if ((rm
& bank_mask
) == 0) {
2953 /* mixed scalar/vector */
2962 /* Load the initial operands. */
2967 /* Integer source */
2968 gen_mov_F0_vreg(0, rm
);
2973 gen_mov_F0_vreg(dp
, rd
);
2974 gen_mov_F1_vreg(dp
, rm
);
2978 /* Compare with zero */
2979 gen_mov_F0_vreg(dp
, rd
);
2990 /* Source and destination the same. */
2991 gen_mov_F0_vreg(dp
, rd
);
2994 /* One source operand. */
2995 gen_mov_F0_vreg(dp
, rm
);
2999 /* Two source operands. */
3000 gen_mov_F0_vreg(dp
, rn
);
3001 gen_mov_F1_vreg(dp
, rm
);
3005 /* Perform the calculation. */
3007 case 0: /* mac: fd + (fn * fm) */
3009 gen_mov_F1_vreg(dp
, rd
);
3012 case 1: /* nmac: fd - (fn * fm) */
3015 gen_mov_F1_vreg(dp
, rd
);
3018 case 2: /* msc: -fd + (fn * fm) */
3020 gen_mov_F1_vreg(dp
, rd
);
3023 case 3: /* nmsc: -fd - (fn * fm) */
3026 gen_mov_F1_vreg(dp
, rd
);
3029 case 4: /* mul: fn * fm */
3032 case 5: /* nmul: -(fn * fm) */
3036 case 6: /* add: fn + fm */
3039 case 7: /* sub: fn - fm */
3042 case 8: /* div: fn / fm */
3045 case 14: /* fconst */
3046 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3049 n
= (insn
<< 12) & 0x80000000;
3050 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3057 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3064 tcg_gen_movi_i32(cpu_F0s
, n
);
3067 case 15: /* extension space */
3090 case 11: /* cmpez */
3094 case 15: /* single<->double conversion */
3096 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3098 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3100 case 16: /* fuito */
3103 case 17: /* fsito */
3106 case 20: /* fshto */
3107 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3109 gen_vfp_shto(dp
, 16 - rm
);
3111 case 21: /* fslto */
3112 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3114 gen_vfp_slto(dp
, 32 - rm
);
3116 case 22: /* fuhto */
3117 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3119 gen_vfp_uhto(dp
, 16 - rm
);
3121 case 23: /* fulto */
3122 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3124 gen_vfp_ulto(dp
, 32 - rm
);
3126 case 24: /* ftoui */
3129 case 25: /* ftouiz */
3132 case 26: /* ftosi */
3135 case 27: /* ftosiz */
3138 case 28: /* ftosh */
3139 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3141 gen_vfp_tosh(dp
, 16 - rm
);
3143 case 29: /* ftosl */
3144 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3146 gen_vfp_tosl(dp
, 32 - rm
);
3148 case 30: /* ftouh */
3149 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3151 gen_vfp_touh(dp
, 16 - rm
);
3153 case 31: /* ftoul */
3154 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3156 gen_vfp_toul(dp
, 32 - rm
);
3158 default: /* undefined */
3159 printf ("rn:%d\n", rn
);
3163 default: /* undefined */
3164 printf ("op:%d\n", op
);
3168 /* Write back the result. */
3169 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3170 ; /* Comparison, do nothing. */
3171 else if (op
== 15 && rn
> 17)
3172 /* Integer result. */
3173 gen_mov_vreg_F0(0, rd
);
3174 else if (op
== 15 && rn
== 15)
3176 gen_mov_vreg_F0(!dp
, rd
);
3178 gen_mov_vreg_F0(dp
, rd
);
3180 /* break out of the loop if we have finished */
3184 if (op
== 15 && delta_m
== 0) {
3185 /* single source one-many */
3187 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3189 gen_mov_vreg_F0(dp
, rd
);
3193 /* Setup the next operands. */
3195 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3199 /* One source operand. */
3200 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3202 gen_mov_F0_vreg(dp
, rm
);
3204 /* Two source operands. */
3205 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3207 gen_mov_F0_vreg(dp
, rn
);
3209 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3211 gen_mov_F1_vreg(dp
, rm
);
3219 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3220 /* two-register transfer */
3221 rn
= (insn
>> 16) & 0xf;
3222 rd
= (insn
>> 12) & 0xf;
3224 VFP_DREG_M(rm
, insn
);
3226 rm
= VFP_SREG_M(insn
);
3229 if (insn
& ARM_CP_RW_BIT
) {
3232 gen_mov_F0_vreg(0, rm
* 2);
3233 tmp
= gen_vfp_mrs();
3234 store_reg(s
, rd
, tmp
);
3235 gen_mov_F0_vreg(0, rm
* 2 + 1);
3236 tmp
= gen_vfp_mrs();
3237 store_reg(s
, rn
, tmp
);
3239 gen_mov_F0_vreg(0, rm
);
3240 tmp
= gen_vfp_mrs();
3241 store_reg(s
, rn
, tmp
);
3242 gen_mov_F0_vreg(0, rm
+ 1);
3243 tmp
= gen_vfp_mrs();
3244 store_reg(s
, rd
, tmp
);
3249 tmp
= load_reg(s
, rd
);
3251 gen_mov_vreg_F0(0, rm
* 2);
3252 tmp
= load_reg(s
, rn
);
3254 gen_mov_vreg_F0(0, rm
* 2 + 1);
3256 tmp
= load_reg(s
, rn
);
3258 gen_mov_vreg_F0(0, rm
);
3259 tmp
= load_reg(s
, rd
);
3261 gen_mov_vreg_F0(0, rm
+ 1);
3266 rn
= (insn
>> 16) & 0xf;
3268 VFP_DREG_D(rd
, insn
);
3270 rd
= VFP_SREG_D(insn
);
3271 if (s
->thumb
&& rn
== 15) {
3272 gen_op_movl_T1_im(s
->pc
& ~2);
3274 gen_movl_T1_reg(s
, rn
);
3276 if ((insn
& 0x01200000) == 0x01000000) {
3277 /* Single load/store */
3278 offset
= (insn
& 0xff) << 2;
3279 if ((insn
& (1 << 23)) == 0)
3281 gen_op_addl_T1_im(offset
);
3282 if (insn
& (1 << 20)) {
3284 gen_mov_vreg_F0(dp
, rd
);
3286 gen_mov_F0_vreg(dp
, rd
);
3290 /* load/store multiple */
3292 n
= (insn
>> 1) & 0x7f;
3296 if (insn
& (1 << 24)) /* pre-decrement */
3297 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3303 for (i
= 0; i
< n
; i
++) {
3304 if (insn
& ARM_CP_RW_BIT
) {
3307 gen_mov_vreg_F0(dp
, rd
+ i
);
3310 gen_mov_F0_vreg(dp
, rd
+ i
);
3313 gen_op_addl_T1_im(offset
);
3315 if (insn
& (1 << 21)) {
3317 if (insn
& (1 << 24))
3318 offset
= -offset
* n
;
3319 else if (dp
&& (insn
& 1))
3325 gen_op_addl_T1_im(offset
);
3326 gen_movl_reg_T1(s
, rn
);
3332 /* Should never happen. */
3338 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3340 TranslationBlock
*tb
;
3343 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3345 gen_set_pc_im(dest
);
3346 tcg_gen_exit_tb((long)tb
+ n
);
3348 gen_set_pc_im(dest
);
3353 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3355 if (unlikely(s
->singlestep_enabled
)) {
3356 /* An indirect jump so that we still trigger the debug exception. */
3361 gen_goto_tb(s
, 0, dest
);
3362 s
->is_jmp
= DISAS_TB_JUMP
;
3366 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3369 tcg_gen_sari_i32(t0
, t0
, 16);
3373 tcg_gen_sari_i32(t1
, t1
, 16);
3376 tcg_gen_mul_i32(t0
, t0
, t1
);
3379 /* Return the mask of PSR bits set by a MSR instruction. */
3380 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3384 if (flags
& (1 << 0))
3386 if (flags
& (1 << 1))
3388 if (flags
& (1 << 2))
3390 if (flags
& (1 << 3))
3393 /* Mask out undefined bits. */
3394 mask
&= ~CPSR_RESERVED
;
3395 if (!arm_feature(env
, ARM_FEATURE_V6
))
3396 mask
&= ~(CPSR_E
| CPSR_GE
);
3397 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3399 /* Mask out execution state bits. */
3402 /* Mask out privileged bits. */
3408 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3409 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3413 /* ??? This is also undefined in system mode. */
3417 tmp
= load_cpu_field(spsr
);
3418 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3419 tcg_gen_andi_i32(t0
, t0
, mask
);
3420 tcg_gen_or_i32(tmp
, tmp
, t0
);
3421 store_cpu_field(tmp
, spsr
);
3423 gen_set_cpsr(t0
, mask
);
3430 /* Returns nonzero if access to the PSR is not permitted. */
3431 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3435 tcg_gen_movi_i32(tmp
, val
);
3436 return gen_set_psr(s
, mask
, spsr
, tmp
);
3439 /* Generate an old-style exception return. Marks pc as dead. */
3440 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3443 store_reg(s
, 15, pc
);
3444 tmp
= load_cpu_field(spsr
);
3445 gen_set_cpsr(tmp
, 0xffffffff);
3447 s
->is_jmp
= DISAS_UPDATE
;
3450 /* Generate a v6 exception return. Marks both values as dead. */
3451 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3453 gen_set_cpsr(cpsr
, 0xffffffff);
3455 store_reg(s
, 15, pc
);
3456 s
->is_jmp
= DISAS_UPDATE
;
3460 gen_set_condexec (DisasContext
*s
)
3462 if (s
->condexec_mask
) {
3463 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3464 TCGv tmp
= new_tmp();
3465 tcg_gen_movi_i32(tmp
, val
);
3466 store_cpu_field(tmp
, condexec_bits
);
3470 static void gen_nop_hint(DisasContext
*s
, int val
)
3474 gen_set_pc_im(s
->pc
);
3475 s
->is_jmp
= DISAS_WFI
;
3479 /* TODO: Implement SEV and WFE. May help SMP performance. */
3485 /* These macros help make the code more readable when migrating from the
3486 old dyngen helpers. They should probably be removed when
3487 T0/T1 are removed. */
3488 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3489 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3491 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3493 static inline int gen_neon_add(int size
)
3496 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3497 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3498 case 2: gen_op_addl_T0_T1(); break;
3504 static inline void gen_neon_rsb(int size
)
3507 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3508 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3509 case 2: gen_op_rsbl_T0_T1(); break;
3514 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3515 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3516 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3517 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3518 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3520 /* FIXME: This is wrong. They set the wrong overflow bit. */
3521 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3522 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3523 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3524 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3526 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3527 switch ((size << 1) | u) { \
3529 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3532 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3535 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3538 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3541 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3544 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3546 default: return 1; \
3549 #define GEN_NEON_INTEGER_OP(name) do { \
3550 switch ((size << 1) | u) { \
3552 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3555 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3558 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3561 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3564 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3567 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3569 default: return 1; \
3573 gen_neon_movl_scratch_T0(int scratch
)
3577 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3578 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3582 gen_neon_movl_scratch_T1(int scratch
)
3586 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3587 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3591 gen_neon_movl_T0_scratch(int scratch
)
3595 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3596 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3600 gen_neon_movl_T1_scratch(int scratch
)
3604 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3605 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3608 static inline void gen_neon_get_scalar(int size
, int reg
)
3611 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3613 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3615 gen_neon_dup_low16(cpu_T
[0]);
3617 gen_neon_dup_high16(cpu_T
[0]);
3621 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3629 tcg_gen_andi_i32(rd
, t0
, 0xff);
3630 tcg_gen_shri_i32(tmp
, t0
, 8);
3631 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3632 tcg_gen_or_i32(rd
, rd
, tmp
);
3633 tcg_gen_shli_i32(tmp
, t1
, 16);
3634 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3635 tcg_gen_or_i32(rd
, rd
, tmp
);
3636 tcg_gen_shli_i32(tmp
, t1
, 8);
3637 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3638 tcg_gen_or_i32(rd
, rd
, tmp
);
3640 tcg_gen_shri_i32(rm
, t0
, 8);
3641 tcg_gen_andi_i32(rm
, rm
, 0xff);
3642 tcg_gen_shri_i32(tmp
, t0
, 16);
3643 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3644 tcg_gen_or_i32(rm
, rm
, tmp
);
3645 tcg_gen_shli_i32(tmp
, t1
, 8);
3646 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3647 tcg_gen_or_i32(rm
, rm
, tmp
);
3648 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3649 tcg_gen_or_i32(t1
, rm
, tmp
);
3650 tcg_gen_mov_i32(t0
, rd
);
3657 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3665 tcg_gen_andi_i32(rd
, t0
, 0xff);
3666 tcg_gen_shli_i32(tmp
, t1
, 8);
3667 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3668 tcg_gen_or_i32(rd
, rd
, tmp
);
3669 tcg_gen_shli_i32(tmp
, t0
, 16);
3670 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3671 tcg_gen_or_i32(rd
, rd
, tmp
);
3672 tcg_gen_shli_i32(tmp
, t1
, 24);
3673 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3674 tcg_gen_or_i32(rd
, rd
, tmp
);
3676 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3677 tcg_gen_shri_i32(tmp
, t0
, 8);
3678 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3679 tcg_gen_or_i32(rm
, rm
, tmp
);
3680 tcg_gen_shri_i32(tmp
, t1
, 8);
3681 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3682 tcg_gen_or_i32(rm
, rm
, tmp
);
3683 tcg_gen_shri_i32(tmp
, t0
, 16);
3684 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3685 tcg_gen_or_i32(t1
, rm
, tmp
);
3686 tcg_gen_mov_i32(t0
, rd
);
3693 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3700 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3701 tcg_gen_shli_i32(tmp2
, t1
, 16);
3702 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3703 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3704 tcg_gen_shri_i32(tmp2
, t0
, 16);
3705 tcg_gen_or_i32(t1
, t1
, tmp2
);
3706 tcg_gen_mov_i32(t0
, tmp
);
3712 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3716 for (n
= 0; n
< q
+ 1; n
+= 2) {
3717 NEON_GET_REG(T0
, reg
, n
);
3718 NEON_GET_REG(T1
, reg
, n
+ 1);
3720 case 0: gen_neon_unzip_u8(cpu_T
[0], cpu_T
[1]); break;
3721 case 1: gen_neon_zip_u16(cpu_T
[0], cpu_T
[1]); break; /* zip and unzip are the same. */
3722 case 2: /* no-op */; break;
3725 gen_neon_movl_T0_scratch(tmp
+ n
);
3726 gen_neon_movl_T1_scratch(tmp
+ n
+ 1);
3730 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3737 tcg_gen_shli_i32(rd
, t0
, 8);
3738 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3739 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3740 tcg_gen_or_i32(rd
, rd
, tmp
);
3742 tcg_gen_shri_i32(t1
, t1
, 8);
3743 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3744 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3745 tcg_gen_or_i32(t1
, t1
, tmp
);
3746 tcg_gen_mov_i32(t0
, rd
);
3752 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3759 tcg_gen_shli_i32(rd
, t0
, 16);
3760 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3761 tcg_gen_or_i32(rd
, rd
, tmp
);
3762 tcg_gen_shri_i32(t1
, t1
, 16);
3763 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3764 tcg_gen_or_i32(t1
, t1
, tmp
);
3765 tcg_gen_mov_i32(t0
, rd
);
3776 } neon_ls_element_type
[11] = {
3790 /* Translate a NEON load/store element instruction. Return nonzero if the
3791 instruction is invalid. */
3792 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3808 if (!vfp_enabled(env
))
3810 VFP_DREG_D(rd
, insn
);
3811 rn
= (insn
>> 16) & 0xf;
3813 load
= (insn
& (1 << 21)) != 0;
3814 if ((insn
& (1 << 23)) == 0) {
3815 /* Load store all elements. */
3816 op
= (insn
>> 8) & 0xf;
3817 size
= (insn
>> 6) & 3;
3818 if (op
> 10 || size
== 3)
3820 nregs
= neon_ls_element_type
[op
].nregs
;
3821 interleave
= neon_ls_element_type
[op
].interleave
;
3822 gen_movl_T1_reg(s
, rn
);
3823 stride
= (1 << size
) * interleave
;
3824 for (reg
= 0; reg
< nregs
; reg
++) {
3825 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3826 gen_movl_T1_reg(s
, rn
);
3827 gen_op_addl_T1_im((1 << size
) * reg
);
3828 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3829 gen_movl_T1_reg(s
, rn
);
3830 gen_op_addl_T1_im(1 << size
);
3832 for (pass
= 0; pass
< 2; pass
++) {
3835 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3836 neon_store_reg(rd
, pass
, tmp
);
3838 tmp
= neon_load_reg(rd
, pass
);
3839 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3841 gen_op_addl_T1_im(stride
);
3842 } else if (size
== 1) {
3844 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3845 gen_op_addl_T1_im(stride
);
3846 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3847 gen_op_addl_T1_im(stride
);
3848 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3850 neon_store_reg(rd
, pass
, tmp
);
3852 tmp
= neon_load_reg(rd
, pass
);
3854 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3855 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3856 gen_op_addl_T1_im(stride
);
3857 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3858 gen_op_addl_T1_im(stride
);
3860 } else /* size == 0 */ {
3863 for (n
= 0; n
< 4; n
++) {
3864 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3865 gen_op_addl_T1_im(stride
);
3869 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3873 neon_store_reg(rd
, pass
, tmp2
);
3875 tmp2
= neon_load_reg(rd
, pass
);
3876 for (n
= 0; n
< 4; n
++) {
3879 tcg_gen_mov_i32(tmp
, tmp2
);
3881 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3883 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3884 gen_op_addl_T1_im(stride
);
3890 rd
+= neon_ls_element_type
[op
].spacing
;
3894 size
= (insn
>> 10) & 3;
3896 /* Load single element to all lanes. */
3899 size
= (insn
>> 6) & 3;
3900 nregs
= ((insn
>> 8) & 3) + 1;
3901 stride
= (insn
& (1 << 5)) ? 2 : 1;
3902 gen_movl_T1_reg(s
, rn
);
3903 for (reg
= 0; reg
< nregs
; reg
++) {
3906 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3907 gen_neon_dup_u8(tmp
, 0);
3910 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3911 gen_neon_dup_low16(tmp
);
3914 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3918 default: /* Avoid compiler warnings. */
3921 gen_op_addl_T1_im(1 << size
);
3923 tcg_gen_mov_i32(tmp2
, tmp
);
3924 neon_store_reg(rd
, 0, tmp2
);
3925 neon_store_reg(rd
, 1, tmp
);
3928 stride
= (1 << size
) * nregs
;
3930 /* Single element. */
3931 pass
= (insn
>> 7) & 1;
3934 shift
= ((insn
>> 5) & 3) * 8;
3938 shift
= ((insn
>> 6) & 1) * 16;
3939 stride
= (insn
& (1 << 5)) ? 2 : 1;
3943 stride
= (insn
& (1 << 6)) ? 2 : 1;
3948 nregs
= ((insn
>> 8) & 3) + 1;
3949 gen_movl_T1_reg(s
, rn
);
3950 for (reg
= 0; reg
< nregs
; reg
++) {
3954 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3957 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3960 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3962 default: /* Avoid compiler warnings. */
3966 tmp2
= neon_load_reg(rd
, pass
);
3967 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3970 neon_store_reg(rd
, pass
, tmp
);
3971 } else { /* Store */
3972 tmp
= neon_load_reg(rd
, pass
);
3974 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3977 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3980 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3983 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3988 gen_op_addl_T1_im(1 << size
);
3990 stride
= nregs
* (1 << size
);
3996 base
= load_reg(s
, rn
);
3998 tcg_gen_addi_i32(base
, base
, stride
);
4001 index
= load_reg(s
, rm
);
4002 tcg_gen_add_i32(base
, base
, index
);
4005 store_reg(s
, rn
, base
);
4010 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4011 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
4013 tcg_gen_and_i32(t
, t
, c
);
4014 tcg_gen_bic_i32(f
, f
, c
);
4015 tcg_gen_or_i32(dest
, t
, f
);
4018 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
4021 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4022 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4023 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4028 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
4031 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4032 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4033 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4038 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
4041 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4042 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4043 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4048 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
4054 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4055 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4060 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4061 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4068 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4069 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4074 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4075 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4082 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
4086 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4087 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4088 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4093 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4094 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4095 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4102 static inline void gen_neon_addl(int size
)
4105 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4106 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4107 case 2: tcg_gen_add_i64(CPU_V001
); break;
4112 static inline void gen_neon_subl(int size
)
4115 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4116 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4117 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4122 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4125 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4126 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4127 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4132 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4135 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4136 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4141 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4145 switch ((size
<< 1) | u
) {
4146 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4147 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4148 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4149 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4151 tmp
= gen_muls_i64_i32(a
, b
);
4152 tcg_gen_mov_i64(dest
, tmp
);
4155 tmp
= gen_mulu_i64_i32(a
, b
);
4156 tcg_gen_mov_i64(dest
, tmp
);
4166 /* Translate a NEON data processing instruction. Return nonzero if the
4167 instruction is invalid.
4168 We process data in a mixture of 32-bit and 64-bit chunks.
4169 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4171 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4189 if (!vfp_enabled(env
))
4191 q
= (insn
& (1 << 6)) != 0;
4192 u
= (insn
>> 24) & 1;
4193 VFP_DREG_D(rd
, insn
);
4194 VFP_DREG_N(rn
, insn
);
4195 VFP_DREG_M(rm
, insn
);
4196 size
= (insn
>> 20) & 3;
4197 if ((insn
& (1 << 23)) == 0) {
4198 /* Three register same length. */
4199 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4200 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4201 || op
== 10 || op
== 11 || op
== 16)) {
4202 /* 64-bit element instructions. */
4203 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4204 neon_load_reg64(cpu_V0
, rn
+ pass
);
4205 neon_load_reg64(cpu_V1
, rm
+ pass
);
4209 gen_helper_neon_add_saturate_u64(CPU_V001
);
4211 gen_helper_neon_add_saturate_s64(CPU_V001
);
4216 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4218 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4223 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4225 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4230 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4233 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4237 case 10: /* VRSHL */
4239 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4241 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4244 case 11: /* VQRSHL */
4246 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4249 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4255 tcg_gen_sub_i64(CPU_V001
);
4257 tcg_gen_add_i64(CPU_V001
);
4263 neon_store_reg64(cpu_V0
, rd
+ pass
);
4270 case 10: /* VRSHL */
4271 case 11: /* VQRSHL */
4274 /* Shift instruction operands are reversed. */
4281 case 20: /* VPMAX */
4282 case 21: /* VPMIN */
4283 case 23: /* VPADD */
4286 case 26: /* VPADD (float) */
4287 pairwise
= (u
&& size
< 2);
4289 case 30: /* VPMIN/VPMAX (float) */
4296 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4305 NEON_GET_REG(T0
, rn
, n
);
4306 NEON_GET_REG(T1
, rn
, n
+ 1);
4308 NEON_GET_REG(T0
, rm
, n
);
4309 NEON_GET_REG(T1
, rm
, n
+ 1);
4313 NEON_GET_REG(T0
, rn
, pass
);
4314 NEON_GET_REG(T1
, rm
, pass
);
4318 GEN_NEON_INTEGER_OP(hadd
);
4321 GEN_NEON_INTEGER_OP_ENV(qadd
);
4323 case 2: /* VRHADD */
4324 GEN_NEON_INTEGER_OP(rhadd
);
4326 case 3: /* Logic ops. */
4327 switch ((u
<< 2) | size
) {
4329 gen_op_andl_T0_T1();
4332 gen_op_bicl_T0_T1();
4342 gen_op_xorl_T0_T1();
4345 tmp
= neon_load_reg(rd
, pass
);
4346 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4350 tmp
= neon_load_reg(rd
, pass
);
4351 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4355 tmp
= neon_load_reg(rd
, pass
);
4356 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4362 GEN_NEON_INTEGER_OP(hsub
);
4365 GEN_NEON_INTEGER_OP_ENV(qsub
);
4368 GEN_NEON_INTEGER_OP(cgt
);
4371 GEN_NEON_INTEGER_OP(cge
);
4374 GEN_NEON_INTEGER_OP(shl
);
4377 GEN_NEON_INTEGER_OP_ENV(qshl
);
4379 case 10: /* VRSHL */
4380 GEN_NEON_INTEGER_OP(rshl
);
4382 case 11: /* VQRSHL */
4383 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4386 GEN_NEON_INTEGER_OP(max
);
4389 GEN_NEON_INTEGER_OP(min
);
4392 GEN_NEON_INTEGER_OP(abd
);
4395 GEN_NEON_INTEGER_OP(abd
);
4396 NEON_GET_REG(T1
, rd
, pass
);
4400 if (!u
) { /* VADD */
4401 if (gen_neon_add(size
))
4405 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4406 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4407 case 2: gen_op_subl_T0_T1(); break;
4413 if (!u
) { /* VTST */
4415 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4416 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4417 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4422 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4423 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4424 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4429 case 18: /* Multiply. */
4431 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4432 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4433 case 2: gen_op_mul_T0_T1(); break;
4436 NEON_GET_REG(T1
, rd
, pass
);
4444 if (u
) { /* polynomial */
4445 gen_helper_neon_mul_p8(CPU_T001
);
4446 } else { /* Integer */
4448 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4449 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4450 case 2: gen_op_mul_T0_T1(); break;
4455 case 20: /* VPMAX */
4456 GEN_NEON_INTEGER_OP(pmax
);
4458 case 21: /* VPMIN */
4459 GEN_NEON_INTEGER_OP(pmin
);
4461 case 22: /* Hultiply high. */
4462 if (!u
) { /* VQDMULH */
4464 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4465 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4468 } else { /* VQRDHMUL */
4470 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4471 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4476 case 23: /* VPADD */
4480 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4481 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4482 case 2: gen_op_addl_T0_T1(); break;
4486 case 26: /* Floating point arithnetic. */
4487 switch ((u
<< 2) | size
) {
4489 gen_helper_neon_add_f32(CPU_T001
);
4492 gen_helper_neon_sub_f32(CPU_T001
);
4495 gen_helper_neon_add_f32(CPU_T001
);
4498 gen_helper_neon_abd_f32(CPU_T001
);
4504 case 27: /* Float multiply. */
4505 gen_helper_neon_mul_f32(CPU_T001
);
4507 NEON_GET_REG(T1
, rd
, pass
);
4509 gen_helper_neon_add_f32(CPU_T001
);
4511 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4515 case 28: /* Float compare. */
4517 gen_helper_neon_ceq_f32(CPU_T001
);
4520 gen_helper_neon_cge_f32(CPU_T001
);
4522 gen_helper_neon_cgt_f32(CPU_T001
);
4525 case 29: /* Float compare absolute. */
4529 gen_helper_neon_acge_f32(CPU_T001
);
4531 gen_helper_neon_acgt_f32(CPU_T001
);
4533 case 30: /* Float min/max. */
4535 gen_helper_neon_max_f32(CPU_T001
);
4537 gen_helper_neon_min_f32(CPU_T001
);
4541 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4543 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4548 /* Save the result. For elementwise operations we can put it
4549 straight into the destination register. For pairwise operations
4550 we have to be careful to avoid clobbering the source operands. */
4551 if (pairwise
&& rd
== rm
) {
4552 gen_neon_movl_scratch_T0(pass
);
4554 NEON_SET_REG(T0
, rd
, pass
);
4558 if (pairwise
&& rd
== rm
) {
4559 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4560 gen_neon_movl_T0_scratch(pass
);
4561 NEON_SET_REG(T0
, rd
, pass
);
4564 /* End of 3 register same size operations. */
4565 } else if (insn
& (1 << 4)) {
4566 if ((insn
& 0x00380080) != 0) {
4567 /* Two registers and shift. */
4568 op
= (insn
>> 8) & 0xf;
4569 if (insn
& (1 << 7)) {
4574 while ((insn
& (1 << (size
+ 19))) == 0)
4577 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4578 /* To avoid excessive dumplication of ops we implement shift
4579 by immediate using the variable shift operations. */
4581 /* Shift by immediate:
4582 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4583 /* Right shifts are encoded as N - shift, where N is the
4584 element size in bits. */
4586 shift
= shift
- (1 << (size
+ 3));
4594 imm
= (uint8_t) shift
;
4599 imm
= (uint16_t) shift
;
4610 for (pass
= 0; pass
< count
; pass
++) {
4612 neon_load_reg64(cpu_V0
, rm
+ pass
);
4613 tcg_gen_movi_i64(cpu_V1
, imm
);
4618 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4620 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4625 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4627 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4632 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4634 case 5: /* VSHL, VSLI */
4635 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4639 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4641 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4643 case 7: /* VQSHLU */
4644 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4647 if (op
== 1 || op
== 3) {
4649 neon_load_reg64(cpu_V0
, rd
+ pass
);
4650 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4651 } else if (op
== 4 || (op
== 5 && u
)) {
4653 cpu_abort(env
, "VS[LR]I.64 not implemented");
4655 neon_store_reg64(cpu_V0
, rd
+ pass
);
4656 } else { /* size < 3 */
4657 /* Operands in T0 and T1. */
4658 gen_op_movl_T1_im(imm
);
4659 NEON_GET_REG(T0
, rm
, pass
);
4663 GEN_NEON_INTEGER_OP(shl
);
4667 GEN_NEON_INTEGER_OP(rshl
);
4672 GEN_NEON_INTEGER_OP(shl
);
4674 case 5: /* VSHL, VSLI */
4676 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4677 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4678 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4683 GEN_NEON_INTEGER_OP_ENV(qshl
);
4685 case 7: /* VQSHLU */
4687 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4688 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4689 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4695 if (op
== 1 || op
== 3) {
4697 NEON_GET_REG(T1
, rd
, pass
);
4699 } else if (op
== 4 || (op
== 5 && u
)) {
4704 imm
= 0xff >> -shift
;
4706 imm
= (uint8_t)(0xff << shift
);
4712 imm
= 0xffff >> -shift
;
4714 imm
= (uint16_t)(0xffff << shift
);
4719 imm
= 0xffffffffu
>> -shift
;
4721 imm
= 0xffffffffu
<< shift
;
4726 tmp
= neon_load_reg(rd
, pass
);
4727 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4728 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4729 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4731 NEON_SET_REG(T0
, rd
, pass
);
4734 } else if (op
< 10) {
4735 /* Shift by immediate and narrow:
4736 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4737 shift
= shift
- (1 << (size
+ 3));
4741 imm
= (uint16_t)shift
;
4743 tmp2
= tcg_const_i32(imm
);
4744 TCGV_UNUSED_I64(tmp64
);
4747 imm
= (uint32_t)shift
;
4748 tmp2
= tcg_const_i32(imm
);
4749 TCGV_UNUSED_I64(tmp64
);
4752 tmp64
= tcg_const_i64(shift
);
4759 for (pass
= 0; pass
< 2; pass
++) {
4761 neon_load_reg64(cpu_V0
, rm
+ pass
);
4764 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4766 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4769 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4771 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4774 tmp
= neon_load_reg(rm
+ pass
, 0);
4775 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4776 tmp3
= neon_load_reg(rm
+ pass
, 1);
4777 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4778 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4783 if (op
== 8 && !u
) {
4784 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4787 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4789 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4794 neon_store_reg(rd
, 0, tmp2
);
4795 neon_store_reg(rd
, 1, tmp
);
4798 } else if (op
== 10) {
4802 tmp
= neon_load_reg(rm
, 0);
4803 tmp2
= neon_load_reg(rm
, 1);
4804 for (pass
= 0; pass
< 2; pass
++) {
4808 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4811 /* The shift is less than the width of the source
4812 type, so we can just shift the whole register. */
4813 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4814 if (size
< 2 || !u
) {
4817 imm
= (0xffu
>> (8 - shift
));
4820 imm
= 0xffff >> (16 - shift
);
4822 imm64
= imm
| (((uint64_t)imm
) << 32);
4823 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4826 neon_store_reg64(cpu_V0
, rd
+ pass
);
4828 } else if (op
== 15 || op
== 16) {
4829 /* VCVT fixed-point. */
4830 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4831 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4834 gen_vfp_ulto(0, shift
);
4836 gen_vfp_slto(0, shift
);
4839 gen_vfp_toul(0, shift
);
4841 gen_vfp_tosl(0, shift
);
4843 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4848 } else { /* (insn & 0x00380080) == 0 */
4851 op
= (insn
>> 8) & 0xf;
4852 /* One register and immediate. */
4853 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4854 invert
= (insn
& (1 << 5)) != 0;
4872 imm
= (imm
<< 8) | (imm
<< 24);
4875 imm
= (imm
< 8) | 0xff;
4878 imm
= (imm
<< 16) | 0xffff;
4881 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4886 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4887 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4893 if (op
!= 14 || !invert
)
4894 gen_op_movl_T1_im(imm
);
4896 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4897 if (op
& 1 && op
< 12) {
4898 tmp
= neon_load_reg(rd
, pass
);
4900 /* The immediate value has already been inverted, so
4902 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4904 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4909 if (op
== 14 && invert
) {
4912 for (n
= 0; n
< 4; n
++) {
4913 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4914 val
|= 0xff << (n
* 8);
4916 tcg_gen_movi_i32(tmp
, val
);
4918 tcg_gen_movi_i32(tmp
, imm
);
4921 neon_store_reg(rd
, pass
, tmp
);
4924 } else { /* (insn & 0x00800010 == 0x00800000) */
4926 op
= (insn
>> 8) & 0xf;
4927 if ((insn
& (1 << 6)) == 0) {
4928 /* Three registers of different lengths. */
4932 /* prewiden, src1_wide, src2_wide */
4933 static const int neon_3reg_wide
[16][3] = {
4934 {1, 0, 0}, /* VADDL */
4935 {1, 1, 0}, /* VADDW */
4936 {1, 0, 0}, /* VSUBL */
4937 {1, 1, 0}, /* VSUBW */
4938 {0, 1, 1}, /* VADDHN */
4939 {0, 0, 0}, /* VABAL */
4940 {0, 1, 1}, /* VSUBHN */
4941 {0, 0, 0}, /* VABDL */
4942 {0, 0, 0}, /* VMLAL */
4943 {0, 0, 0}, /* VQDMLAL */
4944 {0, 0, 0}, /* VMLSL */
4945 {0, 0, 0}, /* VQDMLSL */
4946 {0, 0, 0}, /* Integer VMULL */
4947 {0, 0, 0}, /* VQDMULL */
4948 {0, 0, 0} /* Polynomial VMULL */
4951 prewiden
= neon_3reg_wide
[op
][0];
4952 src1_wide
= neon_3reg_wide
[op
][1];
4953 src2_wide
= neon_3reg_wide
[op
][2];
4955 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4958 /* Avoid overlapping operands. Wide source operands are
4959 always aligned so will never overlap with wide
4960 destinations in problematic ways. */
4961 if (rd
== rm
&& !src2_wide
) {
4962 NEON_GET_REG(T0
, rm
, 1);
4963 gen_neon_movl_scratch_T0(2);
4964 } else if (rd
== rn
&& !src1_wide
) {
4965 NEON_GET_REG(T0
, rn
, 1);
4966 gen_neon_movl_scratch_T0(2);
4969 for (pass
= 0; pass
< 2; pass
++) {
4971 neon_load_reg64(cpu_V0
, rn
+ pass
);
4974 if (pass
== 1 && rd
== rn
) {
4975 gen_neon_movl_T0_scratch(2);
4977 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4979 tmp
= neon_load_reg(rn
, pass
);
4982 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4986 neon_load_reg64(cpu_V1
, rm
+ pass
);
4989 if (pass
== 1 && rd
== rm
) {
4990 gen_neon_movl_T0_scratch(2);
4992 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4994 tmp2
= neon_load_reg(rm
, pass
);
4997 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5001 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5002 gen_neon_addl(size
);
5004 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
5005 gen_neon_subl(size
);
5007 case 5: case 7: /* VABAL, VABDL */
5008 switch ((size
<< 1) | u
) {
5010 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5013 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5016 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5019 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5022 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5025 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5032 case 8: case 9: case 10: case 11: case 12: case 13:
5033 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5034 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5036 case 14: /* Polynomial VMULL */
5037 cpu_abort(env
, "Polynomial VMULL not implemented");
5039 default: /* 15 is RESERVED. */
5042 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
5044 if (op
== 10 || op
== 11) {
5045 gen_neon_negl(cpu_V0
, size
);
5049 neon_load_reg64(cpu_V1
, rd
+ pass
);
5053 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5054 gen_neon_addl(size
);
5056 case 9: case 11: /* VQDMLAL, VQDMLSL */
5057 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5058 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5061 case 13: /* VQDMULL */
5062 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5067 neon_store_reg64(cpu_V0
, rd
+ pass
);
5068 } else if (op
== 4 || op
== 6) {
5069 /* Narrowing operation. */
5074 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5077 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5080 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5081 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5088 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5091 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5094 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5095 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5096 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5104 neon_store_reg(rd
, 0, tmp3
);
5105 neon_store_reg(rd
, 1, tmp
);
5108 /* Write back the result. */
5109 neon_store_reg64(cpu_V0
, rd
+ pass
);
5113 /* Two registers and a scalar. */
5115 case 0: /* Integer VMLA scalar */
5116 case 1: /* Float VMLA scalar */
5117 case 4: /* Integer VMLS scalar */
5118 case 5: /* Floating point VMLS scalar */
5119 case 8: /* Integer VMUL scalar */
5120 case 9: /* Floating point VMUL scalar */
5121 case 12: /* VQDMULH scalar */
5122 case 13: /* VQRDMULH scalar */
5123 gen_neon_get_scalar(size
, rm
);
5124 gen_neon_movl_scratch_T0(0);
5125 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5127 gen_neon_movl_T0_scratch(0);
5128 NEON_GET_REG(T1
, rn
, pass
);
5131 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5133 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5135 } else if (op
== 13) {
5137 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5139 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5141 } else if (op
& 1) {
5142 gen_helper_neon_mul_f32(CPU_T001
);
5145 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5146 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5147 case 2: gen_op_mul_T0_T1(); break;
5153 NEON_GET_REG(T1
, rd
, pass
);
5159 gen_helper_neon_add_f32(CPU_T001
);
5165 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5171 NEON_SET_REG(T0
, rd
, pass
);
5174 case 2: /* VMLAL sclar */
5175 case 3: /* VQDMLAL scalar */
5176 case 6: /* VMLSL scalar */
5177 case 7: /* VQDMLSL scalar */
5178 case 10: /* VMULL scalar */
5179 case 11: /* VQDMULL scalar */
5180 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5183 gen_neon_get_scalar(size
, rm
);
5184 NEON_GET_REG(T1
, rn
, 1);
5186 for (pass
= 0; pass
< 2; pass
++) {
5188 tmp
= neon_load_reg(rn
, 0);
5191 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5194 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5195 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5196 if (op
== 6 || op
== 7) {
5197 gen_neon_negl(cpu_V0
, size
);
5200 neon_load_reg64(cpu_V1
, rd
+ pass
);
5204 gen_neon_addl(size
);
5207 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5208 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5214 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5219 neon_store_reg64(cpu_V0
, rd
+ pass
);
5222 default: /* 14 and 15 are RESERVED */
5226 } else { /* size == 3 */
5229 imm
= (insn
>> 8) & 0xf;
5236 neon_load_reg64(cpu_V0
, rn
);
5238 neon_load_reg64(cpu_V1
, rn
+ 1);
5240 } else if (imm
== 8) {
5241 neon_load_reg64(cpu_V0
, rn
+ 1);
5243 neon_load_reg64(cpu_V1
, rm
);
5246 tmp64
= tcg_temp_new_i64();
5248 neon_load_reg64(cpu_V0
, rn
);
5249 neon_load_reg64(tmp64
, rn
+ 1);
5251 neon_load_reg64(cpu_V0
, rn
+ 1);
5252 neon_load_reg64(tmp64
, rm
);
5254 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5255 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5256 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5258 neon_load_reg64(cpu_V1
, rm
);
5260 neon_load_reg64(cpu_V1
, rm
+ 1);
5263 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5264 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5265 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5268 neon_load_reg64(cpu_V0
, rn
);
5269 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5270 neon_load_reg64(cpu_V1
, rm
);
5271 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5272 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5274 neon_store_reg64(cpu_V0
, rd
);
5276 neon_store_reg64(cpu_V1
, rd
+ 1);
5278 } else if ((insn
& (1 << 11)) == 0) {
5279 /* Two register misc. */
5280 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5281 size
= (insn
>> 18) & 3;
5283 case 0: /* VREV64 */
5286 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5287 NEON_GET_REG(T0
, rm
, pass
* 2);
5288 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5290 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5291 case 1: gen_swap_half(cpu_T
[0]); break;
5292 case 2: /* no-op */ break;
5295 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5297 NEON_SET_REG(T1
, rd
, pass
* 2);
5299 gen_op_movl_T0_T1();
5301 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5302 case 1: gen_swap_half(cpu_T
[0]); break;
5305 NEON_SET_REG(T0
, rd
, pass
* 2);
5309 case 4: case 5: /* VPADDL */
5310 case 12: case 13: /* VPADAL */
5313 for (pass
= 0; pass
< q
+ 1; pass
++) {
5314 tmp
= neon_load_reg(rm
, pass
* 2);
5315 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5316 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5317 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5319 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5320 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5321 case 2: tcg_gen_add_i64(CPU_V001
); break;
5326 neon_load_reg64(cpu_V1
, rd
+ pass
);
5327 gen_neon_addl(size
);
5329 neon_store_reg64(cpu_V0
, rd
+ pass
);
5334 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5335 NEON_GET_REG(T0
, rm
, n
);
5336 NEON_GET_REG(T1
, rd
, n
+ 1);
5337 NEON_SET_REG(T1
, rm
, n
);
5338 NEON_SET_REG(T0
, rd
, n
+ 1);
5346 Rd A3 A2 A1 A0 B2 B0 A2 A0
5347 Rm B3 B2 B1 B0 B3 B1 A3 A1
5351 gen_neon_unzip(rd
, q
, 0, size
);
5352 gen_neon_unzip(rm
, q
, 4, size
);
5354 static int unzip_order_q
[8] =
5355 {0, 2, 4, 6, 1, 3, 5, 7};
5356 for (n
= 0; n
< 8; n
++) {
5357 int reg
= (n
< 4) ? rd
: rm
;
5358 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5359 NEON_SET_REG(T0
, reg
, n
% 4);
5362 static int unzip_order
[4] =
5364 for (n
= 0; n
< 4; n
++) {
5365 int reg
= (n
< 2) ? rd
: rm
;
5366 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5367 NEON_SET_REG(T0
, reg
, n
% 2);
5373 Rd A3 A2 A1 A0 B1 A1 B0 A0
5374 Rm B3 B2 B1 B0 B3 A3 B2 A2
5378 count
= (q
? 4 : 2);
5379 for (n
= 0; n
< count
; n
++) {
5380 NEON_GET_REG(T0
, rd
, n
);
5381 NEON_GET_REG(T1
, rd
, n
);
5383 case 0: gen_neon_zip_u8(cpu_T
[0], cpu_T
[1]); break;
5384 case 1: gen_neon_zip_u16(cpu_T
[0], cpu_T
[1]); break;
5385 case 2: /* no-op */; break;
5388 gen_neon_movl_scratch_T0(n
* 2);
5389 gen_neon_movl_scratch_T1(n
* 2 + 1);
5391 for (n
= 0; n
< count
* 2; n
++) {
5392 int reg
= (n
< count
) ? rd
: rm
;
5393 gen_neon_movl_T0_scratch(n
);
5394 NEON_SET_REG(T0
, reg
, n
% count
);
5397 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5401 for (pass
= 0; pass
< 2; pass
++) {
5402 neon_load_reg64(cpu_V0
, rm
+ pass
);
5404 if (op
== 36 && q
== 0) {
5405 gen_neon_narrow(size
, tmp
, cpu_V0
);
5407 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5409 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5414 neon_store_reg(rd
, 0, tmp2
);
5415 neon_store_reg(rd
, 1, tmp
);
5419 case 38: /* VSHLL */
5422 tmp
= neon_load_reg(rm
, 0);
5423 tmp2
= neon_load_reg(rm
, 1);
5424 for (pass
= 0; pass
< 2; pass
++) {
5427 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5428 neon_store_reg64(cpu_V0
, rd
+ pass
);
5433 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5434 if (op
== 30 || op
== 31 || op
>= 58) {
5435 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5436 neon_reg_offset(rm
, pass
));
5438 NEON_GET_REG(T0
, rm
, pass
);
5441 case 1: /* VREV32 */
5443 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5444 case 1: gen_swap_half(cpu_T
[0]); break;
5448 case 2: /* VREV16 */
5451 gen_rev16(cpu_T
[0]);
5455 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5456 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5457 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5463 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5464 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5465 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5472 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5479 case 14: /* VQABS */
5481 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5482 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5483 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5487 case 15: /* VQNEG */
5489 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5490 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5491 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5495 case 16: case 19: /* VCGT #0, VCLE #0 */
5496 gen_op_movl_T1_im(0);
5498 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5499 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5500 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5506 case 17: case 20: /* VCGE #0, VCLT #0 */
5507 gen_op_movl_T1_im(0);
5509 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5510 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5511 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5517 case 18: /* VCEQ #0 */
5518 gen_op_movl_T1_im(0);
5520 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5521 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5522 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5528 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5529 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5530 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5535 gen_op_movl_T1_im(0);
5540 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5541 gen_op_movl_T1_im(0);
5542 gen_helper_neon_cgt_f32(CPU_T001
);
5546 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5547 gen_op_movl_T1_im(0);
5548 gen_helper_neon_cge_f32(CPU_T001
);
5552 case 26: /* Float VCEQ #0 */
5553 gen_op_movl_T1_im(0);
5554 gen_helper_neon_ceq_f32(CPU_T001
);
5556 case 30: /* Float VABS */
5559 case 31: /* Float VNEG */
5563 NEON_GET_REG(T1
, rd
, pass
);
5564 NEON_SET_REG(T1
, rm
, pass
);
5567 NEON_GET_REG(T1
, rd
, pass
);
5569 case 0: gen_neon_trn_u8(cpu_T
[0], cpu_T
[1]); break;
5570 case 1: gen_neon_trn_u16(cpu_T
[0], cpu_T
[1]); break;
5574 NEON_SET_REG(T1
, rm
, pass
);
5576 case 56: /* Integer VRECPE */
5577 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5579 case 57: /* Integer VRSQRTE */
5580 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5582 case 58: /* Float VRECPE */
5583 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5585 case 59: /* Float VRSQRTE */
5586 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5588 case 60: /* VCVT.F32.S32 */
5591 case 61: /* VCVT.F32.U32 */
5594 case 62: /* VCVT.S32.F32 */
5597 case 63: /* VCVT.U32.F32 */
5601 /* Reserved: 21, 29, 39-56 */
5604 if (op
== 30 || op
== 31 || op
>= 58) {
5605 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5606 neon_reg_offset(rd
, pass
));
5608 NEON_SET_REG(T0
, rd
, pass
);
5613 } else if ((insn
& (1 << 10)) == 0) {
5615 n
= ((insn
>> 5) & 0x18) + 8;
5616 if (insn
& (1 << 6)) {
5617 tmp
= neon_load_reg(rd
, 0);
5620 tcg_gen_movi_i32(tmp
, 0);
5622 tmp2
= neon_load_reg(rm
, 0);
5623 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5626 if (insn
& (1 << 6)) {
5627 tmp
= neon_load_reg(rd
, 1);
5630 tcg_gen_movi_i32(tmp
, 0);
5632 tmp3
= neon_load_reg(rm
, 1);
5633 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5635 neon_store_reg(rd
, 0, tmp2
);
5636 neon_store_reg(rd
, 1, tmp3
);
5638 } else if ((insn
& 0x380) == 0) {
5640 if (insn
& (1 << 19)) {
5641 NEON_SET_REG(T0
, rm
, 1);
5643 NEON_SET_REG(T0
, rm
, 0);
5645 if (insn
& (1 << 16)) {
5646 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5647 } else if (insn
& (1 << 17)) {
5648 if ((insn
>> 18) & 1)
5649 gen_neon_dup_high16(cpu_T
[0]);
5651 gen_neon_dup_low16(cpu_T
[0]);
5653 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5654 NEON_SET_REG(T0
, rd
, pass
);
5664 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5666 int crn
= (insn
>> 16) & 0xf;
5667 int crm
= insn
& 0xf;
5668 int op1
= (insn
>> 21) & 7;
5669 int op2
= (insn
>> 5) & 7;
5670 int rt
= (insn
>> 12) & 0xf;
5673 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5674 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5678 tmp
= load_cpu_field(teecr
);
5679 store_reg(s
, rt
, tmp
);
5682 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5684 if (IS_USER(s
) && (env
->teecr
& 1))
5686 tmp
= load_cpu_field(teehbr
);
5687 store_reg(s
, rt
, tmp
);
5691 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5692 op1
, crn
, crm
, op2
);
5696 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5698 int crn
= (insn
>> 16) & 0xf;
5699 int crm
= insn
& 0xf;
5700 int op1
= (insn
>> 21) & 7;
5701 int op2
= (insn
>> 5) & 7;
5702 int rt
= (insn
>> 12) & 0xf;
5705 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5706 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5710 tmp
= load_reg(s
, rt
);
5711 gen_helper_set_teecr(cpu_env
, tmp
);
5715 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5717 if (IS_USER(s
) && (env
->teecr
& 1))
5719 tmp
= load_reg(s
, rt
);
5720 store_cpu_field(tmp
, teehbr
);
5724 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5725 op1
, crn
, crm
, op2
);
5729 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5733 cpnum
= (insn
>> 8) & 0xf;
5734 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5735 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5741 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5742 return disas_iwmmxt_insn(env
, s
, insn
);
5743 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5744 return disas_dsp_insn(env
, s
, insn
);
5749 return disas_vfp_insn (env
, s
, insn
);
5751 /* Coprocessors 7-15 are architecturally reserved by ARM.
5752 Unfortunately Intel decided to ignore this. */
5753 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5755 if (insn
& (1 << 20))
5756 return disas_cp14_read(env
, s
, insn
);
5758 return disas_cp14_write(env
, s
, insn
);
5760 return disas_cp15_insn (env
, s
, insn
);
5763 /* Unknown coprocessor. See if the board has hooked it. */
5764 return disas_cp_insn (env
, s
, insn
);
5769 /* Store a 64-bit value to a register pair. Clobbers val. */
5770 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5774 tcg_gen_trunc_i64_i32(tmp
, val
);
5775 store_reg(s
, rlow
, tmp
);
5777 tcg_gen_shri_i64(val
, val
, 32);
5778 tcg_gen_trunc_i64_i32(tmp
, val
);
5779 store_reg(s
, rhigh
, tmp
);
5782 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5783 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5788 /* Load value and extend to 64 bits. */
5789 tmp
= tcg_temp_new_i64();
5790 tmp2
= load_reg(s
, rlow
);
5791 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5793 tcg_gen_add_i64(val
, val
, tmp
);
5796 /* load and add a 64-bit value from a register pair. */
5797 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5803 /* Load 64-bit value rd:rn. */
5804 tmpl
= load_reg(s
, rlow
);
5805 tmph
= load_reg(s
, rhigh
);
5806 tmp
= tcg_temp_new_i64();
5807 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5810 tcg_gen_add_i64(val
, val
, tmp
);
5813 /* Set N and Z flags from a 64-bit value. */
5814 static void gen_logicq_cc(TCGv_i64 val
)
5816 TCGv tmp
= new_tmp();
5817 gen_helper_logicq_cc(tmp
, val
);
5822 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5824 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5831 insn
= ldl_code(s
->pc
);
5834 /* M variants do not implement ARM mode. */
5839 /* Unconditional instructions. */
5840 if (((insn
>> 25) & 7) == 1) {
5841 /* NEON Data processing. */
5842 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5845 if (disas_neon_data_insn(env
, s
, insn
))
5849 if ((insn
& 0x0f100000) == 0x04000000) {
5850 /* NEON load/store. */
5851 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5854 if (disas_neon_ls_insn(env
, s
, insn
))
5858 if ((insn
& 0x0d70f000) == 0x0550f000)
5860 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5863 if (insn
& (1 << 9)) {
5864 /* BE8 mode not implemented. */
5868 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5869 switch ((insn
>> 4) & 0xf) {
5872 gen_helper_clrex(cpu_env
);
5878 /* We don't emulate caches so these are a no-op. */
5883 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5889 op1
= (insn
& 0x1f);
5890 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5891 addr
= load_reg(s
, 13);
5894 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5896 i
= (insn
>> 23) & 3;
5898 case 0: offset
= -4; break; /* DA */
5899 case 1: offset
= 0; break; /* IA */
5900 case 2: offset
= -8; break; /* DB */
5901 case 3: offset
= 4; break; /* IB */
5905 tcg_gen_addi_i32(addr
, addr
, offset
);
5906 tmp
= load_reg(s
, 14);
5907 gen_st32(tmp
, addr
, 0);
5908 tmp
= load_cpu_field(spsr
);
5909 tcg_gen_addi_i32(addr
, addr
, 4);
5910 gen_st32(tmp
, addr
, 0);
5911 if (insn
& (1 << 21)) {
5912 /* Base writeback. */
5914 case 0: offset
= -8; break;
5915 case 1: offset
= 4; break;
5916 case 2: offset
= -4; break;
5917 case 3: offset
= 0; break;
5921 tcg_gen_addi_i32(addr
, addr
, offset
);
5922 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5923 store_reg(s
, 13, addr
);
5925 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5931 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5937 rn
= (insn
>> 16) & 0xf;
5938 addr
= load_reg(s
, rn
);
5939 i
= (insn
>> 23) & 3;
5941 case 0: offset
= -4; break; /* DA */
5942 case 1: offset
= 0; break; /* IA */
5943 case 2: offset
= -8; break; /* DB */
5944 case 3: offset
= 4; break; /* IB */
5948 tcg_gen_addi_i32(addr
, addr
, offset
);
5949 /* Load PC into tmp and CPSR into tmp2. */
5950 tmp
= gen_ld32(addr
, 0);
5951 tcg_gen_addi_i32(addr
, addr
, 4);
5952 tmp2
= gen_ld32(addr
, 0);
5953 if (insn
& (1 << 21)) {
5954 /* Base writeback. */
5956 case 0: offset
= -8; break;
5957 case 1: offset
= 4; break;
5958 case 2: offset
= -4; break;
5959 case 3: offset
= 0; break;
5963 tcg_gen_addi_i32(addr
, addr
, offset
);
5964 store_reg(s
, rn
, addr
);
5968 gen_rfe(s
, tmp
, tmp2
);
5970 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5971 /* branch link and change to thumb (blx <offset>) */
5974 val
= (uint32_t)s
->pc
;
5976 tcg_gen_movi_i32(tmp
, val
);
5977 store_reg(s
, 14, tmp
);
5978 /* Sign-extend the 24-bit offset */
5979 offset
= (((int32_t)insn
) << 8) >> 8;
5980 /* offset * 4 + bit24 * 2 + (thumb bit) */
5981 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5982 /* pipeline offset */
5986 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5987 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5988 /* iWMMXt register transfer. */
5989 if (env
->cp15
.c15_cpar
& (1 << 1))
5990 if (!disas_iwmmxt_insn(env
, s
, insn
))
5993 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5994 /* Coprocessor double register transfer. */
5995 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5996 /* Additional coprocessor register transfer. */
5997 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6000 /* cps (privileged) */
6004 if (insn
& (1 << 19)) {
6005 if (insn
& (1 << 8))
6007 if (insn
& (1 << 7))
6009 if (insn
& (1 << 6))
6011 if (insn
& (1 << 18))
6014 if (insn
& (1 << 17)) {
6016 val
|= (insn
& 0x1f);
6019 gen_set_psr_im(s
, mask
, 0, val
);
6026 /* if not always execute, we generate a conditional jump to
6028 s
->condlabel
= gen_new_label();
6029 gen_test_cc(cond
^ 1, s
->condlabel
);
6032 if ((insn
& 0x0f900000) == 0x03000000) {
6033 if ((insn
& (1 << 21)) == 0) {
6035 rd
= (insn
>> 12) & 0xf;
6036 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6037 if ((insn
& (1 << 22)) == 0) {
6040 tcg_gen_movi_i32(tmp
, val
);
6043 tmp
= load_reg(s
, rd
);
6044 tcg_gen_ext16u_i32(tmp
, tmp
);
6045 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6047 store_reg(s
, rd
, tmp
);
6049 if (((insn
>> 12) & 0xf) != 0xf)
6051 if (((insn
>> 16) & 0xf) == 0) {
6052 gen_nop_hint(s
, insn
& 0xff);
6054 /* CPSR = immediate */
6056 shift
= ((insn
>> 8) & 0xf) * 2;
6058 val
= (val
>> shift
) | (val
<< (32 - shift
));
6059 i
= ((insn
& (1 << 22)) != 0);
6060 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6064 } else if ((insn
& 0x0f900000) == 0x01000000
6065 && (insn
& 0x00000090) != 0x00000090) {
6066 /* miscellaneous instructions */
6067 op1
= (insn
>> 21) & 3;
6068 sh
= (insn
>> 4) & 0xf;
6071 case 0x0: /* move program status register */
6074 tmp
= load_reg(s
, rm
);
6075 i
= ((op1
& 2) != 0);
6076 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6080 rd
= (insn
>> 12) & 0xf;
6084 tmp
= load_cpu_field(spsr
);
6087 gen_helper_cpsr_read(tmp
);
6089 store_reg(s
, rd
, tmp
);
6094 /* branch/exchange thumb (bx). */
6095 tmp
= load_reg(s
, rm
);
6097 } else if (op1
== 3) {
6099 rd
= (insn
>> 12) & 0xf;
6100 tmp
= load_reg(s
, rm
);
6101 gen_helper_clz(tmp
, tmp
);
6102 store_reg(s
, rd
, tmp
);
6110 /* Trivial implementation equivalent to bx. */
6111 tmp
= load_reg(s
, rm
);
6121 /* branch link/exchange thumb (blx) */
6122 tmp
= load_reg(s
, rm
);
6124 tcg_gen_movi_i32(tmp2
, s
->pc
);
6125 store_reg(s
, 14, tmp2
);
6128 case 0x5: /* saturating add/subtract */
6129 rd
= (insn
>> 12) & 0xf;
6130 rn
= (insn
>> 16) & 0xf;
6131 tmp
= load_reg(s
, rm
);
6132 tmp2
= load_reg(s
, rn
);
6134 gen_helper_double_saturate(tmp2
, tmp2
);
6136 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6138 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6140 store_reg(s
, rd
, tmp
);
6143 gen_set_condexec(s
);
6144 gen_set_pc_im(s
->pc
- 4);
6145 gen_exception(EXCP_BKPT
);
6146 s
->is_jmp
= DISAS_JUMP
;
6148 case 0x8: /* signed multiply */
6152 rs
= (insn
>> 8) & 0xf;
6153 rn
= (insn
>> 12) & 0xf;
6154 rd
= (insn
>> 16) & 0xf;
6156 /* (32 * 16) >> 16 */
6157 tmp
= load_reg(s
, rm
);
6158 tmp2
= load_reg(s
, rs
);
6160 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6163 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6164 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6166 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6167 if ((sh
& 2) == 0) {
6168 tmp2
= load_reg(s
, rn
);
6169 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6172 store_reg(s
, rd
, tmp
);
6175 tmp
= load_reg(s
, rm
);
6176 tmp2
= load_reg(s
, rs
);
6177 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6180 tmp64
= tcg_temp_new_i64();
6181 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6183 gen_addq(s
, tmp64
, rn
, rd
);
6184 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6187 tmp2
= load_reg(s
, rn
);
6188 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6191 store_reg(s
, rd
, tmp
);
6198 } else if (((insn
& 0x0e000000) == 0 &&
6199 (insn
& 0x00000090) != 0x90) ||
6200 ((insn
& 0x0e000000) == (1 << 25))) {
6201 int set_cc
, logic_cc
, shiftop
;
6203 op1
= (insn
>> 21) & 0xf;
6204 set_cc
= (insn
>> 20) & 1;
6205 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6207 /* data processing instruction */
6208 if (insn
& (1 << 25)) {
6209 /* immediate operand */
6211 shift
= ((insn
>> 8) & 0xf) * 2;
6213 val
= (val
>> shift
) | (val
<< (32 - shift
));
6216 tcg_gen_movi_i32(tmp2
, val
);
6217 if (logic_cc
&& shift
) {
6218 gen_set_CF_bit31(tmp2
);
6223 tmp2
= load_reg(s
, rm
);
6224 shiftop
= (insn
>> 5) & 3;
6225 if (!(insn
& (1 << 4))) {
6226 shift
= (insn
>> 7) & 0x1f;
6227 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6229 rs
= (insn
>> 8) & 0xf;
6230 tmp
= load_reg(s
, rs
);
6231 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6234 if (op1
!= 0x0f && op1
!= 0x0d) {
6235 rn
= (insn
>> 16) & 0xf;
6236 tmp
= load_reg(s
, rn
);
6240 rd
= (insn
>> 12) & 0xf;
6243 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6247 store_reg_bx(env
, s
, rd
, tmp
);
6250 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6254 store_reg_bx(env
, s
, rd
, tmp
);
6257 if (set_cc
&& rd
== 15) {
6258 /* SUBS r15, ... is used for exception return. */
6262 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6263 gen_exception_return(s
, tmp
);
6266 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6268 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6270 store_reg_bx(env
, s
, rd
, tmp
);
6275 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6277 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6279 store_reg_bx(env
, s
, rd
, tmp
);
6283 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6285 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6287 store_reg_bx(env
, s
, rd
, tmp
);
6291 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6293 gen_add_carry(tmp
, tmp
, tmp2
);
6295 store_reg_bx(env
, s
, rd
, tmp
);
6299 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6301 gen_sub_carry(tmp
, tmp
, tmp2
);
6303 store_reg_bx(env
, s
, rd
, tmp
);
6307 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6309 gen_sub_carry(tmp
, tmp2
, tmp
);
6311 store_reg_bx(env
, s
, rd
, tmp
);
6315 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6322 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6329 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6335 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6340 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6344 store_reg_bx(env
, s
, rd
, tmp
);
6347 if (logic_cc
&& rd
== 15) {
6348 /* MOVS r15, ... is used for exception return. */
6352 gen_exception_return(s
, tmp2
);
6357 store_reg_bx(env
, s
, rd
, tmp2
);
6361 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6365 store_reg_bx(env
, s
, rd
, tmp
);
6369 tcg_gen_not_i32(tmp2
, tmp2
);
6373 store_reg_bx(env
, s
, rd
, tmp2
);
6376 if (op1
!= 0x0f && op1
!= 0x0d) {
6380 /* other instructions */
6381 op1
= (insn
>> 24) & 0xf;
6385 /* multiplies, extra load/stores */
6386 sh
= (insn
>> 5) & 3;
6389 rd
= (insn
>> 16) & 0xf;
6390 rn
= (insn
>> 12) & 0xf;
6391 rs
= (insn
>> 8) & 0xf;
6393 op1
= (insn
>> 20) & 0xf;
6395 case 0: case 1: case 2: case 3: case 6:
6397 tmp
= load_reg(s
, rs
);
6398 tmp2
= load_reg(s
, rm
);
6399 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6401 if (insn
& (1 << 22)) {
6402 /* Subtract (mls) */
6404 tmp2
= load_reg(s
, rn
);
6405 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6407 } else if (insn
& (1 << 21)) {
6409 tmp2
= load_reg(s
, rn
);
6410 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6413 if (insn
& (1 << 20))
6415 store_reg(s
, rd
, tmp
);
6419 tmp
= load_reg(s
, rs
);
6420 tmp2
= load_reg(s
, rm
);
6421 if (insn
& (1 << 22))
6422 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6424 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6425 if (insn
& (1 << 21)) /* mult accumulate */
6426 gen_addq(s
, tmp64
, rn
, rd
);
6427 if (!(insn
& (1 << 23))) { /* double accumulate */
6429 gen_addq_lo(s
, tmp64
, rn
);
6430 gen_addq_lo(s
, tmp64
, rd
);
6432 if (insn
& (1 << 20))
6433 gen_logicq_cc(tmp64
);
6434 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6438 rn
= (insn
>> 16) & 0xf;
6439 rd
= (insn
>> 12) & 0xf;
6440 if (insn
& (1 << 23)) {
6441 /* load/store exclusive */
6442 op1
= (insn
>> 21) & 0x3;
6447 addr
= tcg_temp_local_new_i32();
6448 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
6449 if (insn
& (1 << 20)) {
6450 gen_helper_mark_exclusive(cpu_env
, addr
);
6453 tmp
= gen_ld32(addr
, IS_USER(s
));
6455 case 1: /* ldrexd */
6456 tmp
= gen_ld32(addr
, IS_USER(s
));
6457 store_reg(s
, rd
, tmp
);
6458 tcg_gen_addi_i32(addr
, addr
, 4);
6459 tmp
= gen_ld32(addr
, IS_USER(s
));
6462 case 2: /* ldrexb */
6463 tmp
= gen_ld8u(addr
, IS_USER(s
));
6465 case 3: /* ldrexh */
6466 tmp
= gen_ld16u(addr
, IS_USER(s
));
6471 store_reg(s
, rd
, tmp
);
6473 int label
= gen_new_label();
6475 tmp2
= tcg_temp_local_new_i32();
6476 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6477 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6478 tmp
= load_reg(s
,rm
);
6481 gen_st32(tmp
, addr
, IS_USER(s
));
6483 case 1: /* strexd */
6484 gen_st32(tmp
, addr
, IS_USER(s
));
6485 tcg_gen_addi_i32(addr
, addr
, 4);
6486 tmp
= load_reg(s
, rm
+ 1);
6487 gen_st32(tmp
, addr
, IS_USER(s
));
6489 case 2: /* strexb */
6490 gen_st8(tmp
, addr
, IS_USER(s
));
6492 case 3: /* strexh */
6493 gen_st16(tmp
, addr
, IS_USER(s
));
6498 gen_set_label(label
);
6499 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6500 tcg_temp_free(tmp2
);
6502 tcg_temp_free(addr
);
6504 /* SWP instruction */
6507 /* ??? This is not really atomic. However we know
6508 we never have multiple CPUs running in parallel,
6509 so it is good enough. */
6510 addr
= load_reg(s
, rn
);
6511 tmp
= load_reg(s
, rm
);
6512 if (insn
& (1 << 22)) {
6513 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6514 gen_st8(tmp
, addr
, IS_USER(s
));
6516 tmp2
= gen_ld32(addr
, IS_USER(s
));
6517 gen_st32(tmp
, addr
, IS_USER(s
));
6520 store_reg(s
, rd
, tmp2
);
6526 /* Misc load/store */
6527 rn
= (insn
>> 16) & 0xf;
6528 rd
= (insn
>> 12) & 0xf;
6529 addr
= load_reg(s
, rn
);
6530 if (insn
& (1 << 24))
6531 gen_add_datah_offset(s
, insn
, 0, addr
);
6533 if (insn
& (1 << 20)) {
6537 tmp
= gen_ld16u(addr
, IS_USER(s
));
6540 tmp
= gen_ld8s(addr
, IS_USER(s
));
6544 tmp
= gen_ld16s(addr
, IS_USER(s
));
6548 } else if (sh
& 2) {
6552 tmp
= load_reg(s
, rd
);
6553 gen_st32(tmp
, addr
, IS_USER(s
));
6554 tcg_gen_addi_i32(addr
, addr
, 4);
6555 tmp
= load_reg(s
, rd
+ 1);
6556 gen_st32(tmp
, addr
, IS_USER(s
));
6560 tmp
= gen_ld32(addr
, IS_USER(s
));
6561 store_reg(s
, rd
, tmp
);
6562 tcg_gen_addi_i32(addr
, addr
, 4);
6563 tmp
= gen_ld32(addr
, IS_USER(s
));
6567 address_offset
= -4;
6570 tmp
= load_reg(s
, rd
);
6571 gen_st16(tmp
, addr
, IS_USER(s
));
6574 /* Perform base writeback before the loaded value to
6575 ensure correct behavior with overlapping index registers.
6576 ldrd with base writeback is is undefined if the
6577 destination and index registers overlap. */
6578 if (!(insn
& (1 << 24))) {
6579 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6580 store_reg(s
, rn
, addr
);
6581 } else if (insn
& (1 << 21)) {
6583 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6584 store_reg(s
, rn
, addr
);
6589 /* Complete the load. */
6590 store_reg(s
, rd
, tmp
);
6599 if (insn
& (1 << 4)) {
6601 /* Armv6 Media instructions. */
6603 rn
= (insn
>> 16) & 0xf;
6604 rd
= (insn
>> 12) & 0xf;
6605 rs
= (insn
>> 8) & 0xf;
6606 switch ((insn
>> 23) & 3) {
6607 case 0: /* Parallel add/subtract. */
6608 op1
= (insn
>> 20) & 7;
6609 tmp
= load_reg(s
, rn
);
6610 tmp2
= load_reg(s
, rm
);
6611 sh
= (insn
>> 5) & 7;
6612 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6614 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6616 store_reg(s
, rd
, tmp
);
6619 if ((insn
& 0x00700020) == 0) {
6620 /* Halfword pack. */
6621 tmp
= load_reg(s
, rn
);
6622 tmp2
= load_reg(s
, rm
);
6623 shift
= (insn
>> 7) & 0x1f;
6624 if (insn
& (1 << 6)) {
6628 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6629 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6630 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6634 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6635 tcg_gen_ext16u_i32(tmp
, tmp
);
6636 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6638 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6640 store_reg(s
, rd
, tmp
);
6641 } else if ((insn
& 0x00200020) == 0x00200000) {
6643 tmp
= load_reg(s
, rm
);
6644 shift
= (insn
>> 7) & 0x1f;
6645 if (insn
& (1 << 6)) {
6648 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6650 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6652 sh
= (insn
>> 16) & 0x1f;
6654 if (insn
& (1 << 22))
6655 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6657 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6659 store_reg(s
, rd
, tmp
);
6660 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6662 tmp
= load_reg(s
, rm
);
6663 sh
= (insn
>> 16) & 0x1f;
6665 if (insn
& (1 << 22))
6666 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6668 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6670 store_reg(s
, rd
, tmp
);
6671 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6673 tmp
= load_reg(s
, rn
);
6674 tmp2
= load_reg(s
, rm
);
6676 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6677 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6680 store_reg(s
, rd
, tmp
);
6681 } else if ((insn
& 0x000003e0) == 0x00000060) {
6682 tmp
= load_reg(s
, rm
);
6683 shift
= (insn
>> 10) & 3;
6684 /* ??? In many cases it's not neccessary to do a
6685 rotate, a shift is sufficient. */
6687 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6688 op1
= (insn
>> 20) & 7;
6690 case 0: gen_sxtb16(tmp
); break;
6691 case 2: gen_sxtb(tmp
); break;
6692 case 3: gen_sxth(tmp
); break;
6693 case 4: gen_uxtb16(tmp
); break;
6694 case 6: gen_uxtb(tmp
); break;
6695 case 7: gen_uxth(tmp
); break;
6696 default: goto illegal_op
;
6699 tmp2
= load_reg(s
, rn
);
6700 if ((op1
& 3) == 0) {
6701 gen_add16(tmp
, tmp2
);
6703 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6707 store_reg(s
, rd
, tmp
);
6708 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6710 tmp
= load_reg(s
, rm
);
6711 if (insn
& (1 << 22)) {
6712 if (insn
& (1 << 7)) {
6716 gen_helper_rbit(tmp
, tmp
);
6719 if (insn
& (1 << 7))
6722 tcg_gen_bswap32_i32(tmp
, tmp
);
6724 store_reg(s
, rd
, tmp
);
6729 case 2: /* Multiplies (Type 3). */
6730 tmp
= load_reg(s
, rm
);
6731 tmp2
= load_reg(s
, rs
);
6732 if (insn
& (1 << 20)) {
6733 /* Signed multiply most significant [accumulate]. */
6734 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6735 if (insn
& (1 << 5))
6736 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6737 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6739 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6741 tmp2
= load_reg(s
, rd
);
6742 if (insn
& (1 << 6)) {
6743 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6745 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6749 store_reg(s
, rn
, tmp
);
6751 if (insn
& (1 << 5))
6752 gen_swap_half(tmp2
);
6753 gen_smul_dual(tmp
, tmp2
);
6754 /* This addition cannot overflow. */
6755 if (insn
& (1 << 6)) {
6756 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6758 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6761 if (insn
& (1 << 22)) {
6762 /* smlald, smlsld */
6763 tmp64
= tcg_temp_new_i64();
6764 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6766 gen_addq(s
, tmp64
, rd
, rn
);
6767 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6769 /* smuad, smusd, smlad, smlsd */
6772 tmp2
= load_reg(s
, rd
);
6773 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6776 store_reg(s
, rn
, tmp
);
6781 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6783 case 0: /* Unsigned sum of absolute differences. */
6785 tmp
= load_reg(s
, rm
);
6786 tmp2
= load_reg(s
, rs
);
6787 gen_helper_usad8(tmp
, tmp
, tmp2
);
6790 tmp2
= load_reg(s
, rd
);
6791 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6794 store_reg(s
, rn
, tmp
);
6796 case 0x20: case 0x24: case 0x28: case 0x2c:
6797 /* Bitfield insert/clear. */
6799 shift
= (insn
>> 7) & 0x1f;
6800 i
= (insn
>> 16) & 0x1f;
6804 tcg_gen_movi_i32(tmp
, 0);
6806 tmp
= load_reg(s
, rm
);
6809 tmp2
= load_reg(s
, rd
);
6810 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6813 store_reg(s
, rd
, tmp
);
6815 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6816 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6818 tmp
= load_reg(s
, rm
);
6819 shift
= (insn
>> 7) & 0x1f;
6820 i
= ((insn
>> 16) & 0x1f) + 1;
6825 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6827 gen_sbfx(tmp
, shift
, i
);
6830 store_reg(s
, rd
, tmp
);
6840 /* Check for undefined extension instructions
6841 * per the ARM Bible IE:
6842 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6844 sh
= (0xf << 20) | (0xf << 4);
6845 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6849 /* load/store byte/word */
6850 rn
= (insn
>> 16) & 0xf;
6851 rd
= (insn
>> 12) & 0xf;
6852 tmp2
= load_reg(s
, rn
);
6853 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6854 if (insn
& (1 << 24))
6855 gen_add_data_offset(s
, insn
, tmp2
);
6856 if (insn
& (1 << 20)) {
6858 if (insn
& (1 << 22)) {
6859 tmp
= gen_ld8u(tmp2
, i
);
6861 tmp
= gen_ld32(tmp2
, i
);
6865 tmp
= load_reg(s
, rd
);
6866 if (insn
& (1 << 22))
6867 gen_st8(tmp
, tmp2
, i
);
6869 gen_st32(tmp
, tmp2
, i
);
6871 if (!(insn
& (1 << 24))) {
6872 gen_add_data_offset(s
, insn
, tmp2
);
6873 store_reg(s
, rn
, tmp2
);
6874 } else if (insn
& (1 << 21)) {
6875 store_reg(s
, rn
, tmp2
);
6879 if (insn
& (1 << 20)) {
6880 /* Complete the load. */
6884 store_reg(s
, rd
, tmp
);
6890 int j
, n
, user
, loaded_base
;
6892 /* load/store multiple words */
6893 /* XXX: store correct base if write back */
6895 if (insn
& (1 << 22)) {
6897 goto illegal_op
; /* only usable in supervisor mode */
6899 if ((insn
& (1 << 15)) == 0)
6902 rn
= (insn
>> 16) & 0xf;
6903 addr
= load_reg(s
, rn
);
6905 /* compute total size */
6907 TCGV_UNUSED(loaded_var
);
6910 if (insn
& (1 << i
))
6913 /* XXX: test invalid n == 0 case ? */
6914 if (insn
& (1 << 23)) {
6915 if (insn
& (1 << 24)) {
6917 tcg_gen_addi_i32(addr
, addr
, 4);
6919 /* post increment */
6922 if (insn
& (1 << 24)) {
6924 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6926 /* post decrement */
6928 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6933 if (insn
& (1 << i
)) {
6934 if (insn
& (1 << 20)) {
6936 tmp
= gen_ld32(addr
, IS_USER(s
));
6940 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6942 } else if (i
== rn
) {
6946 store_reg(s
, i
, tmp
);
6951 /* special case: r15 = PC + 8 */
6952 val
= (long)s
->pc
+ 4;
6954 tcg_gen_movi_i32(tmp
, val
);
6957 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6959 tmp
= load_reg(s
, i
);
6961 gen_st32(tmp
, addr
, IS_USER(s
));
6964 /* no need to add after the last transfer */
6966 tcg_gen_addi_i32(addr
, addr
, 4);
6969 if (insn
& (1 << 21)) {
6971 if (insn
& (1 << 23)) {
6972 if (insn
& (1 << 24)) {
6975 /* post increment */
6976 tcg_gen_addi_i32(addr
, addr
, 4);
6979 if (insn
& (1 << 24)) {
6982 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6984 /* post decrement */
6985 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6988 store_reg(s
, rn
, addr
);
6993 store_reg(s
, rn
, loaded_var
);
6995 if ((insn
& (1 << 22)) && !user
) {
6996 /* Restore CPSR from SPSR. */
6997 tmp
= load_cpu_field(spsr
);
6998 gen_set_cpsr(tmp
, 0xffffffff);
7000 s
->is_jmp
= DISAS_UPDATE
;
7009 /* branch (and link) */
7010 val
= (int32_t)s
->pc
;
7011 if (insn
& (1 << 24)) {
7013 tcg_gen_movi_i32(tmp
, val
);
7014 store_reg(s
, 14, tmp
);
7016 offset
= (((int32_t)insn
<< 8) >> 8);
7017 val
+= (offset
<< 2) + 4;
7025 if (disas_coproc_insn(env
, s
, insn
))
7030 gen_set_pc_im(s
->pc
);
7031 s
->is_jmp
= DISAS_SWI
;
7035 gen_set_condexec(s
);
7036 gen_set_pc_im(s
->pc
- 4);
7037 gen_exception(EXCP_UDEF
);
7038 s
->is_jmp
= DISAS_JUMP
;
7044 /* Return true if this is a Thumb-2 logical op. */
7046 thumb2_logic_op(int op
)
7051 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7052 then set condition code flags based on the result of the operation.
7053 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7054 to the high bit of T1.
7055 Returns zero if the opcode is valid. */
7058 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7065 tcg_gen_and_i32(t0
, t0
, t1
);
7069 tcg_gen_bic_i32(t0
, t0
, t1
);
7073 tcg_gen_or_i32(t0
, t0
, t1
);
7077 tcg_gen_not_i32(t1
, t1
);
7078 tcg_gen_or_i32(t0
, t0
, t1
);
7082 tcg_gen_xor_i32(t0
, t0
, t1
);
7087 gen_helper_add_cc(t0
, t0
, t1
);
7089 tcg_gen_add_i32(t0
, t0
, t1
);
7093 gen_helper_adc_cc(t0
, t0
, t1
);
7099 gen_helper_sbc_cc(t0
, t0
, t1
);
7101 gen_sub_carry(t0
, t0
, t1
);
7105 gen_helper_sub_cc(t0
, t0
, t1
);
7107 tcg_gen_sub_i32(t0
, t0
, t1
);
7111 gen_helper_sub_cc(t0
, t1
, t0
);
7113 tcg_gen_sub_i32(t0
, t1
, t0
);
7115 default: /* 5, 6, 7, 9, 12, 15. */
7121 gen_set_CF_bit31(t1
);
7126 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7128 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7130 uint32_t insn
, imm
, shift
, offset
;
7131 uint32_t rd
, rn
, rm
, rs
;
7142 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7143 || arm_feature (env
, ARM_FEATURE_M
))) {
7144 /* Thumb-1 cores may need to treat bl and blx as a pair of
7145 16-bit instructions to get correct prefetch abort behavior. */
7147 if ((insn
& (1 << 12)) == 0) {
7148 /* Second half of blx. */
7149 offset
= ((insn
& 0x7ff) << 1);
7150 tmp
= load_reg(s
, 14);
7151 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7152 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7155 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7156 store_reg(s
, 14, tmp2
);
7160 if (insn
& (1 << 11)) {
7161 /* Second half of bl. */
7162 offset
= ((insn
& 0x7ff) << 1) | 1;
7163 tmp
= load_reg(s
, 14);
7164 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7167 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7168 store_reg(s
, 14, tmp2
);
7172 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7173 /* Instruction spans a page boundary. Implement it as two
7174 16-bit instructions in case the second half causes an
7176 offset
= ((int32_t)insn
<< 21) >> 9;
7177 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7180 /* Fall through to 32-bit decode. */
7183 insn
= lduw_code(s
->pc
);
7185 insn
|= (uint32_t)insn_hw1
<< 16;
7187 if ((insn
& 0xf800e800) != 0xf000e800) {
7191 rn
= (insn
>> 16) & 0xf;
7192 rs
= (insn
>> 12) & 0xf;
7193 rd
= (insn
>> 8) & 0xf;
7195 switch ((insn
>> 25) & 0xf) {
7196 case 0: case 1: case 2: case 3:
7197 /* 16-bit instructions. Should never happen. */
7200 if (insn
& (1 << 22)) {
7201 /* Other load/store, table branch. */
7202 if (insn
& 0x01200000) {
7203 /* Load/store doubleword. */
7206 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7208 addr
= load_reg(s
, rn
);
7210 offset
= (insn
& 0xff) * 4;
7211 if ((insn
& (1 << 23)) == 0)
7213 if (insn
& (1 << 24)) {
7214 tcg_gen_addi_i32(addr
, addr
, offset
);
7217 if (insn
& (1 << 20)) {
7219 tmp
= gen_ld32(addr
, IS_USER(s
));
7220 store_reg(s
, rs
, tmp
);
7221 tcg_gen_addi_i32(addr
, addr
, 4);
7222 tmp
= gen_ld32(addr
, IS_USER(s
));
7223 store_reg(s
, rd
, tmp
);
7226 tmp
= load_reg(s
, rs
);
7227 gen_st32(tmp
, addr
, IS_USER(s
));
7228 tcg_gen_addi_i32(addr
, addr
, 4);
7229 tmp
= load_reg(s
, rd
);
7230 gen_st32(tmp
, addr
, IS_USER(s
));
7232 if (insn
& (1 << 21)) {
7233 /* Base writeback. */
7236 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7237 store_reg(s
, rn
, addr
);
7241 } else if ((insn
& (1 << 23)) == 0) {
7242 /* Load/store exclusive word. */
7243 addr
= tcg_temp_local_new();
7244 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7245 if (insn
& (1 << 20)) {
7246 gen_helper_mark_exclusive(cpu_env
, addr
);
7247 tmp
= gen_ld32(addr
, IS_USER(s
));
7248 store_reg(s
, rd
, tmp
);
7250 int label
= gen_new_label();
7251 tmp2
= tcg_temp_local_new();
7252 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7253 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7254 tmp
= load_reg(s
, rs
);
7255 gen_st32(tmp
, addr
, IS_USER(s
));
7256 gen_set_label(label
);
7257 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7258 tcg_temp_free(tmp2
);
7260 tcg_temp_free(addr
);
7261 } else if ((insn
& (1 << 6)) == 0) {
7265 tcg_gen_movi_i32(addr
, s
->pc
);
7267 addr
= load_reg(s
, rn
);
7269 tmp
= load_reg(s
, rm
);
7270 tcg_gen_add_i32(addr
, addr
, tmp
);
7271 if (insn
& (1 << 4)) {
7273 tcg_gen_add_i32(addr
, addr
, tmp
);
7275 tmp
= gen_ld16u(addr
, IS_USER(s
));
7278 tmp
= gen_ld8u(addr
, IS_USER(s
));
7281 tcg_gen_shli_i32(tmp
, tmp
, 1);
7282 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7283 store_reg(s
, 15, tmp
);
7285 /* Load/store exclusive byte/halfword/doubleword. */
7286 /* ??? These are not really atomic. However we know
7287 we never have multiple CPUs running in parallel,
7288 so it is good enough. */
7289 op
= (insn
>> 4) & 0x3;
7290 addr
= tcg_temp_local_new();
7291 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7292 if (insn
& (1 << 20)) {
7293 gen_helper_mark_exclusive(cpu_env
, addr
);
7296 tmp
= gen_ld8u(addr
, IS_USER(s
));
7299 tmp
= gen_ld16u(addr
, IS_USER(s
));
7302 tmp
= gen_ld32(addr
, IS_USER(s
));
7303 tcg_gen_addi_i32(addr
, addr
, 4);
7304 tmp2
= gen_ld32(addr
, IS_USER(s
));
7305 store_reg(s
, rd
, tmp2
);
7310 store_reg(s
, rs
, tmp
);
7312 int label
= gen_new_label();
7313 tmp2
= tcg_temp_local_new();
7314 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7315 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7316 tmp
= load_reg(s
, rs
);
7319 gen_st8(tmp
, addr
, IS_USER(s
));
7322 gen_st16(tmp
, addr
, IS_USER(s
));
7325 gen_st32(tmp
, addr
, IS_USER(s
));
7326 tcg_gen_addi_i32(addr
, addr
, 4);
7327 tmp
= load_reg(s
, rd
);
7328 gen_st32(tmp
, addr
, IS_USER(s
));
7333 gen_set_label(label
);
7334 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7335 tcg_temp_free(tmp2
);
7337 tcg_temp_free(addr
);
7340 /* Load/store multiple, RFE, SRS. */
7341 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7342 /* Not available in user mode. */
7345 if (insn
& (1 << 20)) {
7347 addr
= load_reg(s
, rn
);
7348 if ((insn
& (1 << 24)) == 0)
7349 tcg_gen_addi_i32(addr
, addr
, -8);
7350 /* Load PC into tmp and CPSR into tmp2. */
7351 tmp
= gen_ld32(addr
, 0);
7352 tcg_gen_addi_i32(addr
, addr
, 4);
7353 tmp2
= gen_ld32(addr
, 0);
7354 if (insn
& (1 << 21)) {
7355 /* Base writeback. */
7356 if (insn
& (1 << 24)) {
7357 tcg_gen_addi_i32(addr
, addr
, 4);
7359 tcg_gen_addi_i32(addr
, addr
, -4);
7361 store_reg(s
, rn
, addr
);
7365 gen_rfe(s
, tmp
, tmp2
);
7369 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7370 addr
= load_reg(s
, 13);
7373 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7375 if ((insn
& (1 << 24)) == 0) {
7376 tcg_gen_addi_i32(addr
, addr
, -8);
7378 tmp
= load_reg(s
, 14);
7379 gen_st32(tmp
, addr
, 0);
7380 tcg_gen_addi_i32(addr
, addr
, 4);
7382 gen_helper_cpsr_read(tmp
);
7383 gen_st32(tmp
, addr
, 0);
7384 if (insn
& (1 << 21)) {
7385 if ((insn
& (1 << 24)) == 0) {
7386 tcg_gen_addi_i32(addr
, addr
, -4);
7388 tcg_gen_addi_i32(addr
, addr
, 4);
7390 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7391 store_reg(s
, 13, addr
);
7393 gen_helper_set_r13_banked(cpu_env
,
7394 tcg_const_i32(op
), addr
);
7402 /* Load/store multiple. */
7403 addr
= load_reg(s
, rn
);
7405 for (i
= 0; i
< 16; i
++) {
7406 if (insn
& (1 << i
))
7409 if (insn
& (1 << 24)) {
7410 tcg_gen_addi_i32(addr
, addr
, -offset
);
7413 for (i
= 0; i
< 16; i
++) {
7414 if ((insn
& (1 << i
)) == 0)
7416 if (insn
& (1 << 20)) {
7418 tmp
= gen_ld32(addr
, IS_USER(s
));
7422 store_reg(s
, i
, tmp
);
7426 tmp
= load_reg(s
, i
);
7427 gen_st32(tmp
, addr
, IS_USER(s
));
7429 tcg_gen_addi_i32(addr
, addr
, 4);
7431 if (insn
& (1 << 21)) {
7432 /* Base register writeback. */
7433 if (insn
& (1 << 24)) {
7434 tcg_gen_addi_i32(addr
, addr
, -offset
);
7436 /* Fault if writeback register is in register list. */
7437 if (insn
& (1 << rn
))
7439 store_reg(s
, rn
, addr
);
7446 case 5: /* Data processing register constant shift. */
7449 tcg_gen_movi_i32(tmp
, 0);
7451 tmp
= load_reg(s
, rn
);
7453 tmp2
= load_reg(s
, rm
);
7454 op
= (insn
>> 21) & 0xf;
7455 shiftop
= (insn
>> 4) & 3;
7456 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7457 conds
= (insn
& (1 << 20)) != 0;
7458 logic_cc
= (conds
&& thumb2_logic_op(op
));
7459 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7460 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7464 store_reg(s
, rd
, tmp
);
7469 case 13: /* Misc data processing. */
7470 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7471 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7474 case 0: /* Register controlled shift. */
7475 tmp
= load_reg(s
, rn
);
7476 tmp2
= load_reg(s
, rm
);
7477 if ((insn
& 0x70) != 0)
7479 op
= (insn
>> 21) & 3;
7480 logic_cc
= (insn
& (1 << 20)) != 0;
7481 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7484 store_reg_bx(env
, s
, rd
, tmp
);
7486 case 1: /* Sign/zero extend. */
7487 tmp
= load_reg(s
, rm
);
7488 shift
= (insn
>> 4) & 3;
7489 /* ??? In many cases it's not neccessary to do a
7490 rotate, a shift is sufficient. */
7492 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7493 op
= (insn
>> 20) & 7;
7495 case 0: gen_sxth(tmp
); break;
7496 case 1: gen_uxth(tmp
); break;
7497 case 2: gen_sxtb16(tmp
); break;
7498 case 3: gen_uxtb16(tmp
); break;
7499 case 4: gen_sxtb(tmp
); break;
7500 case 5: gen_uxtb(tmp
); break;
7501 default: goto illegal_op
;
7504 tmp2
= load_reg(s
, rn
);
7505 if ((op
>> 1) == 1) {
7506 gen_add16(tmp
, tmp2
);
7508 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7512 store_reg(s
, rd
, tmp
);
7514 case 2: /* SIMD add/subtract. */
7515 op
= (insn
>> 20) & 7;
7516 shift
= (insn
>> 4) & 7;
7517 if ((op
& 3) == 3 || (shift
& 3) == 3)
7519 tmp
= load_reg(s
, rn
);
7520 tmp2
= load_reg(s
, rm
);
7521 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7523 store_reg(s
, rd
, tmp
);
7525 case 3: /* Other data processing. */
7526 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7528 /* Saturating add/subtract. */
7529 tmp
= load_reg(s
, rn
);
7530 tmp2
= load_reg(s
, rm
);
7532 gen_helper_double_saturate(tmp
, tmp
);
7534 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7536 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7539 tmp
= load_reg(s
, rn
);
7541 case 0x0a: /* rbit */
7542 gen_helper_rbit(tmp
, tmp
);
7544 case 0x08: /* rev */
7545 tcg_gen_bswap32_i32(tmp
, tmp
);
7547 case 0x09: /* rev16 */
7550 case 0x0b: /* revsh */
7553 case 0x10: /* sel */
7554 tmp2
= load_reg(s
, rm
);
7556 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7557 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7561 case 0x18: /* clz */
7562 gen_helper_clz(tmp
, tmp
);
7568 store_reg(s
, rd
, tmp
);
7570 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7571 op
= (insn
>> 4) & 0xf;
7572 tmp
= load_reg(s
, rn
);
7573 tmp2
= load_reg(s
, rm
);
7574 switch ((insn
>> 20) & 7) {
7575 case 0: /* 32 x 32 -> 32 */
7576 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7579 tmp2
= load_reg(s
, rs
);
7581 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7583 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7587 case 1: /* 16 x 16 -> 32 */
7588 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7591 tmp2
= load_reg(s
, rs
);
7592 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7596 case 2: /* Dual multiply add. */
7597 case 4: /* Dual multiply subtract. */
7599 gen_swap_half(tmp2
);
7600 gen_smul_dual(tmp
, tmp2
);
7601 /* This addition cannot overflow. */
7602 if (insn
& (1 << 22)) {
7603 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7605 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7610 tmp2
= load_reg(s
, rs
);
7611 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7615 case 3: /* 32 * 16 -> 32msb */
7617 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7620 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7621 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7623 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7626 tmp2
= load_reg(s
, rs
);
7627 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7631 case 5: case 6: /* 32 * 32 -> 32msb */
7632 gen_imull(tmp
, tmp2
);
7633 if (insn
& (1 << 5)) {
7634 gen_roundqd(tmp
, tmp2
);
7641 tmp2
= load_reg(s
, rs
);
7642 if (insn
& (1 << 21)) {
7643 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7645 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7650 case 7: /* Unsigned sum of absolute differences. */
7651 gen_helper_usad8(tmp
, tmp
, tmp2
);
7654 tmp2
= load_reg(s
, rs
);
7655 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7660 store_reg(s
, rd
, tmp
);
7662 case 6: case 7: /* 64-bit multiply, Divide. */
7663 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7664 tmp
= load_reg(s
, rn
);
7665 tmp2
= load_reg(s
, rm
);
7666 if ((op
& 0x50) == 0x10) {
7668 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7671 gen_helper_udiv(tmp
, tmp
, tmp2
);
7673 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7675 store_reg(s
, rd
, tmp
);
7676 } else if ((op
& 0xe) == 0xc) {
7677 /* Dual multiply accumulate long. */
7679 gen_swap_half(tmp2
);
7680 gen_smul_dual(tmp
, tmp2
);
7682 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7684 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7688 tmp64
= tcg_temp_new_i64();
7689 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7691 gen_addq(s
, tmp64
, rs
, rd
);
7692 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7695 /* Unsigned 64-bit multiply */
7696 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7700 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7702 tmp64
= tcg_temp_new_i64();
7703 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7706 /* Signed 64-bit multiply */
7707 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7712 gen_addq_lo(s
, tmp64
, rs
);
7713 gen_addq_lo(s
, tmp64
, rd
);
7714 } else if (op
& 0x40) {
7715 /* 64-bit accumulate. */
7716 gen_addq(s
, tmp64
, rs
, rd
);
7718 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7723 case 6: case 7: case 14: case 15:
7725 if (((insn
>> 24) & 3) == 3) {
7726 /* Translate into the equivalent ARM encoding. */
7727 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7728 if (disas_neon_data_insn(env
, s
, insn
))
7731 if (insn
& (1 << 28))
7733 if (disas_coproc_insn (env
, s
, insn
))
7737 case 8: case 9: case 10: case 11:
7738 if (insn
& (1 << 15)) {
7739 /* Branches, misc control. */
7740 if (insn
& 0x5000) {
7741 /* Unconditional branch. */
7742 /* signextend(hw1[10:0]) -> offset[:12]. */
7743 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7744 /* hw1[10:0] -> offset[11:1]. */
7745 offset
|= (insn
& 0x7ff) << 1;
7746 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7747 offset[24:22] already have the same value because of the
7748 sign extension above. */
7749 offset
^= ((~insn
) & (1 << 13)) << 10;
7750 offset
^= ((~insn
) & (1 << 11)) << 11;
7752 if (insn
& (1 << 14)) {
7753 /* Branch and link. */
7754 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7758 if (insn
& (1 << 12)) {
7763 offset
&= ~(uint32_t)2;
7764 gen_bx_im(s
, offset
);
7766 } else if (((insn
>> 23) & 7) == 7) {
7768 if (insn
& (1 << 13))
7771 if (insn
& (1 << 26)) {
7772 /* Secure monitor call (v6Z) */
7773 goto illegal_op
; /* not implemented. */
7775 op
= (insn
>> 20) & 7;
7777 case 0: /* msr cpsr. */
7779 tmp
= load_reg(s
, rn
);
7780 addr
= tcg_const_i32(insn
& 0xff);
7781 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7786 case 1: /* msr spsr. */
7789 tmp
= load_reg(s
, rn
);
7791 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7795 case 2: /* cps, nop-hint. */
7796 if (((insn
>> 8) & 7) == 0) {
7797 gen_nop_hint(s
, insn
& 0xff);
7799 /* Implemented as NOP in user mode. */
7804 if (insn
& (1 << 10)) {
7805 if (insn
& (1 << 7))
7807 if (insn
& (1 << 6))
7809 if (insn
& (1 << 5))
7811 if (insn
& (1 << 9))
7812 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7814 if (insn
& (1 << 8)) {
7816 imm
|= (insn
& 0x1f);
7819 gen_set_psr_im(s
, offset
, 0, imm
);
7822 case 3: /* Special control operations. */
7823 op
= (insn
>> 4) & 0xf;
7826 gen_helper_clrex(cpu_env
);
7831 /* These execute as NOPs. */
7839 /* Trivial implementation equivalent to bx. */
7840 tmp
= load_reg(s
, rn
);
7843 case 5: /* Exception return. */
7844 /* Unpredictable in user mode. */
7846 case 6: /* mrs cpsr. */
7849 addr
= tcg_const_i32(insn
& 0xff);
7850 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7852 gen_helper_cpsr_read(tmp
);
7854 store_reg(s
, rd
, tmp
);
7856 case 7: /* mrs spsr. */
7857 /* Not accessible in user mode. */
7858 if (IS_USER(s
) || IS_M(env
))
7860 tmp
= load_cpu_field(spsr
);
7861 store_reg(s
, rd
, tmp
);
7866 /* Conditional branch. */
7867 op
= (insn
>> 22) & 0xf;
7868 /* Generate a conditional jump to next instruction. */
7869 s
->condlabel
= gen_new_label();
7870 gen_test_cc(op
^ 1, s
->condlabel
);
7873 /* offset[11:1] = insn[10:0] */
7874 offset
= (insn
& 0x7ff) << 1;
7875 /* offset[17:12] = insn[21:16]. */
7876 offset
|= (insn
& 0x003f0000) >> 4;
7877 /* offset[31:20] = insn[26]. */
7878 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7879 /* offset[18] = insn[13]. */
7880 offset
|= (insn
& (1 << 13)) << 5;
7881 /* offset[19] = insn[11]. */
7882 offset
|= (insn
& (1 << 11)) << 8;
7884 /* jump to the offset */
7885 gen_jmp(s
, s
->pc
+ offset
);
7888 /* Data processing immediate. */
7889 if (insn
& (1 << 25)) {
7890 if (insn
& (1 << 24)) {
7891 if (insn
& (1 << 20))
7893 /* Bitfield/Saturate. */
7894 op
= (insn
>> 21) & 7;
7896 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7899 tcg_gen_movi_i32(tmp
, 0);
7901 tmp
= load_reg(s
, rn
);
7904 case 2: /* Signed bitfield extract. */
7906 if (shift
+ imm
> 32)
7909 gen_sbfx(tmp
, shift
, imm
);
7911 case 6: /* Unsigned bitfield extract. */
7913 if (shift
+ imm
> 32)
7916 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7918 case 3: /* Bitfield insert/clear. */
7921 imm
= imm
+ 1 - shift
;
7923 tmp2
= load_reg(s
, rd
);
7924 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7930 default: /* Saturate. */
7933 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7935 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7937 tmp2
= tcg_const_i32(imm
);
7940 if ((op
& 1) && shift
== 0)
7941 gen_helper_usat16(tmp
, tmp
, tmp2
);
7943 gen_helper_usat(tmp
, tmp
, tmp2
);
7946 if ((op
& 1) && shift
== 0)
7947 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7949 gen_helper_ssat(tmp
, tmp
, tmp2
);
7953 store_reg(s
, rd
, tmp
);
7955 imm
= ((insn
& 0x04000000) >> 15)
7956 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7957 if (insn
& (1 << 22)) {
7958 /* 16-bit immediate. */
7959 imm
|= (insn
>> 4) & 0xf000;
7960 if (insn
& (1 << 23)) {
7962 tmp
= load_reg(s
, rd
);
7963 tcg_gen_ext16u_i32(tmp
, tmp
);
7964 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7968 tcg_gen_movi_i32(tmp
, imm
);
7971 /* Add/sub 12-bit immediate. */
7973 offset
= s
->pc
& ~(uint32_t)3;
7974 if (insn
& (1 << 23))
7979 tcg_gen_movi_i32(tmp
, offset
);
7981 tmp
= load_reg(s
, rn
);
7982 if (insn
& (1 << 23))
7983 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7985 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7988 store_reg(s
, rd
, tmp
);
7991 int shifter_out
= 0;
7992 /* modified 12-bit immediate. */
7993 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7994 imm
= (insn
& 0xff);
7997 /* Nothing to do. */
7999 case 1: /* 00XY00XY */
8002 case 2: /* XY00XY00 */
8006 case 3: /* XYXYXYXY */
8010 default: /* Rotated constant. */
8011 shift
= (shift
<< 1) | (imm
>> 7);
8013 imm
= imm
<< (32 - shift
);
8018 tcg_gen_movi_i32(tmp2
, imm
);
8019 rn
= (insn
>> 16) & 0xf;
8022 tcg_gen_movi_i32(tmp
, 0);
8024 tmp
= load_reg(s
, rn
);
8026 op
= (insn
>> 21) & 0xf;
8027 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8028 shifter_out
, tmp
, tmp2
))
8031 rd
= (insn
>> 8) & 0xf;
8033 store_reg(s
, rd
, tmp
);
8040 case 12: /* Load/store single data item. */
8045 if ((insn
& 0x01100000) == 0x01000000) {
8046 if (disas_neon_ls_insn(env
, s
, insn
))
8054 /* s->pc has already been incremented by 4. */
8055 imm
= s
->pc
& 0xfffffffc;
8056 if (insn
& (1 << 23))
8057 imm
+= insn
& 0xfff;
8059 imm
-= insn
& 0xfff;
8060 tcg_gen_movi_i32(addr
, imm
);
8062 addr
= load_reg(s
, rn
);
8063 if (insn
& (1 << 23)) {
8064 /* Positive offset. */
8066 tcg_gen_addi_i32(addr
, addr
, imm
);
8068 op
= (insn
>> 8) & 7;
8071 case 0: case 8: /* Shifted Register. */
8072 shift
= (insn
>> 4) & 0xf;
8075 tmp
= load_reg(s
, rm
);
8077 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8078 tcg_gen_add_i32(addr
, addr
, tmp
);
8081 case 4: /* Negative offset. */
8082 tcg_gen_addi_i32(addr
, addr
, -imm
);
8084 case 6: /* User privilege. */
8085 tcg_gen_addi_i32(addr
, addr
, imm
);
8088 case 1: /* Post-decrement. */
8091 case 3: /* Post-increment. */
8095 case 5: /* Pre-decrement. */
8098 case 7: /* Pre-increment. */
8099 tcg_gen_addi_i32(addr
, addr
, imm
);
8107 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8108 if (insn
& (1 << 20)) {
8110 if (rs
== 15 && op
!= 2) {
8113 /* Memory hint. Implemented as NOP. */
8116 case 0: tmp
= gen_ld8u(addr
, user
); break;
8117 case 4: tmp
= gen_ld8s(addr
, user
); break;
8118 case 1: tmp
= gen_ld16u(addr
, user
); break;
8119 case 5: tmp
= gen_ld16s(addr
, user
); break;
8120 case 2: tmp
= gen_ld32(addr
, user
); break;
8121 default: goto illegal_op
;
8126 store_reg(s
, rs
, tmp
);
8133 tmp
= load_reg(s
, rs
);
8135 case 0: gen_st8(tmp
, addr
, user
); break;
8136 case 1: gen_st16(tmp
, addr
, user
); break;
8137 case 2: gen_st32(tmp
, addr
, user
); break;
8138 default: goto illegal_op
;
8142 tcg_gen_addi_i32(addr
, addr
, imm
);
8144 store_reg(s
, rn
, addr
);
8158 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8160 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8167 if (s
->condexec_mask
) {
8168 cond
= s
->condexec_cond
;
8169 s
->condlabel
= gen_new_label();
8170 gen_test_cc(cond
^ 1, s
->condlabel
);
8174 insn
= lduw_code(s
->pc
);
8177 switch (insn
>> 12) {
8181 op
= (insn
>> 11) & 3;
8184 rn
= (insn
>> 3) & 7;
8185 tmp
= load_reg(s
, rn
);
8186 if (insn
& (1 << 10)) {
8189 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8192 rm
= (insn
>> 6) & 7;
8193 tmp2
= load_reg(s
, rm
);
8195 if (insn
& (1 << 9)) {
8196 if (s
->condexec_mask
)
8197 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8199 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8201 if (s
->condexec_mask
)
8202 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8204 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8207 store_reg(s
, rd
, tmp
);
8209 /* shift immediate */
8210 rm
= (insn
>> 3) & 7;
8211 shift
= (insn
>> 6) & 0x1f;
8212 tmp
= load_reg(s
, rm
);
8213 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8214 if (!s
->condexec_mask
)
8216 store_reg(s
, rd
, tmp
);
8220 /* arithmetic large immediate */
8221 op
= (insn
>> 11) & 3;
8222 rd
= (insn
>> 8) & 0x7;
8223 if (op
== 0) { /* mov */
8225 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8226 if (!s
->condexec_mask
)
8228 store_reg(s
, rd
, tmp
);
8230 tmp
= load_reg(s
, rd
);
8232 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8235 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8240 if (s
->condexec_mask
)
8241 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8243 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8245 store_reg(s
, rd
, tmp
);
8248 if (s
->condexec_mask
)
8249 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8251 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8253 store_reg(s
, rd
, tmp
);
8259 if (insn
& (1 << 11)) {
8260 rd
= (insn
>> 8) & 7;
8261 /* load pc-relative. Bit 1 of PC is ignored. */
8262 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8263 val
&= ~(uint32_t)2;
8265 tcg_gen_movi_i32(addr
, val
);
8266 tmp
= gen_ld32(addr
, IS_USER(s
));
8268 store_reg(s
, rd
, tmp
);
8271 if (insn
& (1 << 10)) {
8272 /* data processing extended or blx */
8273 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8274 rm
= (insn
>> 3) & 0xf;
8275 op
= (insn
>> 8) & 3;
8278 tmp
= load_reg(s
, rd
);
8279 tmp2
= load_reg(s
, rm
);
8280 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8282 store_reg(s
, rd
, tmp
);
8285 tmp
= load_reg(s
, rd
);
8286 tmp2
= load_reg(s
, rm
);
8287 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8291 case 2: /* mov/cpy */
8292 tmp
= load_reg(s
, rm
);
8293 store_reg(s
, rd
, tmp
);
8295 case 3:/* branch [and link] exchange thumb register */
8296 tmp
= load_reg(s
, rm
);
8297 if (insn
& (1 << 7)) {
8298 val
= (uint32_t)s
->pc
| 1;
8300 tcg_gen_movi_i32(tmp2
, val
);
8301 store_reg(s
, 14, tmp2
);
8309 /* data processing register */
8311 rm
= (insn
>> 3) & 7;
8312 op
= (insn
>> 6) & 0xf;
8313 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8314 /* the shift/rotate ops want the operands backwards */
8323 if (op
== 9) { /* neg */
8325 tcg_gen_movi_i32(tmp
, 0);
8326 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8327 tmp
= load_reg(s
, rd
);
8332 tmp2
= load_reg(s
, rm
);
8335 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8336 if (!s
->condexec_mask
)
8340 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8341 if (!s
->condexec_mask
)
8345 if (s
->condexec_mask
) {
8346 gen_helper_shl(tmp2
, tmp2
, tmp
);
8348 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8353 if (s
->condexec_mask
) {
8354 gen_helper_shr(tmp2
, tmp2
, tmp
);
8356 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8361 if (s
->condexec_mask
) {
8362 gen_helper_sar(tmp2
, tmp2
, tmp
);
8364 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8369 if (s
->condexec_mask
)
8372 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8375 if (s
->condexec_mask
)
8376 gen_sub_carry(tmp
, tmp
, tmp2
);
8378 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8381 if (s
->condexec_mask
) {
8382 gen_helper_ror(tmp2
, tmp2
, tmp
);
8384 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8389 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8394 if (s
->condexec_mask
)
8395 tcg_gen_neg_i32(tmp
, tmp2
);
8397 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8400 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8404 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8408 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8409 if (!s
->condexec_mask
)
8413 gen_mull(tmp
, tmp2
);
8414 if (!s
->condexec_mask
)
8418 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8419 if (!s
->condexec_mask
)
8423 tcg_gen_not_i32(tmp2
, tmp2
);
8424 if (!s
->condexec_mask
)
8432 store_reg(s
, rm
, tmp2
);
8436 store_reg(s
, rd
, tmp
);
8446 /* load/store register offset. */
8448 rn
= (insn
>> 3) & 7;
8449 rm
= (insn
>> 6) & 7;
8450 op
= (insn
>> 9) & 7;
8451 addr
= load_reg(s
, rn
);
8452 tmp
= load_reg(s
, rm
);
8453 tcg_gen_add_i32(addr
, addr
, tmp
);
8456 if (op
< 3) /* store */
8457 tmp
= load_reg(s
, rd
);
8461 gen_st32(tmp
, addr
, IS_USER(s
));
8464 gen_st16(tmp
, addr
, IS_USER(s
));
8467 gen_st8(tmp
, addr
, IS_USER(s
));
8470 tmp
= gen_ld8s(addr
, IS_USER(s
));
8473 tmp
= gen_ld32(addr
, IS_USER(s
));
8476 tmp
= gen_ld16u(addr
, IS_USER(s
));
8479 tmp
= gen_ld8u(addr
, IS_USER(s
));
8482 tmp
= gen_ld16s(addr
, IS_USER(s
));
8485 if (op
>= 3) /* load */
8486 store_reg(s
, rd
, tmp
);
8491 /* load/store word immediate offset */
8493 rn
= (insn
>> 3) & 7;
8494 addr
= load_reg(s
, rn
);
8495 val
= (insn
>> 4) & 0x7c;
8496 tcg_gen_addi_i32(addr
, addr
, val
);
8498 if (insn
& (1 << 11)) {
8500 tmp
= gen_ld32(addr
, IS_USER(s
));
8501 store_reg(s
, rd
, tmp
);
8504 tmp
= load_reg(s
, rd
);
8505 gen_st32(tmp
, addr
, IS_USER(s
));
8511 /* load/store byte immediate offset */
8513 rn
= (insn
>> 3) & 7;
8514 addr
= load_reg(s
, rn
);
8515 val
= (insn
>> 6) & 0x1f;
8516 tcg_gen_addi_i32(addr
, addr
, val
);
8518 if (insn
& (1 << 11)) {
8520 tmp
= gen_ld8u(addr
, IS_USER(s
));
8521 store_reg(s
, rd
, tmp
);
8524 tmp
= load_reg(s
, rd
);
8525 gen_st8(tmp
, addr
, IS_USER(s
));
8531 /* load/store halfword immediate offset */
8533 rn
= (insn
>> 3) & 7;
8534 addr
= load_reg(s
, rn
);
8535 val
= (insn
>> 5) & 0x3e;
8536 tcg_gen_addi_i32(addr
, addr
, val
);
8538 if (insn
& (1 << 11)) {
8540 tmp
= gen_ld16u(addr
, IS_USER(s
));
8541 store_reg(s
, rd
, tmp
);
8544 tmp
= load_reg(s
, rd
);
8545 gen_st16(tmp
, addr
, IS_USER(s
));
8551 /* load/store from stack */
8552 rd
= (insn
>> 8) & 7;
8553 addr
= load_reg(s
, 13);
8554 val
= (insn
& 0xff) * 4;
8555 tcg_gen_addi_i32(addr
, addr
, val
);
8557 if (insn
& (1 << 11)) {
8559 tmp
= gen_ld32(addr
, IS_USER(s
));
8560 store_reg(s
, rd
, tmp
);
8563 tmp
= load_reg(s
, rd
);
8564 gen_st32(tmp
, addr
, IS_USER(s
));
8570 /* add to high reg */
8571 rd
= (insn
>> 8) & 7;
8572 if (insn
& (1 << 11)) {
8574 tmp
= load_reg(s
, 13);
8576 /* PC. bit 1 is ignored. */
8578 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8580 val
= (insn
& 0xff) * 4;
8581 tcg_gen_addi_i32(tmp
, tmp
, val
);
8582 store_reg(s
, rd
, tmp
);
8587 op
= (insn
>> 8) & 0xf;
8590 /* adjust stack pointer */
8591 tmp
= load_reg(s
, 13);
8592 val
= (insn
& 0x7f) * 4;
8593 if (insn
& (1 << 7))
8594 val
= -(int32_t)val
;
8595 tcg_gen_addi_i32(tmp
, tmp
, val
);
8596 store_reg(s
, 13, tmp
);
8599 case 2: /* sign/zero extend. */
8602 rm
= (insn
>> 3) & 7;
8603 tmp
= load_reg(s
, rm
);
8604 switch ((insn
>> 6) & 3) {
8605 case 0: gen_sxth(tmp
); break;
8606 case 1: gen_sxtb(tmp
); break;
8607 case 2: gen_uxth(tmp
); break;
8608 case 3: gen_uxtb(tmp
); break;
8610 store_reg(s
, rd
, tmp
);
8612 case 4: case 5: case 0xc: case 0xd:
8614 addr
= load_reg(s
, 13);
8615 if (insn
& (1 << 8))
8619 for (i
= 0; i
< 8; i
++) {
8620 if (insn
& (1 << i
))
8623 if ((insn
& (1 << 11)) == 0) {
8624 tcg_gen_addi_i32(addr
, addr
, -offset
);
8626 for (i
= 0; i
< 8; i
++) {
8627 if (insn
& (1 << i
)) {
8628 if (insn
& (1 << 11)) {
8630 tmp
= gen_ld32(addr
, IS_USER(s
));
8631 store_reg(s
, i
, tmp
);
8634 tmp
= load_reg(s
, i
);
8635 gen_st32(tmp
, addr
, IS_USER(s
));
8637 /* advance to the next address. */
8638 tcg_gen_addi_i32(addr
, addr
, 4);
8642 if (insn
& (1 << 8)) {
8643 if (insn
& (1 << 11)) {
8645 tmp
= gen_ld32(addr
, IS_USER(s
));
8646 /* don't set the pc until the rest of the instruction
8650 tmp
= load_reg(s
, 14);
8651 gen_st32(tmp
, addr
, IS_USER(s
));
8653 tcg_gen_addi_i32(addr
, addr
, 4);
8655 if ((insn
& (1 << 11)) == 0) {
8656 tcg_gen_addi_i32(addr
, addr
, -offset
);
8658 /* write back the new stack pointer */
8659 store_reg(s
, 13, addr
);
8660 /* set the new PC value */
8661 if ((insn
& 0x0900) == 0x0900)
8665 case 1: case 3: case 9: case 11: /* czb */
8667 tmp
= load_reg(s
, rm
);
8668 s
->condlabel
= gen_new_label();
8670 if (insn
& (1 << 11))
8671 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8673 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8675 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8676 val
= (uint32_t)s
->pc
+ 2;
8681 case 15: /* IT, nop-hint. */
8682 if ((insn
& 0xf) == 0) {
8683 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8687 s
->condexec_cond
= (insn
>> 4) & 0xe;
8688 s
->condexec_mask
= insn
& 0x1f;
8689 /* No actual code generated for this insn, just setup state. */
8692 case 0xe: /* bkpt */
8693 gen_set_condexec(s
);
8694 gen_set_pc_im(s
->pc
- 2);
8695 gen_exception(EXCP_BKPT
);
8696 s
->is_jmp
= DISAS_JUMP
;
8701 rn
= (insn
>> 3) & 0x7;
8703 tmp
= load_reg(s
, rn
);
8704 switch ((insn
>> 6) & 3) {
8705 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8706 case 1: gen_rev16(tmp
); break;
8707 case 3: gen_revsh(tmp
); break;
8708 default: goto illegal_op
;
8710 store_reg(s
, rd
, tmp
);
8718 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8721 addr
= tcg_const_i32(16);
8722 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8726 addr
= tcg_const_i32(17);
8727 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8731 if (insn
& (1 << 4))
8732 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8735 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8745 /* load/store multiple */
8746 rn
= (insn
>> 8) & 0x7;
8747 addr
= load_reg(s
, rn
);
8748 for (i
= 0; i
< 8; i
++) {
8749 if (insn
& (1 << i
)) {
8750 if (insn
& (1 << 11)) {
8752 tmp
= gen_ld32(addr
, IS_USER(s
));
8753 store_reg(s
, i
, tmp
);
8756 tmp
= load_reg(s
, i
);
8757 gen_st32(tmp
, addr
, IS_USER(s
));
8759 /* advance to the next address */
8760 tcg_gen_addi_i32(addr
, addr
, 4);
8763 /* Base register writeback. */
8764 if ((insn
& (1 << rn
)) == 0) {
8765 store_reg(s
, rn
, addr
);
8772 /* conditional branch or swi */
8773 cond
= (insn
>> 8) & 0xf;
8779 gen_set_condexec(s
);
8780 gen_set_pc_im(s
->pc
);
8781 s
->is_jmp
= DISAS_SWI
;
8784 /* generate a conditional jump to next instruction */
8785 s
->condlabel
= gen_new_label();
8786 gen_test_cc(cond
^ 1, s
->condlabel
);
8789 /* jump to the offset */
8790 val
= (uint32_t)s
->pc
+ 2;
8791 offset
= ((int32_t)insn
<< 24) >> 24;
8797 if (insn
& (1 << 11)) {
8798 if (disas_thumb2_insn(env
, s
, insn
))
8802 /* unconditional branch */
8803 val
= (uint32_t)s
->pc
;
8804 offset
= ((int32_t)insn
<< 21) >> 21;
8805 val
+= (offset
<< 1) + 2;
8810 if (disas_thumb2_insn(env
, s
, insn
))
8816 gen_set_condexec(s
);
8817 gen_set_pc_im(s
->pc
- 4);
8818 gen_exception(EXCP_UDEF
);
8819 s
->is_jmp
= DISAS_JUMP
;
8823 gen_set_condexec(s
);
8824 gen_set_pc_im(s
->pc
- 2);
8825 gen_exception(EXCP_UDEF
);
8826 s
->is_jmp
= DISAS_JUMP
;
8829 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8830 basic block 'tb'. If search_pc is TRUE, also generate PC
8831 information for each intermediate instruction. */
8832 static inline void gen_intermediate_code_internal(CPUState
*env
,
8833 TranslationBlock
*tb
,
8836 DisasContext dc1
, *dc
= &dc1
;
8838 uint16_t *gen_opc_end
;
8840 target_ulong pc_start
;
8841 uint32_t next_page_start
;
8845 /* generate intermediate code */
8852 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8854 dc
->is_jmp
= DISAS_NEXT
;
8856 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8858 dc
->thumb
= env
->thumb
;
8859 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8860 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8861 #if !defined(CONFIG_USER_ONLY)
8863 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8865 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8868 cpu_F0s
= tcg_temp_new_i32();
8869 cpu_F1s
= tcg_temp_new_i32();
8870 cpu_F0d
= tcg_temp_new_i64();
8871 cpu_F1d
= tcg_temp_new_i64();
8874 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8875 cpu_M0
= tcg_temp_new_i64();
8876 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8879 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8881 max_insns
= CF_COUNT_MASK
;
8884 /* Reset the conditional execution bits immediately. This avoids
8885 complications trying to do it at the end of the block. */
8886 if (env
->condexec_bits
)
8888 TCGv tmp
= new_tmp();
8889 tcg_gen_movi_i32(tmp
, 0);
8890 store_cpu_field(tmp
, condexec_bits
);
8893 #ifdef CONFIG_USER_ONLY
8894 /* Intercept jump to the magic kernel page. */
8895 if (dc
->pc
>= 0xffff0000) {
8896 /* We always get here via a jump, so know we are not in a
8897 conditional execution block. */
8898 gen_exception(EXCP_KERNEL_TRAP
);
8899 dc
->is_jmp
= DISAS_UPDATE
;
8903 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8904 /* We always get here via a jump, so know we are not in a
8905 conditional execution block. */
8906 gen_exception(EXCP_EXCEPTION_EXIT
);
8907 dc
->is_jmp
= DISAS_UPDATE
;
8912 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8913 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8914 if (bp
->pc
== dc
->pc
) {
8915 gen_set_condexec(dc
);
8916 gen_set_pc_im(dc
->pc
);
8917 gen_exception(EXCP_DEBUG
);
8918 dc
->is_jmp
= DISAS_JUMP
;
8919 /* Advance PC so that clearing the breakpoint will
8920 invalidate this TB. */
8922 goto done_generating
;
8928 j
= gen_opc_ptr
- gen_opc_buf
;
8932 gen_opc_instr_start
[lj
++] = 0;
8934 gen_opc_pc
[lj
] = dc
->pc
;
8935 gen_opc_instr_start
[lj
] = 1;
8936 gen_opc_icount
[lj
] = num_insns
;
8939 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8943 disas_thumb_insn(env
, dc
);
8944 if (dc
->condexec_mask
) {
8945 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8946 | ((dc
->condexec_mask
>> 4) & 1);
8947 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8948 if (dc
->condexec_mask
== 0) {
8949 dc
->condexec_cond
= 0;
8953 disas_arm_insn(env
, dc
);
8956 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8960 if (dc
->condjmp
&& !dc
->is_jmp
) {
8961 gen_set_label(dc
->condlabel
);
8964 /* Translation stops when a conditional branch is encountered.
8965 * Otherwise the subsequent code could get translated several times.
8966 * Also stop translation when a page boundary is reached. This
8967 * ensures prefetch aborts occur at the right place. */
8969 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8970 !env
->singlestep_enabled
&&
8972 dc
->pc
< next_page_start
&&
8973 num_insns
< max_insns
);
8975 if (tb
->cflags
& CF_LAST_IO
) {
8977 /* FIXME: This can theoretically happen with self-modifying
8979 cpu_abort(env
, "IO on conditional branch instruction");
8984 /* At this stage dc->condjmp will only be set when the skipped
8985 instruction was a conditional branch or trap, and the PC has
8986 already been written. */
8987 if (unlikely(env
->singlestep_enabled
)) {
8988 /* Make sure the pc is updated, and raise a debug exception. */
8990 gen_set_condexec(dc
);
8991 if (dc
->is_jmp
== DISAS_SWI
) {
8992 gen_exception(EXCP_SWI
);
8994 gen_exception(EXCP_DEBUG
);
8996 gen_set_label(dc
->condlabel
);
8998 if (dc
->condjmp
|| !dc
->is_jmp
) {
8999 gen_set_pc_im(dc
->pc
);
9002 gen_set_condexec(dc
);
9003 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
9004 gen_exception(EXCP_SWI
);
9006 /* FIXME: Single stepping a WFI insn will not halt
9008 gen_exception(EXCP_DEBUG
);
9011 /* While branches must always occur at the end of an IT block,
9012 there are a few other things that can cause us to terminate
9013 the TB in the middel of an IT block:
9014 - Exception generating instructions (bkpt, swi, undefined).
9016 - Hardware watchpoints.
9017 Hardware breakpoints have already been handled and skip this code.
9019 gen_set_condexec(dc
);
9020 switch(dc
->is_jmp
) {
9022 gen_goto_tb(dc
, 1, dc
->pc
);
9027 /* indicate that the hash table must be used to find the next TB */
9031 /* nothing more to generate */
9037 gen_exception(EXCP_SWI
);
9041 gen_set_label(dc
->condlabel
);
9042 gen_set_condexec(dc
);
9043 gen_goto_tb(dc
, 1, dc
->pc
);
9049 gen_icount_end(tb
, num_insns
);
9050 *gen_opc_ptr
= INDEX_op_end
;
9053 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9054 qemu_log("----------------\n");
9055 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9056 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9061 j
= gen_opc_ptr
- gen_opc_buf
;
9064 gen_opc_instr_start
[lj
++] = 0;
9066 tb
->size
= dc
->pc
- pc_start
;
9067 tb
->icount
= num_insns
;
9071 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9073 gen_intermediate_code_internal(env
, tb
, 0);
9076 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9078 gen_intermediate_code_internal(env
, tb
, 1);
9081 static const char *cpu_mode_names
[16] = {
9082 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9083 "???", "???", "???", "und", "???", "???", "???", "sys"
9086 void cpu_dump_state(CPUState
*env
, FILE *f
,
9087 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9097 /* ??? This assumes float64 and double have the same layout.
9098 Oh well, it's only debug dumps. */
9107 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9109 cpu_fprintf(f
, "\n");
9111 cpu_fprintf(f
, " ");
9113 psr
= cpsr_read(env
);
9114 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9116 psr
& (1 << 31) ? 'N' : '-',
9117 psr
& (1 << 30) ? 'Z' : '-',
9118 psr
& (1 << 29) ? 'C' : '-',
9119 psr
& (1 << 28) ? 'V' : '-',
9120 psr
& CPSR_T
? 'T' : 'A',
9121 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9124 for (i
= 0; i
< 16; i
++) {
9125 d
.d
= env
->vfp
.regs
[i
];
9129 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9130 i
* 2, (int)s0
.i
, s0
.s
,
9131 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9132 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9135 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9139 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9140 unsigned long searched_pc
, int pc_pos
, void *puc
)
9142 env
->regs
[15] = gen_opc_pc
[pc_pos
];