4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
78 static TCGv_i32 cpu_R
[16];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s
, cpu_F1s
;
82 static TCGv_i64 cpu_F0d
, cpu_F1d
;
84 #include "gen-icount.h"
86 static const char *regnames
[] =
87 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
88 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
90 /* initialize TCG globals. */
91 void arm_translate_init(void)
95 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
97 for (i
= 0; i
< 16; i
++) {
98 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
99 offsetof(CPUState
, regs
[i
]),
107 static int num_temps
;
109 /* Allocate a temporary variable. */
110 static TCGv_i32
new_tmp(void)
113 return tcg_temp_new_i32();
116 /* Release a temporary variable. */
117 static void dead_tmp(TCGv tmp
)
123 static inline TCGv
load_cpu_offset(int offset
)
125 TCGv tmp
= new_tmp();
126 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
130 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
132 static inline void store_cpu_offset(TCGv var
, int offset
)
134 tcg_gen_st_i32(var
, cpu_env
, offset
);
138 #define store_cpu_field(var, name) \
139 store_cpu_offset(var, offsetof(CPUState, name))
141 /* Set a variable to the value of a CPU register. */
142 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
146 /* normaly, since we updated PC, we need only to add one insn */
148 addr
= (long)s
->pc
+ 2;
150 addr
= (long)s
->pc
+ 4;
151 tcg_gen_movi_i32(var
, addr
);
153 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
157 /* Create a new temporary and set it to the value of a CPU register. */
158 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
160 TCGv tmp
= new_tmp();
161 load_reg_var(s
, tmp
, reg
);
165 /* Set a CPU register. The source must be a temporary and will be
167 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
170 tcg_gen_andi_i32(var
, var
, ~1);
171 s
->is_jmp
= DISAS_JUMP
;
173 tcg_gen_mov_i32(cpu_R
[reg
], var
);
177 /* Value extensions. */
178 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
179 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
180 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
181 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
183 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
184 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
187 static inline void gen_set_cpsr(TCGv var
, uint32_t mask
)
189 TCGv tmp_mask
= tcg_const_i32(mask
);
190 gen_helper_cpsr_write(var
, tmp_mask
);
191 tcg_temp_free_i32(tmp_mask
);
193 /* Set NZCV flags from the high 4 bits of var. */
194 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
196 static void gen_exception(int excp
)
198 TCGv tmp
= new_tmp();
199 tcg_gen_movi_i32(tmp
, excp
);
200 gen_helper_exception(tmp
);
204 static void gen_smul_dual(TCGv a
, TCGv b
)
206 TCGv tmp1
= new_tmp();
207 TCGv tmp2
= new_tmp();
208 tcg_gen_ext16s_i32(tmp1
, a
);
209 tcg_gen_ext16s_i32(tmp2
, b
);
210 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
212 tcg_gen_sari_i32(a
, a
, 16);
213 tcg_gen_sari_i32(b
, b
, 16);
214 tcg_gen_mul_i32(b
, b
, a
);
215 tcg_gen_mov_i32(a
, tmp1
);
219 /* Byteswap each halfword. */
220 static void gen_rev16(TCGv var
)
222 TCGv tmp
= new_tmp();
223 tcg_gen_shri_i32(tmp
, var
, 8);
224 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
225 tcg_gen_shli_i32(var
, var
, 8);
226 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
227 tcg_gen_or_i32(var
, var
, tmp
);
231 /* Byteswap low halfword and sign extend. */
232 static void gen_revsh(TCGv var
)
234 TCGv tmp
= new_tmp();
235 tcg_gen_shri_i32(tmp
, var
, 8);
236 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
237 tcg_gen_shli_i32(var
, var
, 8);
238 tcg_gen_ext8s_i32(var
, var
);
239 tcg_gen_or_i32(var
, var
, tmp
);
243 /* Unsigned bitfield extract. */
244 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
247 tcg_gen_shri_i32(var
, var
, shift
);
248 tcg_gen_andi_i32(var
, var
, mask
);
251 /* Signed bitfield extract. */
252 static void gen_sbfx(TCGv var
, int shift
, int width
)
257 tcg_gen_sari_i32(var
, var
, shift
);
258 if (shift
+ width
< 32) {
259 signbit
= 1u << (width
- 1);
260 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
261 tcg_gen_xori_i32(var
, var
, signbit
);
262 tcg_gen_subi_i32(var
, var
, signbit
);
266 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
267 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
269 tcg_gen_andi_i32(val
, val
, mask
);
270 tcg_gen_shli_i32(val
, val
, shift
);
271 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
272 tcg_gen_or_i32(dest
, base
, val
);
275 /* Round the top 32 bits of a 64-bit value. */
276 static void gen_roundqd(TCGv a
, TCGv b
)
278 tcg_gen_shri_i32(a
, a
, 31);
279 tcg_gen_add_i32(a
, a
, b
);
282 /* FIXME: Most targets have native widening multiplication.
283 It would be good to use that instead of a full wide multiply. */
284 /* 32x32->64 multiply. Marks inputs as dead. */
285 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
287 TCGv_i64 tmp1
= tcg_temp_new_i64();
288 TCGv_i64 tmp2
= tcg_temp_new_i64();
290 tcg_gen_extu_i32_i64(tmp1
, a
);
292 tcg_gen_extu_i32_i64(tmp2
, b
);
294 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
295 tcg_temp_free_i64(tmp2
);
299 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
301 TCGv_i64 tmp1
= tcg_temp_new_i64();
302 TCGv_i64 tmp2
= tcg_temp_new_i64();
304 tcg_gen_ext_i32_i64(tmp1
, a
);
306 tcg_gen_ext_i32_i64(tmp2
, b
);
308 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
309 tcg_temp_free_i64(tmp2
);
313 /* Unsigned 32x32->64 multiply. */
314 static void gen_mull(TCGv a
, TCGv b
)
316 TCGv_i64 tmp1
= tcg_temp_new_i64();
317 TCGv_i64 tmp2
= tcg_temp_new_i64();
319 tcg_gen_extu_i32_i64(tmp1
, a
);
320 tcg_gen_extu_i32_i64(tmp2
, b
);
321 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
322 tcg_temp_free_i64(tmp2
);
323 tcg_gen_trunc_i64_i32(a
, tmp1
);
324 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
325 tcg_gen_trunc_i64_i32(b
, tmp1
);
326 tcg_temp_free_i64(tmp1
);
329 /* Signed 32x32->64 multiply. */
330 static void gen_imull(TCGv a
, TCGv b
)
332 TCGv_i64 tmp1
= tcg_temp_new_i64();
333 TCGv_i64 tmp2
= tcg_temp_new_i64();
335 tcg_gen_ext_i32_i64(tmp1
, a
);
336 tcg_gen_ext_i32_i64(tmp2
, b
);
337 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
338 tcg_temp_free_i64(tmp2
);
339 tcg_gen_trunc_i64_i32(a
, tmp1
);
340 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
341 tcg_gen_trunc_i64_i32(b
, tmp1
);
342 tcg_temp_free_i64(tmp1
);
345 /* Swap low and high halfwords. */
346 static void gen_swap_half(TCGv var
)
348 TCGv tmp
= new_tmp();
349 tcg_gen_shri_i32(tmp
, var
, 16);
350 tcg_gen_shli_i32(var
, var
, 16);
351 tcg_gen_or_i32(var
, var
, tmp
);
355 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
356 tmp = (t0 ^ t1) & 0x8000;
359 t0 = (t0 + t1) ^ tmp;
362 static void gen_add16(TCGv t0
, TCGv t1
)
364 TCGv tmp
= new_tmp();
365 tcg_gen_xor_i32(tmp
, t0
, t1
);
366 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
367 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
368 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
369 tcg_gen_add_i32(t0
, t0
, t1
);
370 tcg_gen_xor_i32(t0
, t0
, tmp
);
375 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
377 /* Set CF to the top bit of var. */
378 static void gen_set_CF_bit31(TCGv var
)
380 TCGv tmp
= new_tmp();
381 tcg_gen_shri_i32(tmp
, var
, 31);
386 /* Set N and Z flags from var. */
387 static inline void gen_logic_CC(TCGv var
)
389 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
390 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
394 static void gen_adc(TCGv t0
, TCGv t1
)
397 tcg_gen_add_i32(t0
, t0
, t1
);
398 tmp
= load_cpu_field(CF
);
399 tcg_gen_add_i32(t0
, t0
, tmp
);
403 /* dest = T0 + T1 + CF. */
404 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
407 tcg_gen_add_i32(dest
, t0
, t1
);
408 tmp
= load_cpu_field(CF
);
409 tcg_gen_add_i32(dest
, dest
, tmp
);
413 /* dest = T0 - T1 + CF - 1. */
414 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
417 tcg_gen_sub_i32(dest
, t0
, t1
);
418 tmp
= load_cpu_field(CF
);
419 tcg_gen_add_i32(dest
, dest
, tmp
);
420 tcg_gen_subi_i32(dest
, dest
, 1);
424 /* T0 &= ~T1. Clobbers T1. */
425 /* FIXME: Implement bic natively. */
426 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
428 TCGv tmp
= new_tmp();
429 tcg_gen_not_i32(tmp
, t1
);
430 tcg_gen_and_i32(dest
, t0
, tmp
);
434 /* FIXME: Implement this natively. */
435 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
437 /* FIXME: Implement this natively. */
438 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
446 tcg_gen_shri_i32(tmp
, t1
, i
);
447 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
448 tcg_gen_or_i32(t0
, t1
, tmp
);
452 static void shifter_out_im(TCGv var
, int shift
)
454 TCGv tmp
= new_tmp();
456 tcg_gen_andi_i32(tmp
, var
, 1);
458 tcg_gen_shri_i32(tmp
, var
, shift
);
460 tcg_gen_andi_i32(tmp
, tmp
, 1);
466 /* Shift by immediate. Includes special handling for shift == 0. */
467 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
473 shifter_out_im(var
, 32 - shift
);
474 tcg_gen_shli_i32(var
, var
, shift
);
480 tcg_gen_shri_i32(var
, var
, 31);
483 tcg_gen_movi_i32(var
, 0);
486 shifter_out_im(var
, shift
- 1);
487 tcg_gen_shri_i32(var
, var
, shift
);
494 shifter_out_im(var
, shift
- 1);
497 tcg_gen_sari_i32(var
, var
, shift
);
499 case 3: /* ROR/RRX */
502 shifter_out_im(var
, shift
- 1);
503 tcg_gen_rori_i32(var
, var
, shift
); break;
505 TCGv tmp
= load_cpu_field(CF
);
507 shifter_out_im(var
, 0);
508 tcg_gen_shri_i32(var
, var
, 1);
509 tcg_gen_shli_i32(tmp
, tmp
, 31);
510 tcg_gen_or_i32(var
, var
, tmp
);
516 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
517 TCGv shift
, int flags
)
521 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
522 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
523 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
524 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
528 case 0: gen_helper_shl(var
, var
, shift
); break;
529 case 1: gen_helper_shr(var
, var
, shift
); break;
530 case 2: gen_helper_sar(var
, var
, shift
); break;
531 case 3: gen_helper_ror(var
, var
, shift
); break;
537 #define PAS_OP(pfx) \
539 case 0: gen_pas_helper(glue(pfx,add16)); break; \
540 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
541 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
542 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
543 case 4: gen_pas_helper(glue(pfx,add8)); break; \
544 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
546 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
551 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
553 tmp
= tcg_temp_new_ptr();
554 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
556 tcg_temp_free_ptr(tmp
);
559 tmp
= tcg_temp_new_ptr();
560 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
562 tcg_temp_free_ptr(tmp
);
564 #undef gen_pas_helper
565 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
578 #undef gen_pas_helper
583 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
584 #define PAS_OP(pfx) \
586 case 0: gen_pas_helper(glue(pfx,add8)); break; \
587 case 1: gen_pas_helper(glue(pfx,add16)); break; \
588 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
589 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
590 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
591 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
593 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
600 tmp
= tcg_temp_new_ptr();
601 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
603 tcg_temp_free_ptr(tmp
);
606 tmp
= tcg_temp_new_ptr();
607 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
609 tcg_temp_free_ptr(tmp
);
611 #undef gen_pas_helper
612 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
625 #undef gen_pas_helper
630 static void gen_test_cc(int cc
, int label
)
638 tmp
= load_cpu_field(ZF
);
639 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
642 tmp
= load_cpu_field(ZF
);
643 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
646 tmp
= load_cpu_field(CF
);
647 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
650 tmp
= load_cpu_field(CF
);
651 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
654 tmp
= load_cpu_field(NF
);
655 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
658 tmp
= load_cpu_field(NF
);
659 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
662 tmp
= load_cpu_field(VF
);
663 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
666 tmp
= load_cpu_field(VF
);
667 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
669 case 8: /* hi: C && !Z */
670 inv
= gen_new_label();
671 tmp
= load_cpu_field(CF
);
672 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
674 tmp
= load_cpu_field(ZF
);
675 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
678 case 9: /* ls: !C || Z */
679 tmp
= load_cpu_field(CF
);
680 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
682 tmp
= load_cpu_field(ZF
);
683 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
685 case 10: /* ge: N == V -> N ^ V == 0 */
686 tmp
= load_cpu_field(VF
);
687 tmp2
= load_cpu_field(NF
);
688 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
690 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
692 case 11: /* lt: N != V -> N ^ V != 0 */
693 tmp
= load_cpu_field(VF
);
694 tmp2
= load_cpu_field(NF
);
695 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
697 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
699 case 12: /* gt: !Z && N == V */
700 inv
= gen_new_label();
701 tmp
= load_cpu_field(ZF
);
702 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
704 tmp
= load_cpu_field(VF
);
705 tmp2
= load_cpu_field(NF
);
706 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
708 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
711 case 13: /* le: Z || N != V */
712 tmp
= load_cpu_field(ZF
);
713 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
715 tmp
= load_cpu_field(VF
);
716 tmp2
= load_cpu_field(NF
);
717 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
719 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
722 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
728 static const uint8_t table_logic_cc
[16] = {
747 /* Set PC and Thumb state from an immediate address. */
748 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
752 s
->is_jmp
= DISAS_UPDATE
;
753 if (s
->thumb
!= (addr
& 1)) {
755 tcg_gen_movi_i32(tmp
, addr
& 1);
756 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
759 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
762 /* Set PC and Thumb state from var. var is marked as dead. */
763 static inline void gen_bx(DisasContext
*s
, TCGv var
)
765 s
->is_jmp
= DISAS_UPDATE
;
766 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
767 tcg_gen_andi_i32(var
, var
, 1);
768 store_cpu_field(var
, thumb
);
771 /* Variant of store_reg which uses branch&exchange logic when storing
772 to r15 in ARM architecture v7 and above. The source must be a temporary
773 and will be marked as dead. */
774 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
777 if (reg
== 15 && ENABLE_ARCH_7
) {
780 store_reg(s
, reg
, var
);
784 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
786 TCGv tmp
= new_tmp();
787 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
790 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
792 TCGv tmp
= new_tmp();
793 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
796 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
798 TCGv tmp
= new_tmp();
799 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
802 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
804 TCGv tmp
= new_tmp();
805 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
808 static inline TCGv
gen_ld32(TCGv addr
, int index
)
810 TCGv tmp
= new_tmp();
811 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
814 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
816 tcg_gen_qemu_st8(val
, addr
, index
);
819 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
821 tcg_gen_qemu_st16(val
, addr
, index
);
824 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
826 tcg_gen_qemu_st32(val
, addr
, index
);
830 static inline void gen_set_pc_im(uint32_t val
)
832 tcg_gen_movi_i32(cpu_R
[15], val
);
835 /* Force a TB lookup after an instruction that changes the CPU state. */
836 static inline void gen_lookup_tb(DisasContext
*s
)
838 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
839 s
->is_jmp
= DISAS_UPDATE
;
842 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
845 int val
, rm
, shift
, shiftop
;
848 if (!(insn
& (1 << 25))) {
851 if (!(insn
& (1 << 23)))
854 tcg_gen_addi_i32(var
, var
, val
);
858 shift
= (insn
>> 7) & 0x1f;
859 shiftop
= (insn
>> 5) & 3;
860 offset
= load_reg(s
, rm
);
861 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
862 if (!(insn
& (1 << 23)))
863 tcg_gen_sub_i32(var
, var
, offset
);
865 tcg_gen_add_i32(var
, var
, offset
);
870 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
876 if (insn
& (1 << 22)) {
878 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
879 if (!(insn
& (1 << 23)))
883 tcg_gen_addi_i32(var
, var
, val
);
887 tcg_gen_addi_i32(var
, var
, extra
);
889 offset
= load_reg(s
, rm
);
890 if (!(insn
& (1 << 23)))
891 tcg_gen_sub_i32(var
, var
, offset
);
893 tcg_gen_add_i32(var
, var
, offset
);
898 #define VFP_OP2(name) \
899 static inline void gen_vfp_##name(int dp) \
902 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
904 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
914 static inline void gen_vfp_abs(int dp
)
917 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
919 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
922 static inline void gen_vfp_neg(int dp
)
925 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
927 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
930 static inline void gen_vfp_sqrt(int dp
)
933 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
935 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
938 static inline void gen_vfp_cmp(int dp
)
941 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
943 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
946 static inline void gen_vfp_cmpe(int dp
)
949 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
951 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
954 static inline void gen_vfp_F1_ld0(int dp
)
957 tcg_gen_movi_i64(cpu_F1d
, 0);
959 tcg_gen_movi_i32(cpu_F1s
, 0);
962 static inline void gen_vfp_uito(int dp
)
965 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
967 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
970 static inline void gen_vfp_sito(int dp
)
973 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
975 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
978 static inline void gen_vfp_toui(int dp
)
981 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
983 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
986 static inline void gen_vfp_touiz(int dp
)
989 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
991 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
994 static inline void gen_vfp_tosi(int dp
)
997 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
999 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1002 static inline void gen_vfp_tosiz(int dp
)
1005 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1007 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1010 #define VFP_GEN_FIX(name) \
1011 static inline void gen_vfp_##name(int dp, int shift) \
1013 TCGv tmp_shift = tcg_const_i32(shift); \
1015 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1017 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1018 tcg_temp_free_i32(tmp_shift); \
1030 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1033 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1035 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1038 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1041 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1043 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1047 vfp_reg_offset (int dp
, int reg
)
1050 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1052 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1053 + offsetof(CPU_DoubleU
, l
.upper
);
1055 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1056 + offsetof(CPU_DoubleU
, l
.lower
);
1060 /* Return the offset of a 32-bit piece of a NEON register.
1061 zero is the least significant end of the register. */
1063 neon_reg_offset (int reg
, int n
)
1067 return vfp_reg_offset(0, sreg
);
1070 static TCGv
neon_load_reg(int reg
, int pass
)
1072 TCGv tmp
= new_tmp();
1073 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1077 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1079 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1083 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1085 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1088 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1090 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1093 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1094 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1095 #define tcg_gen_st_f32 tcg_gen_st_i32
1096 #define tcg_gen_st_f64 tcg_gen_st_i64
1098 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1101 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1103 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1106 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1109 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1111 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1114 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1117 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1119 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1122 #define ARM_CP_RW_BIT (1 << 20)
1124 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1126 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1129 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1131 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1134 static inline TCGv
iwmmxt_load_creg(int reg
)
1136 TCGv var
= new_tmp();
1137 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1141 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1143 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1146 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1148 iwmmxt_store_reg(cpu_M0
, rn
);
1151 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1153 iwmmxt_load_reg(cpu_M0
, rn
);
1156 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1158 iwmmxt_load_reg(cpu_V1
, rn
);
1159 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1162 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1164 iwmmxt_load_reg(cpu_V1
, rn
);
1165 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1168 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1170 iwmmxt_load_reg(cpu_V1
, rn
);
1171 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1174 #define IWMMXT_OP(name) \
1175 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1177 iwmmxt_load_reg(cpu_V1, rn); \
1178 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1181 #define IWMMXT_OP_ENV(name) \
1182 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1184 iwmmxt_load_reg(cpu_V1, rn); \
1185 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1188 #define IWMMXT_OP_ENV_SIZE(name) \
1189 IWMMXT_OP_ENV(name##b) \
1190 IWMMXT_OP_ENV(name##w) \
1191 IWMMXT_OP_ENV(name##l)
1193 #define IWMMXT_OP_ENV1(name) \
1194 static inline void gen_op_iwmmxt_##name##_M0(void) \
1196 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1210 IWMMXT_OP_ENV_SIZE(unpackl
)
1211 IWMMXT_OP_ENV_SIZE(unpackh
)
1213 IWMMXT_OP_ENV1(unpacklub
)
1214 IWMMXT_OP_ENV1(unpackluw
)
1215 IWMMXT_OP_ENV1(unpacklul
)
1216 IWMMXT_OP_ENV1(unpackhub
)
1217 IWMMXT_OP_ENV1(unpackhuw
)
1218 IWMMXT_OP_ENV1(unpackhul
)
1219 IWMMXT_OP_ENV1(unpacklsb
)
1220 IWMMXT_OP_ENV1(unpacklsw
)
1221 IWMMXT_OP_ENV1(unpacklsl
)
1222 IWMMXT_OP_ENV1(unpackhsb
)
1223 IWMMXT_OP_ENV1(unpackhsw
)
1224 IWMMXT_OP_ENV1(unpackhsl
)
1226 IWMMXT_OP_ENV_SIZE(cmpeq
)
1227 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1228 IWMMXT_OP_ENV_SIZE(cmpgts
)
1230 IWMMXT_OP_ENV_SIZE(mins
)
1231 IWMMXT_OP_ENV_SIZE(minu
)
1232 IWMMXT_OP_ENV_SIZE(maxs
)
1233 IWMMXT_OP_ENV_SIZE(maxu
)
1235 IWMMXT_OP_ENV_SIZE(subn
)
1236 IWMMXT_OP_ENV_SIZE(addn
)
1237 IWMMXT_OP_ENV_SIZE(subu
)
1238 IWMMXT_OP_ENV_SIZE(addu
)
1239 IWMMXT_OP_ENV_SIZE(subs
)
1240 IWMMXT_OP_ENV_SIZE(adds
)
1242 IWMMXT_OP_ENV(avgb0
)
1243 IWMMXT_OP_ENV(avgb1
)
1244 IWMMXT_OP_ENV(avgw0
)
1245 IWMMXT_OP_ENV(avgw1
)
1249 IWMMXT_OP_ENV(packuw
)
1250 IWMMXT_OP_ENV(packul
)
1251 IWMMXT_OP_ENV(packuq
)
1252 IWMMXT_OP_ENV(packsw
)
1253 IWMMXT_OP_ENV(packsl
)
1254 IWMMXT_OP_ENV(packsq
)
1256 static void gen_op_iwmmxt_set_mup(void)
1259 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1260 tcg_gen_ori_i32(tmp
, tmp
, 2);
1261 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1264 static void gen_op_iwmmxt_set_cup(void)
1267 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1268 tcg_gen_ori_i32(tmp
, tmp
, 1);
1269 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1272 static void gen_op_iwmmxt_setpsr_nz(void)
1274 TCGv tmp
= new_tmp();
1275 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1276 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1279 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1281 iwmmxt_load_reg(cpu_V1
, rn
);
1282 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1283 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1286 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1292 rd
= (insn
>> 16) & 0xf;
1293 tmp
= load_reg(s
, rd
);
1295 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1296 if (insn
& (1 << 24)) {
1298 if (insn
& (1 << 23))
1299 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1301 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1302 tcg_gen_mov_i32(dest
, tmp
);
1303 if (insn
& (1 << 21))
1304 store_reg(s
, rd
, tmp
);
1307 } else if (insn
& (1 << 21)) {
1309 tcg_gen_mov_i32(dest
, tmp
);
1310 if (insn
& (1 << 23))
1311 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1313 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1314 store_reg(s
, rd
, tmp
);
1315 } else if (!(insn
& (1 << 23)))
1320 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1322 int rd
= (insn
>> 0) & 0xf;
1325 if (insn
& (1 << 8)) {
1326 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1329 tmp
= iwmmxt_load_creg(rd
);
1333 iwmmxt_load_reg(cpu_V0
, rd
);
1334 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1336 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1337 tcg_gen_mov_i32(dest
, tmp
);
1342 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1343 (ie. an undefined instruction). */
1344 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1347 int rdhi
, rdlo
, rd0
, rd1
, i
;
1349 TCGv tmp
, tmp2
, tmp3
;
1351 if ((insn
& 0x0e000e00) == 0x0c000000) {
1352 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1354 rdlo
= (insn
>> 12) & 0xf;
1355 rdhi
= (insn
>> 16) & 0xf;
1356 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1357 iwmmxt_load_reg(cpu_V0
, wrd
);
1358 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1359 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1360 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1361 } else { /* TMCRR */
1362 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1363 iwmmxt_store_reg(cpu_V0
, wrd
);
1364 gen_op_iwmmxt_set_mup();
1369 wrd
= (insn
>> 12) & 0xf;
1371 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1375 if (insn
& ARM_CP_RW_BIT
) {
1376 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1378 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1379 iwmmxt_store_creg(wrd
, tmp
);
1382 if (insn
& (1 << 8)) {
1383 if (insn
& (1 << 22)) { /* WLDRD */
1384 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1386 } else { /* WLDRW wRd */
1387 tmp
= gen_ld32(addr
, IS_USER(s
));
1390 if (insn
& (1 << 22)) { /* WLDRH */
1391 tmp
= gen_ld16u(addr
, IS_USER(s
));
1392 } else { /* WLDRB */
1393 tmp
= gen_ld8u(addr
, IS_USER(s
));
1397 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1400 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1403 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1404 tmp
= iwmmxt_load_creg(wrd
);
1405 gen_st32(tmp
, addr
, IS_USER(s
));
1407 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1409 if (insn
& (1 << 8)) {
1410 if (insn
& (1 << 22)) { /* WSTRD */
1412 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1413 } else { /* WSTRW wRd */
1414 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1415 gen_st32(tmp
, addr
, IS_USER(s
));
1418 if (insn
& (1 << 22)) { /* WSTRH */
1419 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1420 gen_st16(tmp
, addr
, IS_USER(s
));
1421 } else { /* WSTRB */
1422 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1423 gen_st8(tmp
, addr
, IS_USER(s
));
1431 if ((insn
& 0x0f000000) != 0x0e000000)
1434 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1435 case 0x000: /* WOR */
1436 wrd
= (insn
>> 12) & 0xf;
1437 rd0
= (insn
>> 0) & 0xf;
1438 rd1
= (insn
>> 16) & 0xf;
1439 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1440 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1441 gen_op_iwmmxt_setpsr_nz();
1442 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1443 gen_op_iwmmxt_set_mup();
1444 gen_op_iwmmxt_set_cup();
1446 case 0x011: /* TMCR */
1449 rd
= (insn
>> 12) & 0xf;
1450 wrd
= (insn
>> 16) & 0xf;
1452 case ARM_IWMMXT_wCID
:
1453 case ARM_IWMMXT_wCASF
:
1455 case ARM_IWMMXT_wCon
:
1456 gen_op_iwmmxt_set_cup();
1458 case ARM_IWMMXT_wCSSF
:
1459 tmp
= iwmmxt_load_creg(wrd
);
1460 tmp2
= load_reg(s
, rd
);
1461 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
1463 iwmmxt_store_creg(wrd
, tmp
);
1465 case ARM_IWMMXT_wCGR0
:
1466 case ARM_IWMMXT_wCGR1
:
1467 case ARM_IWMMXT_wCGR2
:
1468 case ARM_IWMMXT_wCGR3
:
1469 gen_op_iwmmxt_set_cup();
1470 tmp
= load_reg(s
, rd
);
1471 iwmmxt_store_creg(wrd
, tmp
);
1477 case 0x100: /* WXOR */
1478 wrd
= (insn
>> 12) & 0xf;
1479 rd0
= (insn
>> 0) & 0xf;
1480 rd1
= (insn
>> 16) & 0xf;
1481 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1482 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1483 gen_op_iwmmxt_setpsr_nz();
1484 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1485 gen_op_iwmmxt_set_mup();
1486 gen_op_iwmmxt_set_cup();
1488 case 0x111: /* TMRC */
1491 rd
= (insn
>> 12) & 0xf;
1492 wrd
= (insn
>> 16) & 0xf;
1493 tmp
= iwmmxt_load_creg(wrd
);
1494 store_reg(s
, rd
, tmp
);
1496 case 0x300: /* WANDN */
1497 wrd
= (insn
>> 12) & 0xf;
1498 rd0
= (insn
>> 0) & 0xf;
1499 rd1
= (insn
>> 16) & 0xf;
1500 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1501 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1502 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1503 gen_op_iwmmxt_setpsr_nz();
1504 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1505 gen_op_iwmmxt_set_mup();
1506 gen_op_iwmmxt_set_cup();
1508 case 0x200: /* WAND */
1509 wrd
= (insn
>> 12) & 0xf;
1510 rd0
= (insn
>> 0) & 0xf;
1511 rd1
= (insn
>> 16) & 0xf;
1512 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1513 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1514 gen_op_iwmmxt_setpsr_nz();
1515 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1516 gen_op_iwmmxt_set_mup();
1517 gen_op_iwmmxt_set_cup();
1519 case 0x810: case 0xa10: /* WMADD */
1520 wrd
= (insn
>> 12) & 0xf;
1521 rd0
= (insn
>> 0) & 0xf;
1522 rd1
= (insn
>> 16) & 0xf;
1523 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1524 if (insn
& (1 << 21))
1525 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1527 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1528 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1529 gen_op_iwmmxt_set_mup();
1531 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1532 wrd
= (insn
>> 12) & 0xf;
1533 rd0
= (insn
>> 16) & 0xf;
1534 rd1
= (insn
>> 0) & 0xf;
1535 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1536 switch ((insn
>> 22) & 3) {
1538 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1541 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1544 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1549 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1550 gen_op_iwmmxt_set_mup();
1551 gen_op_iwmmxt_set_cup();
1553 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1554 wrd
= (insn
>> 12) & 0xf;
1555 rd0
= (insn
>> 16) & 0xf;
1556 rd1
= (insn
>> 0) & 0xf;
1557 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1558 switch ((insn
>> 22) & 3) {
1560 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1563 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1566 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1571 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1572 gen_op_iwmmxt_set_mup();
1573 gen_op_iwmmxt_set_cup();
1575 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1576 wrd
= (insn
>> 12) & 0xf;
1577 rd0
= (insn
>> 16) & 0xf;
1578 rd1
= (insn
>> 0) & 0xf;
1579 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1580 if (insn
& (1 << 22))
1581 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1583 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1584 if (!(insn
& (1 << 20)))
1585 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1586 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1587 gen_op_iwmmxt_set_mup();
1589 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1590 wrd
= (insn
>> 12) & 0xf;
1591 rd0
= (insn
>> 16) & 0xf;
1592 rd1
= (insn
>> 0) & 0xf;
1593 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1594 if (insn
& (1 << 21)) {
1595 if (insn
& (1 << 20))
1596 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1598 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1600 if (insn
& (1 << 20))
1601 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1603 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1605 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1606 gen_op_iwmmxt_set_mup();
1608 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1609 wrd
= (insn
>> 12) & 0xf;
1610 rd0
= (insn
>> 16) & 0xf;
1611 rd1
= (insn
>> 0) & 0xf;
1612 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1613 if (insn
& (1 << 21))
1614 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1616 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1617 if (!(insn
& (1 << 20))) {
1618 iwmmxt_load_reg(cpu_V1
, wrd
);
1619 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1621 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1622 gen_op_iwmmxt_set_mup();
1624 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1625 wrd
= (insn
>> 12) & 0xf;
1626 rd0
= (insn
>> 16) & 0xf;
1627 rd1
= (insn
>> 0) & 0xf;
1628 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1629 switch ((insn
>> 22) & 3) {
1631 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1634 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1637 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1642 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1643 gen_op_iwmmxt_set_mup();
1644 gen_op_iwmmxt_set_cup();
1646 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1647 wrd
= (insn
>> 12) & 0xf;
1648 rd0
= (insn
>> 16) & 0xf;
1649 rd1
= (insn
>> 0) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1651 if (insn
& (1 << 22)) {
1652 if (insn
& (1 << 20))
1653 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1655 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1657 if (insn
& (1 << 20))
1658 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1660 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1662 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1663 gen_op_iwmmxt_set_mup();
1664 gen_op_iwmmxt_set_cup();
1666 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1667 wrd
= (insn
>> 12) & 0xf;
1668 rd0
= (insn
>> 16) & 0xf;
1669 rd1
= (insn
>> 0) & 0xf;
1670 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1671 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1672 tcg_gen_andi_i32(tmp
, tmp
, 7);
1673 iwmmxt_load_reg(cpu_V1
, rd1
);
1674 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1676 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1677 gen_op_iwmmxt_set_mup();
1679 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1680 if (((insn
>> 6) & 3) == 3)
1682 rd
= (insn
>> 12) & 0xf;
1683 wrd
= (insn
>> 16) & 0xf;
1684 tmp
= load_reg(s
, rd
);
1685 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1686 switch ((insn
>> 6) & 3) {
1688 tmp2
= tcg_const_i32(0xff);
1689 tmp3
= tcg_const_i32((insn
& 7) << 3);
1692 tmp2
= tcg_const_i32(0xffff);
1693 tmp3
= tcg_const_i32((insn
& 3) << 4);
1696 tmp2
= tcg_const_i32(0xffffffff);
1697 tmp3
= tcg_const_i32((insn
& 1) << 5);
1703 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1704 tcg_temp_free(tmp3
);
1705 tcg_temp_free(tmp2
);
1707 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1708 gen_op_iwmmxt_set_mup();
1710 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1711 rd
= (insn
>> 12) & 0xf;
1712 wrd
= (insn
>> 16) & 0xf;
1713 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1715 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1717 switch ((insn
>> 22) & 3) {
1719 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1720 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1722 tcg_gen_ext8s_i32(tmp
, tmp
);
1724 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1728 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1729 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1731 tcg_gen_ext16s_i32(tmp
, tmp
);
1733 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1737 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1738 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1741 store_reg(s
, rd
, tmp
);
1743 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1744 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1746 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1747 switch ((insn
>> 22) & 3) {
1749 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1752 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1755 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1758 tcg_gen_shli_i32(tmp
, tmp
, 28);
1762 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1763 if (((insn
>> 6) & 3) == 3)
1765 rd
= (insn
>> 12) & 0xf;
1766 wrd
= (insn
>> 16) & 0xf;
1767 tmp
= load_reg(s
, rd
);
1768 switch ((insn
>> 6) & 3) {
1770 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1773 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1776 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1781 gen_op_iwmmxt_set_mup();
1783 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1784 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1786 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1788 tcg_gen_mov_i32(tmp2
, tmp
);
1789 switch ((insn
>> 22) & 3) {
1791 for (i
= 0; i
< 7; i
++) {
1792 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1793 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1797 for (i
= 0; i
< 3; i
++) {
1798 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1799 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1803 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1804 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1811 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1812 wrd
= (insn
>> 12) & 0xf;
1813 rd0
= (insn
>> 16) & 0xf;
1814 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1815 switch ((insn
>> 22) & 3) {
1817 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1820 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1823 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1828 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1829 gen_op_iwmmxt_set_mup();
1831 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1832 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1834 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1836 tcg_gen_mov_i32(tmp2
, tmp
);
1837 switch ((insn
>> 22) & 3) {
1839 for (i
= 0; i
< 7; i
++) {
1840 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1841 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1845 for (i
= 0; i
< 3; i
++) {
1846 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1847 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1851 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1852 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1859 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1860 rd
= (insn
>> 12) & 0xf;
1861 rd0
= (insn
>> 16) & 0xf;
1862 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1864 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1866 switch ((insn
>> 22) & 3) {
1868 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1871 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1874 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1877 store_reg(s
, rd
, tmp
);
1879 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1880 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1881 wrd
= (insn
>> 12) & 0xf;
1882 rd0
= (insn
>> 16) & 0xf;
1883 rd1
= (insn
>> 0) & 0xf;
1884 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1885 switch ((insn
>> 22) & 3) {
1887 if (insn
& (1 << 21))
1888 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1890 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1893 if (insn
& (1 << 21))
1894 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1896 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1899 if (insn
& (1 << 21))
1900 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1902 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1907 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1908 gen_op_iwmmxt_set_mup();
1909 gen_op_iwmmxt_set_cup();
1911 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1912 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1913 wrd
= (insn
>> 12) & 0xf;
1914 rd0
= (insn
>> 16) & 0xf;
1915 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1916 switch ((insn
>> 22) & 3) {
1918 if (insn
& (1 << 21))
1919 gen_op_iwmmxt_unpacklsb_M0();
1921 gen_op_iwmmxt_unpacklub_M0();
1924 if (insn
& (1 << 21))
1925 gen_op_iwmmxt_unpacklsw_M0();
1927 gen_op_iwmmxt_unpackluw_M0();
1930 if (insn
& (1 << 21))
1931 gen_op_iwmmxt_unpacklsl_M0();
1933 gen_op_iwmmxt_unpacklul_M0();
1938 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1939 gen_op_iwmmxt_set_mup();
1940 gen_op_iwmmxt_set_cup();
1942 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1943 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1944 wrd
= (insn
>> 12) & 0xf;
1945 rd0
= (insn
>> 16) & 0xf;
1946 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1947 switch ((insn
>> 22) & 3) {
1949 if (insn
& (1 << 21))
1950 gen_op_iwmmxt_unpackhsb_M0();
1952 gen_op_iwmmxt_unpackhub_M0();
1955 if (insn
& (1 << 21))
1956 gen_op_iwmmxt_unpackhsw_M0();
1958 gen_op_iwmmxt_unpackhuw_M0();
1961 if (insn
& (1 << 21))
1962 gen_op_iwmmxt_unpackhsl_M0();
1964 gen_op_iwmmxt_unpackhul_M0();
1969 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1970 gen_op_iwmmxt_set_mup();
1971 gen_op_iwmmxt_set_cup();
1973 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1974 case 0x214: case 0x614: case 0xa14: case 0xe14:
1975 if (((insn
>> 22) & 3) == 0)
1977 wrd
= (insn
>> 12) & 0xf;
1978 rd0
= (insn
>> 16) & 0xf;
1979 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1981 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1985 switch ((insn
>> 22) & 3) {
1987 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1990 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1993 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1997 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1998 gen_op_iwmmxt_set_mup();
1999 gen_op_iwmmxt_set_cup();
2001 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2002 case 0x014: case 0x414: case 0x814: case 0xc14:
2003 if (((insn
>> 22) & 3) == 0)
2005 wrd
= (insn
>> 12) & 0xf;
2006 rd0
= (insn
>> 16) & 0xf;
2007 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2009 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2013 switch ((insn
>> 22) & 3) {
2015 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2018 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2021 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2025 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2026 gen_op_iwmmxt_set_mup();
2027 gen_op_iwmmxt_set_cup();
2029 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2030 case 0x114: case 0x514: case 0x914: case 0xd14:
2031 if (((insn
>> 22) & 3) == 0)
2033 wrd
= (insn
>> 12) & 0xf;
2034 rd0
= (insn
>> 16) & 0xf;
2035 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2037 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2041 switch ((insn
>> 22) & 3) {
2043 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2046 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2049 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2053 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2054 gen_op_iwmmxt_set_mup();
2055 gen_op_iwmmxt_set_cup();
2057 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2058 case 0x314: case 0x714: case 0xb14: case 0xf14:
2059 if (((insn
>> 22) & 3) == 0)
2061 wrd
= (insn
>> 12) & 0xf;
2062 rd0
= (insn
>> 16) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2065 switch ((insn
>> 22) & 3) {
2067 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2071 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2074 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2078 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2081 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2085 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2089 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2090 gen_op_iwmmxt_set_mup();
2091 gen_op_iwmmxt_set_cup();
2093 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2094 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2095 wrd
= (insn
>> 12) & 0xf;
2096 rd0
= (insn
>> 16) & 0xf;
2097 rd1
= (insn
>> 0) & 0xf;
2098 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2099 switch ((insn
>> 22) & 3) {
2101 if (insn
& (1 << 21))
2102 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2104 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2107 if (insn
& (1 << 21))
2108 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2110 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2113 if (insn
& (1 << 21))
2114 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2116 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2121 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2122 gen_op_iwmmxt_set_mup();
2124 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2125 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2126 wrd
= (insn
>> 12) & 0xf;
2127 rd0
= (insn
>> 16) & 0xf;
2128 rd1
= (insn
>> 0) & 0xf;
2129 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2130 switch ((insn
>> 22) & 3) {
2132 if (insn
& (1 << 21))
2133 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2135 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2138 if (insn
& (1 << 21))
2139 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2141 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2144 if (insn
& (1 << 21))
2145 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2147 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2152 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2153 gen_op_iwmmxt_set_mup();
2155 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2156 case 0x402: case 0x502: case 0x602: case 0x702:
2157 wrd
= (insn
>> 12) & 0xf;
2158 rd0
= (insn
>> 16) & 0xf;
2159 rd1
= (insn
>> 0) & 0xf;
2160 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2161 tmp
= tcg_const_i32((insn
>> 20) & 3);
2162 iwmmxt_load_reg(cpu_V1
, rd1
);
2163 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2165 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2166 gen_op_iwmmxt_set_mup();
2168 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2169 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2170 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2171 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2172 wrd
= (insn
>> 12) & 0xf;
2173 rd0
= (insn
>> 16) & 0xf;
2174 rd1
= (insn
>> 0) & 0xf;
2175 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2176 switch ((insn
>> 20) & 0xf) {
2178 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2181 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2184 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2187 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2190 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2193 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2196 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2199 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2202 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2207 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2208 gen_op_iwmmxt_set_mup();
2209 gen_op_iwmmxt_set_cup();
2211 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2212 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2213 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2214 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2215 wrd
= (insn
>> 12) & 0xf;
2216 rd0
= (insn
>> 16) & 0xf;
2217 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2218 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2219 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2221 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2222 gen_op_iwmmxt_set_mup();
2223 gen_op_iwmmxt_set_cup();
2225 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2226 case 0x418: case 0x518: case 0x618: case 0x718:
2227 case 0x818: case 0x918: case 0xa18: case 0xb18:
2228 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2229 wrd
= (insn
>> 12) & 0xf;
2230 rd0
= (insn
>> 16) & 0xf;
2231 rd1
= (insn
>> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2233 switch ((insn
>> 20) & 0xf) {
2235 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2238 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2241 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2244 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2247 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2250 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2253 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2256 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2259 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2264 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2265 gen_op_iwmmxt_set_mup();
2266 gen_op_iwmmxt_set_cup();
2268 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2269 case 0x408: case 0x508: case 0x608: case 0x708:
2270 case 0x808: case 0x908: case 0xa08: case 0xb08:
2271 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2272 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2274 wrd
= (insn
>> 12) & 0xf;
2275 rd0
= (insn
>> 16) & 0xf;
2276 rd1
= (insn
>> 0) & 0xf;
2277 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2278 switch ((insn
>> 22) & 3) {
2280 if (insn
& (1 << 21))
2281 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2283 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2286 if (insn
& (1 << 21))
2287 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2289 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2292 if (insn
& (1 << 21))
2293 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2295 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2298 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2299 gen_op_iwmmxt_set_mup();
2300 gen_op_iwmmxt_set_cup();
2302 case 0x201: case 0x203: case 0x205: case 0x207:
2303 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2304 case 0x211: case 0x213: case 0x215: case 0x217:
2305 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2306 wrd
= (insn
>> 5) & 0xf;
2307 rd0
= (insn
>> 12) & 0xf;
2308 rd1
= (insn
>> 0) & 0xf;
2309 if (rd0
== 0xf || rd1
== 0xf)
2311 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2312 tmp
= load_reg(s
, rd0
);
2313 tmp2
= load_reg(s
, rd1
);
2314 switch ((insn
>> 16) & 0xf) {
2315 case 0x0: /* TMIA */
2316 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2318 case 0x8: /* TMIAPH */
2319 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2321 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2322 if (insn
& (1 << 16))
2323 tcg_gen_shri_i32(tmp
, tmp
, 16);
2324 if (insn
& (1 << 17))
2325 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2326 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2335 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2336 gen_op_iwmmxt_set_mup();
2345 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2346 (ie. an undefined instruction). */
2347 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2349 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2352 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2353 /* Multiply with Internal Accumulate Format */
2354 rd0
= (insn
>> 12) & 0xf;
2356 acc
= (insn
>> 5) & 7;
2361 tmp
= load_reg(s
, rd0
);
2362 tmp2
= load_reg(s
, rd1
);
2363 switch ((insn
>> 16) & 0xf) {
2365 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2367 case 0x8: /* MIAPH */
2368 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2370 case 0xc: /* MIABB */
2371 case 0xd: /* MIABT */
2372 case 0xe: /* MIATB */
2373 case 0xf: /* MIATT */
2374 if (insn
& (1 << 16))
2375 tcg_gen_shri_i32(tmp
, tmp
, 16);
2376 if (insn
& (1 << 17))
2377 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2378 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2386 gen_op_iwmmxt_movq_wRn_M0(acc
);
2390 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2391 /* Internal Accumulator Access Format */
2392 rdhi
= (insn
>> 16) & 0xf;
2393 rdlo
= (insn
>> 12) & 0xf;
2399 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2400 iwmmxt_load_reg(cpu_V0
, acc
);
2401 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2402 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2403 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2404 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2406 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2407 iwmmxt_store_reg(cpu_V0
, acc
);
2415 /* Disassemble system coprocessor instruction. Return nonzero if
2416 instruction is not defined. */
2417 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2420 uint32_t rd
= (insn
>> 12) & 0xf;
2421 uint32_t cp
= (insn
>> 8) & 0xf;
2426 if (insn
& ARM_CP_RW_BIT
) {
2427 if (!env
->cp
[cp
].cp_read
)
2429 gen_set_pc_im(s
->pc
);
2431 tmp2
= tcg_const_i32(insn
);
2432 gen_helper_get_cp(tmp
, cpu_env
, tmp2
);
2433 tcg_temp_free(tmp2
);
2434 store_reg(s
, rd
, tmp
);
2436 if (!env
->cp
[cp
].cp_write
)
2438 gen_set_pc_im(s
->pc
);
2439 tmp
= load_reg(s
, rd
);
2440 tmp2
= tcg_const_i32(insn
);
2441 gen_helper_set_cp(cpu_env
, tmp2
, tmp
);
2442 tcg_temp_free(tmp2
);
2448 static int cp15_user_ok(uint32_t insn
)
2450 int cpn
= (insn
>> 16) & 0xf;
2451 int cpm
= insn
& 0xf;
2452 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2454 if (cpn
== 13 && cpm
== 0) {
2456 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2460 /* ISB, DSB, DMB. */
2461 if ((cpm
== 5 && op
== 4)
2462 || (cpm
== 10 && (op
== 4 || op
== 5)))
2468 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2469 instruction is not defined. */
2470 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2475 /* M profile cores use memory mapped registers instead of cp15. */
2476 if (arm_feature(env
, ARM_FEATURE_M
))
2479 if ((insn
& (1 << 25)) == 0) {
2480 if (insn
& (1 << 20)) {
2484 /* mcrr. Used for block cache operations, so implement as no-op. */
2487 if ((insn
& (1 << 4)) == 0) {
2491 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2494 if ((insn
& 0x0fff0fff) == 0x0e070f90
2495 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2496 /* Wait for interrupt. */
2497 gen_set_pc_im(s
->pc
);
2498 s
->is_jmp
= DISAS_WFI
;
2501 rd
= (insn
>> 12) & 0xf;
2502 tmp2
= tcg_const_i32(insn
);
2503 if (insn
& ARM_CP_RW_BIT
) {
2505 gen_helper_get_cp15(tmp
, cpu_env
, tmp2
);
2506 /* If the destination register is r15 then sets condition codes. */
2508 store_reg(s
, rd
, tmp
);
2512 tmp
= load_reg(s
, rd
);
2513 gen_helper_set_cp15(cpu_env
, tmp2
, tmp
);
2515 /* Normally we would always end the TB here, but Linux
2516 * arch/arm/mach-pxa/sleep.S expects two instructions following
2517 * an MMU enable to execute from cache. Imitate this behaviour. */
2518 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2519 (insn
& 0x0fff0fff) != 0x0e010f10)
2522 tcg_temp_free_i32(tmp2
);
2526 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2527 #define VFP_SREG(insn, bigbit, smallbit) \
2528 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2529 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2530 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2531 reg = (((insn) >> (bigbit)) & 0x0f) \
2532 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2534 if (insn & (1 << (smallbit))) \
2536 reg = ((insn) >> (bigbit)) & 0x0f; \
2539 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2540 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2541 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2542 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2543 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2544 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2546 /* Move between integer and VFP cores. */
2547 static TCGv
gen_vfp_mrs(void)
2549 TCGv tmp
= new_tmp();
2550 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2554 static void gen_vfp_msr(TCGv tmp
)
2556 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2561 vfp_enabled(CPUState
* env
)
2563 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2566 static void gen_neon_dup_u8(TCGv var
, int shift
)
2568 TCGv tmp
= new_tmp();
2570 tcg_gen_shri_i32(var
, var
, shift
);
2571 tcg_gen_ext8u_i32(var
, var
);
2572 tcg_gen_shli_i32(tmp
, var
, 8);
2573 tcg_gen_or_i32(var
, var
, tmp
);
2574 tcg_gen_shli_i32(tmp
, var
, 16);
2575 tcg_gen_or_i32(var
, var
, tmp
);
2579 static void gen_neon_dup_low16(TCGv var
)
2581 TCGv tmp
= new_tmp();
2582 tcg_gen_ext16u_i32(var
, var
);
2583 tcg_gen_shli_i32(tmp
, var
, 16);
2584 tcg_gen_or_i32(var
, var
, tmp
);
2588 static void gen_neon_dup_high16(TCGv var
)
2590 TCGv tmp
= new_tmp();
2591 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2592 tcg_gen_shri_i32(tmp
, var
, 16);
2593 tcg_gen_or_i32(var
, var
, tmp
);
2597 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2598 (ie. an undefined instruction). */
2599 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2601 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2607 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2610 if (!vfp_enabled(env
)) {
2611 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2612 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2614 rn
= (insn
>> 16) & 0xf;
2615 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2616 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2619 dp
= ((insn
& 0xf00) == 0xb00);
2620 switch ((insn
>> 24) & 0xf) {
2622 if (insn
& (1 << 4)) {
2623 /* single register transfer */
2624 rd
= (insn
>> 12) & 0xf;
2629 VFP_DREG_N(rn
, insn
);
2632 if (insn
& 0x00c00060
2633 && !arm_feature(env
, ARM_FEATURE_NEON
))
2636 pass
= (insn
>> 21) & 1;
2637 if (insn
& (1 << 22)) {
2639 offset
= ((insn
>> 5) & 3) * 8;
2640 } else if (insn
& (1 << 5)) {
2642 offset
= (insn
& (1 << 6)) ? 16 : 0;
2647 if (insn
& ARM_CP_RW_BIT
) {
2649 tmp
= neon_load_reg(rn
, pass
);
2653 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2654 if (insn
& (1 << 23))
2660 if (insn
& (1 << 23)) {
2662 tcg_gen_shri_i32(tmp
, tmp
, 16);
2668 tcg_gen_sari_i32(tmp
, tmp
, 16);
2677 store_reg(s
, rd
, tmp
);
2680 tmp
= load_reg(s
, rd
);
2681 if (insn
& (1 << 23)) {
2684 gen_neon_dup_u8(tmp
, 0);
2685 } else if (size
== 1) {
2686 gen_neon_dup_low16(tmp
);
2688 for (n
= 0; n
<= pass
* 2; n
++) {
2690 tcg_gen_mov_i32(tmp2
, tmp
);
2691 neon_store_reg(rn
, n
, tmp2
);
2693 neon_store_reg(rn
, n
, tmp
);
2698 tmp2
= neon_load_reg(rn
, pass
);
2699 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2703 tmp2
= neon_load_reg(rn
, pass
);
2704 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2710 neon_store_reg(rn
, pass
, tmp
);
2714 if ((insn
& 0x6f) != 0x00)
2716 rn
= VFP_SREG_N(insn
);
2717 if (insn
& ARM_CP_RW_BIT
) {
2719 if (insn
& (1 << 21)) {
2720 /* system register */
2725 /* VFP2 allows access to FSID from userspace.
2726 VFP3 restricts all id registers to privileged
2729 && arm_feature(env
, ARM_FEATURE_VFP3
))
2731 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2736 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2738 case ARM_VFP_FPINST
:
2739 case ARM_VFP_FPINST2
:
2740 /* Not present in VFP3. */
2742 || arm_feature(env
, ARM_FEATURE_VFP3
))
2744 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2748 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2749 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2752 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2758 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2760 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2766 gen_mov_F0_vreg(0, rn
);
2767 tmp
= gen_vfp_mrs();
2770 /* Set the 4 flag bits in the CPSR. */
2774 store_reg(s
, rd
, tmp
);
2778 tmp
= load_reg(s
, rd
);
2779 if (insn
& (1 << 21)) {
2781 /* system register */
2786 /* Writes are ignored. */
2789 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2796 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2799 case ARM_VFP_FPINST
:
2800 case ARM_VFP_FPINST2
:
2801 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2808 gen_mov_vreg_F0(0, rn
);
2813 /* data processing */
2814 /* The opcode is in bits 23, 21, 20 and 6. */
2815 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2819 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2821 /* rn is register number */
2822 VFP_DREG_N(rn
, insn
);
2825 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2826 /* Integer or single precision destination. */
2827 rd
= VFP_SREG_D(insn
);
2829 VFP_DREG_D(rd
, insn
);
2832 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2833 /* Integer source. */
2834 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2836 VFP_DREG_M(rm
, insn
);
2839 rn
= VFP_SREG_N(insn
);
2840 if (op
== 15 && rn
== 15) {
2841 /* Double precision destination. */
2842 VFP_DREG_D(rd
, insn
);
2844 rd
= VFP_SREG_D(insn
);
2846 rm
= VFP_SREG_M(insn
);
2849 veclen
= env
->vfp
.vec_len
;
2850 if (op
== 15 && rn
> 3)
2853 /* Shut up compiler warnings. */
2864 /* Figure out what type of vector operation this is. */
2865 if ((rd
& bank_mask
) == 0) {
2870 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2872 delta_d
= env
->vfp
.vec_stride
+ 1;
2874 if ((rm
& bank_mask
) == 0) {
2875 /* mixed scalar/vector */
2884 /* Load the initial operands. */
2889 /* Integer source */
2890 gen_mov_F0_vreg(0, rm
);
2895 gen_mov_F0_vreg(dp
, rd
);
2896 gen_mov_F1_vreg(dp
, rm
);
2900 /* Compare with zero */
2901 gen_mov_F0_vreg(dp
, rd
);
2912 /* Source and destination the same. */
2913 gen_mov_F0_vreg(dp
, rd
);
2916 /* One source operand. */
2917 gen_mov_F0_vreg(dp
, rm
);
2921 /* Two source operands. */
2922 gen_mov_F0_vreg(dp
, rn
);
2923 gen_mov_F1_vreg(dp
, rm
);
2927 /* Perform the calculation. */
2929 case 0: /* mac: fd + (fn * fm) */
2931 gen_mov_F1_vreg(dp
, rd
);
2934 case 1: /* nmac: fd - (fn * fm) */
2937 gen_mov_F1_vreg(dp
, rd
);
2940 case 2: /* msc: -fd + (fn * fm) */
2942 gen_mov_F1_vreg(dp
, rd
);
2945 case 3: /* nmsc: -fd - (fn * fm) */
2948 gen_mov_F1_vreg(dp
, rd
);
2951 case 4: /* mul: fn * fm */
2954 case 5: /* nmul: -(fn * fm) */
2958 case 6: /* add: fn + fm */
2961 case 7: /* sub: fn - fm */
2964 case 8: /* div: fn / fm */
2967 case 14: /* fconst */
2968 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2971 n
= (insn
<< 12) & 0x80000000;
2972 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2979 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
2986 tcg_gen_movi_i32(cpu_F0s
, n
);
2989 case 15: /* extension space */
3012 case 11: /* cmpez */
3016 case 15: /* single<->double conversion */
3018 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3020 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3022 case 16: /* fuito */
3025 case 17: /* fsito */
3028 case 20: /* fshto */
3029 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3031 gen_vfp_shto(dp
, 16 - rm
);
3033 case 21: /* fslto */
3034 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3036 gen_vfp_slto(dp
, 32 - rm
);
3038 case 22: /* fuhto */
3039 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3041 gen_vfp_uhto(dp
, 16 - rm
);
3043 case 23: /* fulto */
3044 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3046 gen_vfp_ulto(dp
, 32 - rm
);
3048 case 24: /* ftoui */
3051 case 25: /* ftouiz */
3054 case 26: /* ftosi */
3057 case 27: /* ftosiz */
3060 case 28: /* ftosh */
3061 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3063 gen_vfp_tosh(dp
, 16 - rm
);
3065 case 29: /* ftosl */
3066 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3068 gen_vfp_tosl(dp
, 32 - rm
);
3070 case 30: /* ftouh */
3071 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3073 gen_vfp_touh(dp
, 16 - rm
);
3075 case 31: /* ftoul */
3076 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3078 gen_vfp_toul(dp
, 32 - rm
);
3080 default: /* undefined */
3081 printf ("rn:%d\n", rn
);
3085 default: /* undefined */
3086 printf ("op:%d\n", op
);
3090 /* Write back the result. */
3091 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3092 ; /* Comparison, do nothing. */
3093 else if (op
== 15 && rn
> 17)
3094 /* Integer result. */
3095 gen_mov_vreg_F0(0, rd
);
3096 else if (op
== 15 && rn
== 15)
3098 gen_mov_vreg_F0(!dp
, rd
);
3100 gen_mov_vreg_F0(dp
, rd
);
3102 /* break out of the loop if we have finished */
3106 if (op
== 15 && delta_m
== 0) {
3107 /* single source one-many */
3109 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3111 gen_mov_vreg_F0(dp
, rd
);
3115 /* Setup the next operands. */
3117 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3121 /* One source operand. */
3122 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3124 gen_mov_F0_vreg(dp
, rm
);
3126 /* Two source operands. */
3127 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3129 gen_mov_F0_vreg(dp
, rn
);
3131 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3133 gen_mov_F1_vreg(dp
, rm
);
3141 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3142 /* two-register transfer */
3143 rn
= (insn
>> 16) & 0xf;
3144 rd
= (insn
>> 12) & 0xf;
3146 VFP_DREG_M(rm
, insn
);
3148 rm
= VFP_SREG_M(insn
);
3151 if (insn
& ARM_CP_RW_BIT
) {
3154 gen_mov_F0_vreg(0, rm
* 2);
3155 tmp
= gen_vfp_mrs();
3156 store_reg(s
, rd
, tmp
);
3157 gen_mov_F0_vreg(0, rm
* 2 + 1);
3158 tmp
= gen_vfp_mrs();
3159 store_reg(s
, rn
, tmp
);
3161 gen_mov_F0_vreg(0, rm
);
3162 tmp
= gen_vfp_mrs();
3163 store_reg(s
, rn
, tmp
);
3164 gen_mov_F0_vreg(0, rm
+ 1);
3165 tmp
= gen_vfp_mrs();
3166 store_reg(s
, rd
, tmp
);
3171 tmp
= load_reg(s
, rd
);
3173 gen_mov_vreg_F0(0, rm
* 2);
3174 tmp
= load_reg(s
, rn
);
3176 gen_mov_vreg_F0(0, rm
* 2 + 1);
3178 tmp
= load_reg(s
, rn
);
3180 gen_mov_vreg_F0(0, rm
);
3181 tmp
= load_reg(s
, rd
);
3183 gen_mov_vreg_F0(0, rm
+ 1);
3188 rn
= (insn
>> 16) & 0xf;
3190 VFP_DREG_D(rd
, insn
);
3192 rd
= VFP_SREG_D(insn
);
3193 if (s
->thumb
&& rn
== 15) {
3195 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3197 addr
= load_reg(s
, rn
);
3199 if ((insn
& 0x01200000) == 0x01000000) {
3200 /* Single load/store */
3201 offset
= (insn
& 0xff) << 2;
3202 if ((insn
& (1 << 23)) == 0)
3204 tcg_gen_addi_i32(addr
, addr
, offset
);
3205 if (insn
& (1 << 20)) {
3206 gen_vfp_ld(s
, dp
, addr
);
3207 gen_mov_vreg_F0(dp
, rd
);
3209 gen_mov_F0_vreg(dp
, rd
);
3210 gen_vfp_st(s
, dp
, addr
);
3214 /* load/store multiple */
3216 n
= (insn
>> 1) & 0x7f;
3220 if (insn
& (1 << 24)) /* pre-decrement */
3221 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3227 for (i
= 0; i
< n
; i
++) {
3228 if (insn
& ARM_CP_RW_BIT
) {
3230 gen_vfp_ld(s
, dp
, addr
);
3231 gen_mov_vreg_F0(dp
, rd
+ i
);
3234 gen_mov_F0_vreg(dp
, rd
+ i
);
3235 gen_vfp_st(s
, dp
, addr
);
3237 tcg_gen_addi_i32(addr
, addr
, offset
);
3239 if (insn
& (1 << 21)) {
3241 if (insn
& (1 << 24))
3242 offset
= -offset
* n
;
3243 else if (dp
&& (insn
& 1))
3249 tcg_gen_addi_i32(addr
, addr
, offset
);
3250 store_reg(s
, rn
, addr
);
3258 /* Should never happen. */
3264 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3266 TranslationBlock
*tb
;
3269 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3271 gen_set_pc_im(dest
);
3272 tcg_gen_exit_tb((long)tb
+ n
);
3274 gen_set_pc_im(dest
);
3279 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3281 if (unlikely(s
->singlestep_enabled
)) {
3282 /* An indirect jump so that we still trigger the debug exception. */
3287 gen_goto_tb(s
, 0, dest
);
3288 s
->is_jmp
= DISAS_TB_JUMP
;
3292 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3295 tcg_gen_sari_i32(t0
, t0
, 16);
3299 tcg_gen_sari_i32(t1
, t1
, 16);
3302 tcg_gen_mul_i32(t0
, t0
, t1
);
3305 /* Return the mask of PSR bits set by a MSR instruction. */
3306 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3310 if (flags
& (1 << 0))
3312 if (flags
& (1 << 1))
3314 if (flags
& (1 << 2))
3316 if (flags
& (1 << 3))
3319 /* Mask out undefined bits. */
3320 mask
&= ~CPSR_RESERVED
;
3321 if (!arm_feature(env
, ARM_FEATURE_V6
))
3322 mask
&= ~(CPSR_E
| CPSR_GE
);
3323 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3325 /* Mask out execution state bits. */
3328 /* Mask out privileged bits. */
3334 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3335 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3339 /* ??? This is also undefined in system mode. */
3343 tmp
= load_cpu_field(spsr
);
3344 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3345 tcg_gen_andi_i32(t0
, t0
, mask
);
3346 tcg_gen_or_i32(tmp
, tmp
, t0
);
3347 store_cpu_field(tmp
, spsr
);
3349 gen_set_cpsr(t0
, mask
);
3356 /* Returns nonzero if access to the PSR is not permitted. */
3357 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3361 tcg_gen_movi_i32(tmp
, val
);
3362 return gen_set_psr(s
, mask
, spsr
, tmp
);
3365 /* Generate an old-style exception return. Marks pc as dead. */
3366 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3369 store_reg(s
, 15, pc
);
3370 tmp
= load_cpu_field(spsr
);
3371 gen_set_cpsr(tmp
, 0xffffffff);
3373 s
->is_jmp
= DISAS_UPDATE
;
3376 /* Generate a v6 exception return. Marks both values as dead. */
3377 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3379 gen_set_cpsr(cpsr
, 0xffffffff);
3381 store_reg(s
, 15, pc
);
3382 s
->is_jmp
= DISAS_UPDATE
;
3386 gen_set_condexec (DisasContext
*s
)
3388 if (s
->condexec_mask
) {
3389 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3390 TCGv tmp
= new_tmp();
3391 tcg_gen_movi_i32(tmp
, val
);
3392 store_cpu_field(tmp
, condexec_bits
);
3396 static void gen_nop_hint(DisasContext
*s
, int val
)
3400 gen_set_pc_im(s
->pc
);
3401 s
->is_jmp
= DISAS_WFI
;
3405 /* TODO: Implement SEV and WFE. May help SMP performance. */
3411 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3413 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3416 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3417 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3418 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3424 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3427 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3428 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3429 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3434 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3435 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3436 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3437 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3438 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3440 /* FIXME: This is wrong. They set the wrong overflow bit. */
3441 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3442 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3443 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3444 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3446 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3447 switch ((size << 1) | u) { \
3449 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3452 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3455 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3458 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3461 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3464 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3466 default: return 1; \
3469 #define GEN_NEON_INTEGER_OP(name) do { \
3470 switch ((size << 1) | u) { \
3472 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3475 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3478 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3481 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3484 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3487 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3489 default: return 1; \
3492 static TCGv
neon_load_scratch(int scratch
)
3494 TCGv tmp
= new_tmp();
3495 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3499 static void neon_store_scratch(int scratch
, TCGv var
)
3501 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3505 static inline TCGv
neon_get_scalar(int size
, int reg
)
3509 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3511 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3513 gen_neon_dup_low16(tmp
);
3515 gen_neon_dup_high16(tmp
);
3521 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3529 tcg_gen_andi_i32(rd
, t0
, 0xff);
3530 tcg_gen_shri_i32(tmp
, t0
, 8);
3531 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3532 tcg_gen_or_i32(rd
, rd
, tmp
);
3533 tcg_gen_shli_i32(tmp
, t1
, 16);
3534 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3535 tcg_gen_or_i32(rd
, rd
, tmp
);
3536 tcg_gen_shli_i32(tmp
, t1
, 8);
3537 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3538 tcg_gen_or_i32(rd
, rd
, tmp
);
3540 tcg_gen_shri_i32(rm
, t0
, 8);
3541 tcg_gen_andi_i32(rm
, rm
, 0xff);
3542 tcg_gen_shri_i32(tmp
, t0
, 16);
3543 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3544 tcg_gen_or_i32(rm
, rm
, tmp
);
3545 tcg_gen_shli_i32(tmp
, t1
, 8);
3546 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3547 tcg_gen_or_i32(rm
, rm
, tmp
);
3548 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3549 tcg_gen_or_i32(t1
, rm
, tmp
);
3550 tcg_gen_mov_i32(t0
, rd
);
3557 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3565 tcg_gen_andi_i32(rd
, t0
, 0xff);
3566 tcg_gen_shli_i32(tmp
, t1
, 8);
3567 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3568 tcg_gen_or_i32(rd
, rd
, tmp
);
3569 tcg_gen_shli_i32(tmp
, t0
, 16);
3570 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3571 tcg_gen_or_i32(rd
, rd
, tmp
);
3572 tcg_gen_shli_i32(tmp
, t1
, 24);
3573 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3574 tcg_gen_or_i32(rd
, rd
, tmp
);
3576 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3577 tcg_gen_shri_i32(tmp
, t0
, 8);
3578 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3579 tcg_gen_or_i32(rm
, rm
, tmp
);
3580 tcg_gen_shri_i32(tmp
, t1
, 8);
3581 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3582 tcg_gen_or_i32(rm
, rm
, tmp
);
3583 tcg_gen_shri_i32(tmp
, t0
, 16);
3584 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3585 tcg_gen_or_i32(t1
, rm
, tmp
);
3586 tcg_gen_mov_i32(t0
, rd
);
3593 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3600 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3601 tcg_gen_shli_i32(tmp2
, t1
, 16);
3602 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3603 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3604 tcg_gen_shri_i32(tmp2
, t0
, 16);
3605 tcg_gen_or_i32(t1
, t1
, tmp2
);
3606 tcg_gen_mov_i32(t0
, tmp
);
3612 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3617 for (n
= 0; n
< q
+ 1; n
+= 2) {
3618 t0
= neon_load_reg(reg
, n
);
3619 t1
= neon_load_reg(reg
, n
+ 1);
3621 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3622 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3623 case 2: /* no-op */; break;
3626 neon_store_scratch(tmp
+ n
, t0
);
3627 neon_store_scratch(tmp
+ n
+ 1, t1
);
3631 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3638 tcg_gen_shli_i32(rd
, t0
, 8);
3639 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3640 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3641 tcg_gen_or_i32(rd
, rd
, tmp
);
3643 tcg_gen_shri_i32(t1
, t1
, 8);
3644 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3645 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3646 tcg_gen_or_i32(t1
, t1
, tmp
);
3647 tcg_gen_mov_i32(t0
, rd
);
3653 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3660 tcg_gen_shli_i32(rd
, t0
, 16);
3661 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3662 tcg_gen_or_i32(rd
, rd
, tmp
);
3663 tcg_gen_shri_i32(t1
, t1
, 16);
3664 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3665 tcg_gen_or_i32(t1
, t1
, tmp
);
3666 tcg_gen_mov_i32(t0
, rd
);
3677 } neon_ls_element_type
[11] = {
3691 /* Translate a NEON load/store element instruction. Return nonzero if the
3692 instruction is invalid. */
3693 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3710 if (!vfp_enabled(env
))
3712 VFP_DREG_D(rd
, insn
);
3713 rn
= (insn
>> 16) & 0xf;
3715 load
= (insn
& (1 << 21)) != 0;
3717 if ((insn
& (1 << 23)) == 0) {
3718 /* Load store all elements. */
3719 op
= (insn
>> 8) & 0xf;
3720 size
= (insn
>> 6) & 3;
3721 if (op
> 10 || size
== 3)
3723 nregs
= neon_ls_element_type
[op
].nregs
;
3724 interleave
= neon_ls_element_type
[op
].interleave
;
3725 load_reg_var(s
, addr
, rn
);
3726 stride
= (1 << size
) * interleave
;
3727 for (reg
= 0; reg
< nregs
; reg
++) {
3728 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3729 load_reg_var(s
, addr
, rn
);
3730 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3731 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3732 load_reg_var(s
, addr
, rn
);
3733 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3735 for (pass
= 0; pass
< 2; pass
++) {
3738 tmp
= gen_ld32(addr
, IS_USER(s
));
3739 neon_store_reg(rd
, pass
, tmp
);
3741 tmp
= neon_load_reg(rd
, pass
);
3742 gen_st32(tmp
, addr
, IS_USER(s
));
3744 tcg_gen_addi_i32(addr
, addr
, stride
);
3745 } else if (size
== 1) {
3747 tmp
= gen_ld16u(addr
, IS_USER(s
));
3748 tcg_gen_addi_i32(addr
, addr
, stride
);
3749 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3750 tcg_gen_addi_i32(addr
, addr
, stride
);
3751 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3753 neon_store_reg(rd
, pass
, tmp
);
3755 tmp
= neon_load_reg(rd
, pass
);
3757 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3758 gen_st16(tmp
, addr
, IS_USER(s
));
3759 tcg_gen_addi_i32(addr
, addr
, stride
);
3760 gen_st16(tmp2
, addr
, IS_USER(s
));
3761 tcg_gen_addi_i32(addr
, addr
, stride
);
3763 } else /* size == 0 */ {
3766 for (n
= 0; n
< 4; n
++) {
3767 tmp
= gen_ld8u(addr
, IS_USER(s
));
3768 tcg_gen_addi_i32(addr
, addr
, stride
);
3772 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3776 neon_store_reg(rd
, pass
, tmp2
);
3778 tmp2
= neon_load_reg(rd
, pass
);
3779 for (n
= 0; n
< 4; n
++) {
3782 tcg_gen_mov_i32(tmp
, tmp2
);
3784 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3786 gen_st8(tmp
, addr
, IS_USER(s
));
3787 tcg_gen_addi_i32(addr
, addr
, stride
);
3793 rd
+= neon_ls_element_type
[op
].spacing
;
3797 size
= (insn
>> 10) & 3;
3799 /* Load single element to all lanes. */
3802 size
= (insn
>> 6) & 3;
3803 nregs
= ((insn
>> 8) & 3) + 1;
3804 stride
= (insn
& (1 << 5)) ? 2 : 1;
3805 load_reg_var(s
, addr
, rn
);
3806 for (reg
= 0; reg
< nregs
; reg
++) {
3809 tmp
= gen_ld8u(addr
, IS_USER(s
));
3810 gen_neon_dup_u8(tmp
, 0);
3813 tmp
= gen_ld16u(addr
, IS_USER(s
));
3814 gen_neon_dup_low16(tmp
);
3817 tmp
= gen_ld32(addr
, IS_USER(s
));
3821 default: /* Avoid compiler warnings. */
3824 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3826 tcg_gen_mov_i32(tmp2
, tmp
);
3827 neon_store_reg(rd
, 0, tmp2
);
3828 neon_store_reg(rd
, 1, tmp
);
3831 stride
= (1 << size
) * nregs
;
3833 /* Single element. */
3834 pass
= (insn
>> 7) & 1;
3837 shift
= ((insn
>> 5) & 3) * 8;
3841 shift
= ((insn
>> 6) & 1) * 16;
3842 stride
= (insn
& (1 << 5)) ? 2 : 1;
3846 stride
= (insn
& (1 << 6)) ? 2 : 1;
3851 nregs
= ((insn
>> 8) & 3) + 1;
3852 load_reg_var(s
, addr
, rn
);
3853 for (reg
= 0; reg
< nregs
; reg
++) {
3857 tmp
= gen_ld8u(addr
, IS_USER(s
));
3860 tmp
= gen_ld16u(addr
, IS_USER(s
));
3863 tmp
= gen_ld32(addr
, IS_USER(s
));
3865 default: /* Avoid compiler warnings. */
3869 tmp2
= neon_load_reg(rd
, pass
);
3870 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3873 neon_store_reg(rd
, pass
, tmp
);
3874 } else { /* Store */
3875 tmp
= neon_load_reg(rd
, pass
);
3877 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3880 gen_st8(tmp
, addr
, IS_USER(s
));
3883 gen_st16(tmp
, addr
, IS_USER(s
));
3886 gen_st32(tmp
, addr
, IS_USER(s
));
3891 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3893 stride
= nregs
* (1 << size
);
3900 base
= load_reg(s
, rn
);
3902 tcg_gen_addi_i32(base
, base
, stride
);
3905 index
= load_reg(s
, rm
);
3906 tcg_gen_add_i32(base
, base
, index
);
3909 store_reg(s
, rn
, base
);
3914 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3915 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3917 tcg_gen_and_i32(t
, t
, c
);
3918 tcg_gen_bic_i32(f
, f
, c
);
3919 tcg_gen_or_i32(dest
, t
, f
);
3922 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3925 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3926 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3927 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3932 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3935 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3936 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3937 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3942 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3945 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3946 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3947 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3952 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3958 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3959 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3964 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3965 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3972 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3973 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3978 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3979 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3986 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3990 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3991 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3992 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3997 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3998 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3999 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4006 static inline void gen_neon_addl(int size
)
4009 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4010 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4011 case 2: tcg_gen_add_i64(CPU_V001
); break;
4016 static inline void gen_neon_subl(int size
)
4019 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4020 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4021 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4026 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4029 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4030 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4031 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4036 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4039 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4040 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4045 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4049 switch ((size
<< 1) | u
) {
4050 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4051 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4052 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4053 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4055 tmp
= gen_muls_i64_i32(a
, b
);
4056 tcg_gen_mov_i64(dest
, tmp
);
4059 tmp
= gen_mulu_i64_i32(a
, b
);
4060 tcg_gen_mov_i64(dest
, tmp
);
4066 /* Translate a NEON data processing instruction. Return nonzero if the
4067 instruction is invalid.
4068 We process data in a mixture of 32-bit and 64-bit chunks.
4069 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4071 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4084 TCGv tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4087 if (!vfp_enabled(env
))
4089 q
= (insn
& (1 << 6)) != 0;
4090 u
= (insn
>> 24) & 1;
4091 VFP_DREG_D(rd
, insn
);
4092 VFP_DREG_N(rn
, insn
);
4093 VFP_DREG_M(rm
, insn
);
4094 size
= (insn
>> 20) & 3;
4095 if ((insn
& (1 << 23)) == 0) {
4096 /* Three register same length. */
4097 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4098 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4099 || op
== 10 || op
== 11 || op
== 16)) {
4100 /* 64-bit element instructions. */
4101 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4102 neon_load_reg64(cpu_V0
, rn
+ pass
);
4103 neon_load_reg64(cpu_V1
, rm
+ pass
);
4107 gen_helper_neon_add_saturate_u64(CPU_V001
);
4109 gen_helper_neon_add_saturate_s64(CPU_V001
);
4114 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4116 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4121 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4123 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4128 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4131 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4135 case 10: /* VRSHL */
4137 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4139 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4142 case 11: /* VQRSHL */
4144 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4147 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4153 tcg_gen_sub_i64(CPU_V001
);
4155 tcg_gen_add_i64(CPU_V001
);
4161 neon_store_reg64(cpu_V0
, rd
+ pass
);
4168 case 10: /* VRSHL */
4169 case 11: /* VQRSHL */
4172 /* Shift instruction operands are reversed. */
4179 case 20: /* VPMAX */
4180 case 21: /* VPMIN */
4181 case 23: /* VPADD */
4184 case 26: /* VPADD (float) */
4185 pairwise
= (u
&& size
< 2);
4187 case 30: /* VPMIN/VPMAX (float) */
4195 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4204 tmp
= neon_load_reg(rn
, n
);
4205 tmp2
= neon_load_reg(rn
, n
+ 1);
4207 tmp
= neon_load_reg(rm
, n
);
4208 tmp2
= neon_load_reg(rm
, n
+ 1);
4212 tmp
= neon_load_reg(rn
, pass
);
4213 tmp2
= neon_load_reg(rm
, pass
);
4217 GEN_NEON_INTEGER_OP(hadd
);
4220 GEN_NEON_INTEGER_OP_ENV(qadd
);
4222 case 2: /* VRHADD */
4223 GEN_NEON_INTEGER_OP(rhadd
);
4225 case 3: /* Logic ops. */
4226 switch ((u
<< 2) | size
) {
4228 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4231 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4234 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4237 tcg_gen_not_i32(tmp2
, tmp2
);
4238 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4241 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4244 tmp3
= neon_load_reg(rd
, pass
);
4245 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4249 tmp3
= neon_load_reg(rd
, pass
);
4250 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4254 tmp3
= neon_load_reg(rd
, pass
);
4255 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4261 GEN_NEON_INTEGER_OP(hsub
);
4264 GEN_NEON_INTEGER_OP_ENV(qsub
);
4267 GEN_NEON_INTEGER_OP(cgt
);
4270 GEN_NEON_INTEGER_OP(cge
);
4273 GEN_NEON_INTEGER_OP(shl
);
4276 GEN_NEON_INTEGER_OP_ENV(qshl
);
4278 case 10: /* VRSHL */
4279 GEN_NEON_INTEGER_OP(rshl
);
4281 case 11: /* VQRSHL */
4282 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4285 GEN_NEON_INTEGER_OP(max
);
4288 GEN_NEON_INTEGER_OP(min
);
4291 GEN_NEON_INTEGER_OP(abd
);
4294 GEN_NEON_INTEGER_OP(abd
);
4296 tmp2
= neon_load_reg(rd
, pass
);
4297 gen_neon_add(size
, tmp
, tmp2
);
4300 if (!u
) { /* VADD */
4301 if (gen_neon_add(size
, tmp
, tmp2
))
4305 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4306 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4307 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4313 if (!u
) { /* VTST */
4315 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4316 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4317 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4322 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4323 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4324 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4329 case 18: /* Multiply. */
4331 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4332 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4333 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4337 tmp2
= neon_load_reg(rd
, pass
);
4339 gen_neon_rsb(size
, tmp
, tmp2
);
4341 gen_neon_add(size
, tmp
, tmp2
);
4345 if (u
) { /* polynomial */
4346 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4347 } else { /* Integer */
4349 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4350 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4351 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4356 case 20: /* VPMAX */
4357 GEN_NEON_INTEGER_OP(pmax
);
4359 case 21: /* VPMIN */
4360 GEN_NEON_INTEGER_OP(pmin
);
4362 case 22: /* Hultiply high. */
4363 if (!u
) { /* VQDMULH */
4365 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4366 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4369 } else { /* VQRDHMUL */
4371 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4372 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4377 case 23: /* VPADD */
4381 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4382 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4383 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4387 case 26: /* Floating point arithnetic. */
4388 switch ((u
<< 2) | size
) {
4390 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4393 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4396 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4399 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4405 case 27: /* Float multiply. */
4406 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4409 tmp2
= neon_load_reg(rd
, pass
);
4411 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4413 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4417 case 28: /* Float compare. */
4419 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4422 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4424 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4427 case 29: /* Float compare absolute. */
4431 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4433 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4435 case 30: /* Float min/max. */
4437 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4439 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4443 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4445 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4452 /* Save the result. For elementwise operations we can put it
4453 straight into the destination register. For pairwise operations
4454 we have to be careful to avoid clobbering the source operands. */
4455 if (pairwise
&& rd
== rm
) {
4456 neon_store_scratch(pass
, tmp
);
4458 neon_store_reg(rd
, pass
, tmp
);
4462 if (pairwise
&& rd
== rm
) {
4463 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4464 tmp
= neon_load_scratch(pass
);
4465 neon_store_reg(rd
, pass
, tmp
);
4468 /* End of 3 register same size operations. */
4469 } else if (insn
& (1 << 4)) {
4470 if ((insn
& 0x00380080) != 0) {
4471 /* Two registers and shift. */
4472 op
= (insn
>> 8) & 0xf;
4473 if (insn
& (1 << 7)) {
4478 while ((insn
& (1 << (size
+ 19))) == 0)
4481 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4482 /* To avoid excessive dumplication of ops we implement shift
4483 by immediate using the variable shift operations. */
4485 /* Shift by immediate:
4486 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4487 /* Right shifts are encoded as N - shift, where N is the
4488 element size in bits. */
4490 shift
= shift
- (1 << (size
+ 3));
4498 imm
= (uint8_t) shift
;
4503 imm
= (uint16_t) shift
;
4514 for (pass
= 0; pass
< count
; pass
++) {
4516 neon_load_reg64(cpu_V0
, rm
+ pass
);
4517 tcg_gen_movi_i64(cpu_V1
, imm
);
4522 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4524 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4529 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4531 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4536 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4538 case 5: /* VSHL, VSLI */
4539 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4543 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4545 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4547 case 7: /* VQSHLU */
4548 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4551 if (op
== 1 || op
== 3) {
4553 neon_load_reg64(cpu_V0
, rd
+ pass
);
4554 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4555 } else if (op
== 4 || (op
== 5 && u
)) {
4557 cpu_abort(env
, "VS[LR]I.64 not implemented");
4559 neon_store_reg64(cpu_V0
, rd
+ pass
);
4560 } else { /* size < 3 */
4561 /* Operands in T0 and T1. */
4562 tmp
= neon_load_reg(rm
, pass
);
4564 tcg_gen_movi_i32(tmp2
, imm
);
4568 GEN_NEON_INTEGER_OP(shl
);
4572 GEN_NEON_INTEGER_OP(rshl
);
4577 GEN_NEON_INTEGER_OP(shl
);
4579 case 5: /* VSHL, VSLI */
4581 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4582 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4583 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4588 GEN_NEON_INTEGER_OP_ENV(qshl
);
4590 case 7: /* VQSHLU */
4592 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4593 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4594 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4601 if (op
== 1 || op
== 3) {
4603 tmp2
= neon_load_reg(rd
, pass
);
4604 gen_neon_add(size
, tmp2
, tmp
);
4606 } else if (op
== 4 || (op
== 5 && u
)) {
4611 imm
= 0xff >> -shift
;
4613 imm
= (uint8_t)(0xff << shift
);
4619 imm
= 0xffff >> -shift
;
4621 imm
= (uint16_t)(0xffff << shift
);
4626 imm
= 0xffffffffu
>> -shift
;
4628 imm
= 0xffffffffu
<< shift
;
4633 tmp2
= neon_load_reg(rd
, pass
);
4634 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4635 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4636 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4639 neon_store_reg(rd
, pass
, tmp
);
4642 } else if (op
< 10) {
4643 /* Shift by immediate and narrow:
4644 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4645 shift
= shift
- (1 << (size
+ 3));
4649 imm
= (uint16_t)shift
;
4651 tmp2
= tcg_const_i32(imm
);
4652 TCGV_UNUSED_I64(tmp64
);
4655 imm
= (uint32_t)shift
;
4656 tmp2
= tcg_const_i32(imm
);
4657 TCGV_UNUSED_I64(tmp64
);
4660 tmp64
= tcg_const_i64(shift
);
4667 for (pass
= 0; pass
< 2; pass
++) {
4669 neon_load_reg64(cpu_V0
, rm
+ pass
);
4672 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4674 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4677 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4679 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4682 tmp
= neon_load_reg(rm
+ pass
, 0);
4683 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4684 tmp3
= neon_load_reg(rm
+ pass
, 1);
4685 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4686 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4691 if (op
== 8 && !u
) {
4692 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4695 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4697 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4705 neon_store_reg(rd
, 0, tmp2
);
4706 neon_store_reg(rd
, 1, tmp
);
4710 tcg_temp_free_i64(tmp64
);
4712 } else if (op
== 10) {
4716 tmp
= neon_load_reg(rm
, 0);
4717 tmp2
= neon_load_reg(rm
, 1);
4718 for (pass
= 0; pass
< 2; pass
++) {
4722 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4725 /* The shift is less than the width of the source
4726 type, so we can just shift the whole register. */
4727 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4728 if (size
< 2 || !u
) {
4731 imm
= (0xffu
>> (8 - shift
));
4734 imm
= 0xffff >> (16 - shift
);
4736 imm64
= imm
| (((uint64_t)imm
) << 32);
4737 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4740 neon_store_reg64(cpu_V0
, rd
+ pass
);
4742 } else if (op
== 15 || op
== 16) {
4743 /* VCVT fixed-point. */
4744 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4745 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4748 gen_vfp_ulto(0, shift
);
4750 gen_vfp_slto(0, shift
);
4753 gen_vfp_toul(0, shift
);
4755 gen_vfp_tosl(0, shift
);
4757 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4762 } else { /* (insn & 0x00380080) == 0 */
4765 op
= (insn
>> 8) & 0xf;
4766 /* One register and immediate. */
4767 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4768 invert
= (insn
& (1 << 5)) != 0;
4786 imm
= (imm
<< 8) | (imm
<< 24);
4789 imm
= (imm
< 8) | 0xff;
4792 imm
= (imm
<< 16) | 0xffff;
4795 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4800 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4801 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4807 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4808 if (op
& 1 && op
< 12) {
4809 tmp
= neon_load_reg(rd
, pass
);
4811 /* The immediate value has already been inverted, so
4813 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4815 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4820 if (op
== 14 && invert
) {
4823 for (n
= 0; n
< 4; n
++) {
4824 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4825 val
|= 0xff << (n
* 8);
4827 tcg_gen_movi_i32(tmp
, val
);
4829 tcg_gen_movi_i32(tmp
, imm
);
4832 neon_store_reg(rd
, pass
, tmp
);
4835 } else { /* (insn & 0x00800010 == 0x00800000) */
4837 op
= (insn
>> 8) & 0xf;
4838 if ((insn
& (1 << 6)) == 0) {
4839 /* Three registers of different lengths. */
4843 /* prewiden, src1_wide, src2_wide */
4844 static const int neon_3reg_wide
[16][3] = {
4845 {1, 0, 0}, /* VADDL */
4846 {1, 1, 0}, /* VADDW */
4847 {1, 0, 0}, /* VSUBL */
4848 {1, 1, 0}, /* VSUBW */
4849 {0, 1, 1}, /* VADDHN */
4850 {0, 0, 0}, /* VABAL */
4851 {0, 1, 1}, /* VSUBHN */
4852 {0, 0, 0}, /* VABDL */
4853 {0, 0, 0}, /* VMLAL */
4854 {0, 0, 0}, /* VQDMLAL */
4855 {0, 0, 0}, /* VMLSL */
4856 {0, 0, 0}, /* VQDMLSL */
4857 {0, 0, 0}, /* Integer VMULL */
4858 {0, 0, 0}, /* VQDMULL */
4859 {0, 0, 0} /* Polynomial VMULL */
4862 prewiden
= neon_3reg_wide
[op
][0];
4863 src1_wide
= neon_3reg_wide
[op
][1];
4864 src2_wide
= neon_3reg_wide
[op
][2];
4866 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4869 /* Avoid overlapping operands. Wide source operands are
4870 always aligned so will never overlap with wide
4871 destinations in problematic ways. */
4872 if (rd
== rm
&& !src2_wide
) {
4873 tmp
= neon_load_reg(rm
, 1);
4874 neon_store_scratch(2, tmp
);
4875 } else if (rd
== rn
&& !src1_wide
) {
4876 tmp
= neon_load_reg(rn
, 1);
4877 neon_store_scratch(2, tmp
);
4880 for (pass
= 0; pass
< 2; pass
++) {
4882 neon_load_reg64(cpu_V0
, rn
+ pass
);
4885 if (pass
== 1 && rd
== rn
) {
4886 tmp
= neon_load_scratch(2);
4888 tmp
= neon_load_reg(rn
, pass
);
4891 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4895 neon_load_reg64(cpu_V1
, rm
+ pass
);
4898 if (pass
== 1 && rd
== rm
) {
4899 tmp2
= neon_load_scratch(2);
4901 tmp2
= neon_load_reg(rm
, pass
);
4904 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4908 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4909 gen_neon_addl(size
);
4911 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4912 gen_neon_subl(size
);
4914 case 5: case 7: /* VABAL, VABDL */
4915 switch ((size
<< 1) | u
) {
4917 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4920 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4923 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4926 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4929 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4932 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4939 case 8: case 9: case 10: case 11: case 12: case 13:
4940 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4941 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4945 case 14: /* Polynomial VMULL */
4946 cpu_abort(env
, "Polynomial VMULL not implemented");
4948 default: /* 15 is RESERVED. */
4951 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4953 if (op
== 10 || op
== 11) {
4954 gen_neon_negl(cpu_V0
, size
);
4958 neon_load_reg64(cpu_V1
, rd
+ pass
);
4962 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4963 gen_neon_addl(size
);
4965 case 9: case 11: /* VQDMLAL, VQDMLSL */
4966 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4967 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4970 case 13: /* VQDMULL */
4971 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4976 neon_store_reg64(cpu_V0
, rd
+ pass
);
4977 } else if (op
== 4 || op
== 6) {
4978 /* Narrowing operation. */
4983 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4986 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4989 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4990 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4997 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5000 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5003 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5004 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5005 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5013 neon_store_reg(rd
, 0, tmp3
);
5014 neon_store_reg(rd
, 1, tmp
);
5017 /* Write back the result. */
5018 neon_store_reg64(cpu_V0
, rd
+ pass
);
5022 /* Two registers and a scalar. */
5024 case 0: /* Integer VMLA scalar */
5025 case 1: /* Float VMLA scalar */
5026 case 4: /* Integer VMLS scalar */
5027 case 5: /* Floating point VMLS scalar */
5028 case 8: /* Integer VMUL scalar */
5029 case 9: /* Floating point VMUL scalar */
5030 case 12: /* VQDMULH scalar */
5031 case 13: /* VQRDMULH scalar */
5032 tmp
= neon_get_scalar(size
, rm
);
5033 neon_store_scratch(0, tmp
);
5034 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5035 tmp
= neon_load_scratch(0);
5036 tmp2
= neon_load_reg(rn
, pass
);
5039 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5041 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5043 } else if (op
== 13) {
5045 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5047 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5049 } else if (op
& 1) {
5050 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5053 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5054 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5055 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5062 tmp2
= neon_load_reg(rd
, pass
);
5065 gen_neon_add(size
, tmp
, tmp2
);
5068 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5071 gen_neon_rsb(size
, tmp
, tmp2
);
5074 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5081 neon_store_reg(rd
, pass
, tmp
);
5084 case 2: /* VMLAL sclar */
5085 case 3: /* VQDMLAL scalar */
5086 case 6: /* VMLSL scalar */
5087 case 7: /* VQDMLSL scalar */
5088 case 10: /* VMULL scalar */
5089 case 11: /* VQDMULL scalar */
5090 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5093 tmp2
= neon_get_scalar(size
, rm
);
5094 tmp3
= neon_load_reg(rn
, 1);
5096 for (pass
= 0; pass
< 2; pass
++) {
5098 tmp
= neon_load_reg(rn
, 0);
5102 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5104 if (op
== 6 || op
== 7) {
5105 gen_neon_negl(cpu_V0
, size
);
5108 neon_load_reg64(cpu_V1
, rd
+ pass
);
5112 gen_neon_addl(size
);
5115 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5116 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5122 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5127 neon_store_reg64(cpu_V0
, rd
+ pass
);
5133 default: /* 14 and 15 are RESERVED */
5137 } else { /* size == 3 */
5140 imm
= (insn
>> 8) & 0xf;
5147 neon_load_reg64(cpu_V0
, rn
);
5149 neon_load_reg64(cpu_V1
, rn
+ 1);
5151 } else if (imm
== 8) {
5152 neon_load_reg64(cpu_V0
, rn
+ 1);
5154 neon_load_reg64(cpu_V1
, rm
);
5157 tmp64
= tcg_temp_new_i64();
5159 neon_load_reg64(cpu_V0
, rn
);
5160 neon_load_reg64(tmp64
, rn
+ 1);
5162 neon_load_reg64(cpu_V0
, rn
+ 1);
5163 neon_load_reg64(tmp64
, rm
);
5165 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5166 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5167 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5169 neon_load_reg64(cpu_V1
, rm
);
5171 neon_load_reg64(cpu_V1
, rm
+ 1);
5174 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5175 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5176 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5177 tcg_temp_free_i64(tmp64
);
5180 neon_load_reg64(cpu_V0
, rn
);
5181 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5182 neon_load_reg64(cpu_V1
, rm
);
5183 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5184 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5186 neon_store_reg64(cpu_V0
, rd
);
5188 neon_store_reg64(cpu_V1
, rd
+ 1);
5190 } else if ((insn
& (1 << 11)) == 0) {
5191 /* Two register misc. */
5192 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5193 size
= (insn
>> 18) & 3;
5195 case 0: /* VREV64 */
5198 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5199 tmp
= neon_load_reg(rm
, pass
* 2);
5200 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5202 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5203 case 1: gen_swap_half(tmp
); break;
5204 case 2: /* no-op */ break;
5207 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5209 neon_store_reg(rd
, pass
* 2, tmp2
);
5212 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5213 case 1: gen_swap_half(tmp2
); break;
5216 neon_store_reg(rd
, pass
* 2, tmp2
);
5220 case 4: case 5: /* VPADDL */
5221 case 12: case 13: /* VPADAL */
5224 for (pass
= 0; pass
< q
+ 1; pass
++) {
5225 tmp
= neon_load_reg(rm
, pass
* 2);
5226 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5227 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5228 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5230 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5231 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5232 case 2: tcg_gen_add_i64(CPU_V001
); break;
5237 neon_load_reg64(cpu_V1
, rd
+ pass
);
5238 gen_neon_addl(size
);
5240 neon_store_reg64(cpu_V0
, rd
+ pass
);
5245 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5246 tmp
= neon_load_reg(rm
, n
);
5247 tmp2
= neon_load_reg(rd
, n
+ 1);
5248 neon_store_reg(rm
, n
, tmp2
);
5249 neon_store_reg(rd
, n
+ 1, tmp
);
5257 Rd A3 A2 A1 A0 B2 B0 A2 A0
5258 Rm B3 B2 B1 B0 B3 B1 A3 A1
5262 gen_neon_unzip(rd
, q
, 0, size
);
5263 gen_neon_unzip(rm
, q
, 4, size
);
5265 static int unzip_order_q
[8] =
5266 {0, 2, 4, 6, 1, 3, 5, 7};
5267 for (n
= 0; n
< 8; n
++) {
5268 int reg
= (n
< 4) ? rd
: rm
;
5269 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5270 neon_store_reg(reg
, n
% 4, tmp
);
5273 static int unzip_order
[4] =
5275 for (n
= 0; n
< 4; n
++) {
5276 int reg
= (n
< 2) ? rd
: rm
;
5277 tmp
= neon_load_scratch(unzip_order
[n
]);
5278 neon_store_reg(reg
, n
% 2, tmp
);
5284 Rd A3 A2 A1 A0 B1 A1 B0 A0
5285 Rm B3 B2 B1 B0 B3 A3 B2 A2
5289 count
= (q
? 4 : 2);
5290 for (n
= 0; n
< count
; n
++) {
5291 tmp
= neon_load_reg(rd
, n
);
5292 tmp2
= neon_load_reg(rd
, n
);
5294 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5295 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5296 case 2: /* no-op */; break;
5299 neon_store_scratch(n
* 2, tmp
);
5300 neon_store_scratch(n
* 2 + 1, tmp2
);
5302 for (n
= 0; n
< count
* 2; n
++) {
5303 int reg
= (n
< count
) ? rd
: rm
;
5304 tmp
= neon_load_scratch(n
);
5305 neon_store_reg(reg
, n
% count
, tmp
);
5308 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5312 for (pass
= 0; pass
< 2; pass
++) {
5313 neon_load_reg64(cpu_V0
, rm
+ pass
);
5315 if (op
== 36 && q
== 0) {
5316 gen_neon_narrow(size
, tmp
, cpu_V0
);
5318 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5320 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5325 neon_store_reg(rd
, 0, tmp2
);
5326 neon_store_reg(rd
, 1, tmp
);
5330 case 38: /* VSHLL */
5333 tmp
= neon_load_reg(rm
, 0);
5334 tmp2
= neon_load_reg(rm
, 1);
5335 for (pass
= 0; pass
< 2; pass
++) {
5338 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5339 neon_store_reg64(cpu_V0
, rd
+ pass
);
5344 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5345 if (op
== 30 || op
== 31 || op
>= 58) {
5346 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5347 neon_reg_offset(rm
, pass
));
5350 tmp
= neon_load_reg(rm
, pass
);
5353 case 1: /* VREV32 */
5355 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5356 case 1: gen_swap_half(tmp
); break;
5360 case 2: /* VREV16 */
5367 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5368 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5369 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5375 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5376 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5377 case 2: gen_helper_clz(tmp
, tmp
); break;
5384 gen_helper_neon_cnt_u8(tmp
, tmp
);
5389 tcg_gen_not_i32(tmp
, tmp
);
5391 case 14: /* VQABS */
5393 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5394 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5395 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5399 case 15: /* VQNEG */
5401 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5402 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5403 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5407 case 16: case 19: /* VCGT #0, VCLE #0 */
5408 tmp2
= tcg_const_i32(0);
5410 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5411 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5412 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5415 tcg_temp_free(tmp2
);
5417 tcg_gen_not_i32(tmp
, tmp
);
5419 case 17: case 20: /* VCGE #0, VCLT #0 */
5420 tmp2
= tcg_const_i32(0);
5422 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5423 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5424 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5427 tcg_temp_free(tmp2
);
5429 tcg_gen_not_i32(tmp
, tmp
);
5431 case 18: /* VCEQ #0 */
5432 tmp2
= tcg_const_i32(0);
5434 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5435 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5436 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5439 tcg_temp_free(tmp2
);
5443 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5444 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5445 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5452 tmp2
= tcg_const_i32(0);
5453 gen_neon_rsb(size
, tmp
, tmp2
);
5454 tcg_temp_free(tmp2
);
5456 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5457 tmp2
= tcg_const_i32(0);
5458 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5459 tcg_temp_free(tmp2
);
5461 tcg_gen_not_i32(tmp
, tmp
);
5463 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5464 tmp2
= tcg_const_i32(0);
5465 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5466 tcg_temp_free(tmp2
);
5468 tcg_gen_not_i32(tmp
, tmp
);
5470 case 26: /* Float VCEQ #0 */
5471 tmp2
= tcg_const_i32(0);
5472 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5473 tcg_temp_free(tmp2
);
5475 case 30: /* Float VABS */
5478 case 31: /* Float VNEG */
5482 tmp2
= neon_load_reg(rd
, pass
);
5483 neon_store_reg(rm
, pass
, tmp2
);
5486 tmp2
= neon_load_reg(rd
, pass
);
5488 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5489 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5493 neon_store_reg(rm
, pass
, tmp2
);
5495 case 56: /* Integer VRECPE */
5496 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5498 case 57: /* Integer VRSQRTE */
5499 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5501 case 58: /* Float VRECPE */
5502 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5504 case 59: /* Float VRSQRTE */
5505 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5507 case 60: /* VCVT.F32.S32 */
5510 case 61: /* VCVT.F32.U32 */
5513 case 62: /* VCVT.S32.F32 */
5516 case 63: /* VCVT.U32.F32 */
5520 /* Reserved: 21, 29, 39-56 */
5523 if (op
== 30 || op
== 31 || op
>= 58) {
5524 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5525 neon_reg_offset(rd
, pass
));
5527 neon_store_reg(rd
, pass
, tmp
);
5532 } else if ((insn
& (1 << 10)) == 0) {
5534 n
= ((insn
>> 5) & 0x18) + 8;
5535 if (insn
& (1 << 6)) {
5536 tmp
= neon_load_reg(rd
, 0);
5539 tcg_gen_movi_i32(tmp
, 0);
5541 tmp2
= neon_load_reg(rm
, 0);
5542 tmp4
= tcg_const_i32(rn
);
5543 tmp5
= tcg_const_i32(n
);
5544 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tmp4
, tmp5
);
5546 if (insn
& (1 << 6)) {
5547 tmp
= neon_load_reg(rd
, 1);
5550 tcg_gen_movi_i32(tmp
, 0);
5552 tmp3
= neon_load_reg(rm
, 1);
5553 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tmp4
, tmp5
);
5556 neon_store_reg(rd
, 0, tmp2
);
5557 neon_store_reg(rd
, 1, tmp3
);
5559 } else if ((insn
& 0x380) == 0) {
5561 if (insn
& (1 << 19)) {
5562 tmp
= neon_load_reg(rm
, 1);
5564 tmp
= neon_load_reg(rm
, 0);
5566 if (insn
& (1 << 16)) {
5567 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5568 } else if (insn
& (1 << 17)) {
5569 if ((insn
>> 18) & 1)
5570 gen_neon_dup_high16(tmp
);
5572 gen_neon_dup_low16(tmp
);
5574 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5576 tcg_gen_mov_i32(tmp2
, tmp
);
5577 neon_store_reg(rd
, pass
, tmp2
);
5588 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5590 int crn
= (insn
>> 16) & 0xf;
5591 int crm
= insn
& 0xf;
5592 int op1
= (insn
>> 21) & 7;
5593 int op2
= (insn
>> 5) & 7;
5594 int rt
= (insn
>> 12) & 0xf;
5597 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5598 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5602 tmp
= load_cpu_field(teecr
);
5603 store_reg(s
, rt
, tmp
);
5606 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5608 if (IS_USER(s
) && (env
->teecr
& 1))
5610 tmp
= load_cpu_field(teehbr
);
5611 store_reg(s
, rt
, tmp
);
5615 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5616 op1
, crn
, crm
, op2
);
5620 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5622 int crn
= (insn
>> 16) & 0xf;
5623 int crm
= insn
& 0xf;
5624 int op1
= (insn
>> 21) & 7;
5625 int op2
= (insn
>> 5) & 7;
5626 int rt
= (insn
>> 12) & 0xf;
5629 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5630 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5634 tmp
= load_reg(s
, rt
);
5635 gen_helper_set_teecr(cpu_env
, tmp
);
5639 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5641 if (IS_USER(s
) && (env
->teecr
& 1))
5643 tmp
= load_reg(s
, rt
);
5644 store_cpu_field(tmp
, teehbr
);
5648 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5649 op1
, crn
, crm
, op2
);
5653 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5657 cpnum
= (insn
>> 8) & 0xf;
5658 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5659 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5665 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5666 return disas_iwmmxt_insn(env
, s
, insn
);
5667 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5668 return disas_dsp_insn(env
, s
, insn
);
5673 return disas_vfp_insn (env
, s
, insn
);
5675 /* Coprocessors 7-15 are architecturally reserved by ARM.
5676 Unfortunately Intel decided to ignore this. */
5677 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5679 if (insn
& (1 << 20))
5680 return disas_cp14_read(env
, s
, insn
);
5682 return disas_cp14_write(env
, s
, insn
);
5684 return disas_cp15_insn (env
, s
, insn
);
5687 /* Unknown coprocessor. See if the board has hooked it. */
5688 return disas_cp_insn (env
, s
, insn
);
5693 /* Store a 64-bit value to a register pair. Clobbers val. */
5694 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5698 tcg_gen_trunc_i64_i32(tmp
, val
);
5699 store_reg(s
, rlow
, tmp
);
5701 tcg_gen_shri_i64(val
, val
, 32);
5702 tcg_gen_trunc_i64_i32(tmp
, val
);
5703 store_reg(s
, rhigh
, tmp
);
5706 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5707 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5712 /* Load value and extend to 64 bits. */
5713 tmp
= tcg_temp_new_i64();
5714 tmp2
= load_reg(s
, rlow
);
5715 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5717 tcg_gen_add_i64(val
, val
, tmp
);
5718 tcg_temp_free_i64(tmp
);
5721 /* load and add a 64-bit value from a register pair. */
5722 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5728 /* Load 64-bit value rd:rn. */
5729 tmpl
= load_reg(s
, rlow
);
5730 tmph
= load_reg(s
, rhigh
);
5731 tmp
= tcg_temp_new_i64();
5732 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5735 tcg_gen_add_i64(val
, val
, tmp
);
5736 tcg_temp_free_i64(tmp
);
5739 /* Set N and Z flags from a 64-bit value. */
5740 static void gen_logicq_cc(TCGv_i64 val
)
5742 TCGv tmp
= new_tmp();
5743 gen_helper_logicq_cc(tmp
, val
);
5748 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5750 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5757 insn
= ldl_code(s
->pc
);
5760 /* M variants do not implement ARM mode. */
5765 /* Unconditional instructions. */
5766 if (((insn
>> 25) & 7) == 1) {
5767 /* NEON Data processing. */
5768 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5771 if (disas_neon_data_insn(env
, s
, insn
))
5775 if ((insn
& 0x0f100000) == 0x04000000) {
5776 /* NEON load/store. */
5777 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5780 if (disas_neon_ls_insn(env
, s
, insn
))
5784 if ((insn
& 0x0d70f000) == 0x0550f000)
5786 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5789 if (insn
& (1 << 9)) {
5790 /* BE8 mode not implemented. */
5794 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5795 switch ((insn
>> 4) & 0xf) {
5798 gen_helper_clrex(cpu_env
);
5804 /* We don't emulate caches so these are a no-op. */
5809 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5815 op1
= (insn
& 0x1f);
5816 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5817 addr
= load_reg(s
, 13);
5820 tmp
= tcg_const_i32(op1
);
5821 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
5822 tcg_temp_free_i32(tmp
);
5824 i
= (insn
>> 23) & 3;
5826 case 0: offset
= -4; break; /* DA */
5827 case 1: offset
= 0; break; /* IA */
5828 case 2: offset
= -8; break; /* DB */
5829 case 3: offset
= 4; break; /* IB */
5833 tcg_gen_addi_i32(addr
, addr
, offset
);
5834 tmp
= load_reg(s
, 14);
5835 gen_st32(tmp
, addr
, 0);
5836 tmp
= load_cpu_field(spsr
);
5837 tcg_gen_addi_i32(addr
, addr
, 4);
5838 gen_st32(tmp
, addr
, 0);
5839 if (insn
& (1 << 21)) {
5840 /* Base writeback. */
5842 case 0: offset
= -8; break;
5843 case 1: offset
= 4; break;
5844 case 2: offset
= -4; break;
5845 case 3: offset
= 0; break;
5849 tcg_gen_addi_i32(addr
, addr
, offset
);
5850 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5851 store_reg(s
, 13, addr
);
5853 tmp
= tcg_const_i32(op1
);
5854 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
5855 tcg_temp_free_i32(tmp
);
5861 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5867 rn
= (insn
>> 16) & 0xf;
5868 addr
= load_reg(s
, rn
);
5869 i
= (insn
>> 23) & 3;
5871 case 0: offset
= -4; break; /* DA */
5872 case 1: offset
= 0; break; /* IA */
5873 case 2: offset
= -8; break; /* DB */
5874 case 3: offset
= 4; break; /* IB */
5878 tcg_gen_addi_i32(addr
, addr
, offset
);
5879 /* Load PC into tmp and CPSR into tmp2. */
5880 tmp
= gen_ld32(addr
, 0);
5881 tcg_gen_addi_i32(addr
, addr
, 4);
5882 tmp2
= gen_ld32(addr
, 0);
5883 if (insn
& (1 << 21)) {
5884 /* Base writeback. */
5886 case 0: offset
= -8; break;
5887 case 1: offset
= 4; break;
5888 case 2: offset
= -4; break;
5889 case 3: offset
= 0; break;
5893 tcg_gen_addi_i32(addr
, addr
, offset
);
5894 store_reg(s
, rn
, addr
);
5898 gen_rfe(s
, tmp
, tmp2
);
5900 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5901 /* branch link and change to thumb (blx <offset>) */
5904 val
= (uint32_t)s
->pc
;
5906 tcg_gen_movi_i32(tmp
, val
);
5907 store_reg(s
, 14, tmp
);
5908 /* Sign-extend the 24-bit offset */
5909 offset
= (((int32_t)insn
) << 8) >> 8;
5910 /* offset * 4 + bit24 * 2 + (thumb bit) */
5911 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5912 /* pipeline offset */
5916 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5917 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5918 /* iWMMXt register transfer. */
5919 if (env
->cp15
.c15_cpar
& (1 << 1))
5920 if (!disas_iwmmxt_insn(env
, s
, insn
))
5923 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5924 /* Coprocessor double register transfer. */
5925 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5926 /* Additional coprocessor register transfer. */
5927 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5930 /* cps (privileged) */
5934 if (insn
& (1 << 19)) {
5935 if (insn
& (1 << 8))
5937 if (insn
& (1 << 7))
5939 if (insn
& (1 << 6))
5941 if (insn
& (1 << 18))
5944 if (insn
& (1 << 17)) {
5946 val
|= (insn
& 0x1f);
5949 gen_set_psr_im(s
, mask
, 0, val
);
5956 /* if not always execute, we generate a conditional jump to
5958 s
->condlabel
= gen_new_label();
5959 gen_test_cc(cond
^ 1, s
->condlabel
);
5962 if ((insn
& 0x0f900000) == 0x03000000) {
5963 if ((insn
& (1 << 21)) == 0) {
5965 rd
= (insn
>> 12) & 0xf;
5966 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5967 if ((insn
& (1 << 22)) == 0) {
5970 tcg_gen_movi_i32(tmp
, val
);
5973 tmp
= load_reg(s
, rd
);
5974 tcg_gen_ext16u_i32(tmp
, tmp
);
5975 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5977 store_reg(s
, rd
, tmp
);
5979 if (((insn
>> 12) & 0xf) != 0xf)
5981 if (((insn
>> 16) & 0xf) == 0) {
5982 gen_nop_hint(s
, insn
& 0xff);
5984 /* CPSR = immediate */
5986 shift
= ((insn
>> 8) & 0xf) * 2;
5988 val
= (val
>> shift
) | (val
<< (32 - shift
));
5989 i
= ((insn
& (1 << 22)) != 0);
5990 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5994 } else if ((insn
& 0x0f900000) == 0x01000000
5995 && (insn
& 0x00000090) != 0x00000090) {
5996 /* miscellaneous instructions */
5997 op1
= (insn
>> 21) & 3;
5998 sh
= (insn
>> 4) & 0xf;
6001 case 0x0: /* move program status register */
6004 tmp
= load_reg(s
, rm
);
6005 i
= ((op1
& 2) != 0);
6006 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6010 rd
= (insn
>> 12) & 0xf;
6014 tmp
= load_cpu_field(spsr
);
6017 gen_helper_cpsr_read(tmp
);
6019 store_reg(s
, rd
, tmp
);
6024 /* branch/exchange thumb (bx). */
6025 tmp
= load_reg(s
, rm
);
6027 } else if (op1
== 3) {
6029 rd
= (insn
>> 12) & 0xf;
6030 tmp
= load_reg(s
, rm
);
6031 gen_helper_clz(tmp
, tmp
);
6032 store_reg(s
, rd
, tmp
);
6040 /* Trivial implementation equivalent to bx. */
6041 tmp
= load_reg(s
, rm
);
6051 /* branch link/exchange thumb (blx) */
6052 tmp
= load_reg(s
, rm
);
6054 tcg_gen_movi_i32(tmp2
, s
->pc
);
6055 store_reg(s
, 14, tmp2
);
6058 case 0x5: /* saturating add/subtract */
6059 rd
= (insn
>> 12) & 0xf;
6060 rn
= (insn
>> 16) & 0xf;
6061 tmp
= load_reg(s
, rm
);
6062 tmp2
= load_reg(s
, rn
);
6064 gen_helper_double_saturate(tmp2
, tmp2
);
6066 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6068 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6070 store_reg(s
, rd
, tmp
);
6073 gen_set_condexec(s
);
6074 gen_set_pc_im(s
->pc
- 4);
6075 gen_exception(EXCP_BKPT
);
6076 s
->is_jmp
= DISAS_JUMP
;
6078 case 0x8: /* signed multiply */
6082 rs
= (insn
>> 8) & 0xf;
6083 rn
= (insn
>> 12) & 0xf;
6084 rd
= (insn
>> 16) & 0xf;
6086 /* (32 * 16) >> 16 */
6087 tmp
= load_reg(s
, rm
);
6088 tmp2
= load_reg(s
, rs
);
6090 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6093 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6094 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6096 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6097 tcg_temp_free_i64(tmp64
);
6098 if ((sh
& 2) == 0) {
6099 tmp2
= load_reg(s
, rn
);
6100 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6103 store_reg(s
, rd
, tmp
);
6106 tmp
= load_reg(s
, rm
);
6107 tmp2
= load_reg(s
, rs
);
6108 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6111 tmp64
= tcg_temp_new_i64();
6112 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6114 gen_addq(s
, tmp64
, rn
, rd
);
6115 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6116 tcg_temp_free_i64(tmp64
);
6119 tmp2
= load_reg(s
, rn
);
6120 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6123 store_reg(s
, rd
, tmp
);
6130 } else if (((insn
& 0x0e000000) == 0 &&
6131 (insn
& 0x00000090) != 0x90) ||
6132 ((insn
& 0x0e000000) == (1 << 25))) {
6133 int set_cc
, logic_cc
, shiftop
;
6135 op1
= (insn
>> 21) & 0xf;
6136 set_cc
= (insn
>> 20) & 1;
6137 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6139 /* data processing instruction */
6140 if (insn
& (1 << 25)) {
6141 /* immediate operand */
6143 shift
= ((insn
>> 8) & 0xf) * 2;
6145 val
= (val
>> shift
) | (val
<< (32 - shift
));
6148 tcg_gen_movi_i32(tmp2
, val
);
6149 if (logic_cc
&& shift
) {
6150 gen_set_CF_bit31(tmp2
);
6155 tmp2
= load_reg(s
, rm
);
6156 shiftop
= (insn
>> 5) & 3;
6157 if (!(insn
& (1 << 4))) {
6158 shift
= (insn
>> 7) & 0x1f;
6159 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6161 rs
= (insn
>> 8) & 0xf;
6162 tmp
= load_reg(s
, rs
);
6163 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6166 if (op1
!= 0x0f && op1
!= 0x0d) {
6167 rn
= (insn
>> 16) & 0xf;
6168 tmp
= load_reg(s
, rn
);
6172 rd
= (insn
>> 12) & 0xf;
6175 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6179 store_reg_bx(env
, s
, rd
, tmp
);
6182 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6186 store_reg_bx(env
, s
, rd
, tmp
);
6189 if (set_cc
&& rd
== 15) {
6190 /* SUBS r15, ... is used for exception return. */
6194 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6195 gen_exception_return(s
, tmp
);
6198 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6200 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6202 store_reg_bx(env
, s
, rd
, tmp
);
6207 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6209 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6211 store_reg_bx(env
, s
, rd
, tmp
);
6215 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6217 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6219 store_reg_bx(env
, s
, rd
, tmp
);
6223 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6225 gen_add_carry(tmp
, tmp
, tmp2
);
6227 store_reg_bx(env
, s
, rd
, tmp
);
6231 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6233 gen_sub_carry(tmp
, tmp
, tmp2
);
6235 store_reg_bx(env
, s
, rd
, tmp
);
6239 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6241 gen_sub_carry(tmp
, tmp2
, tmp
);
6243 store_reg_bx(env
, s
, rd
, tmp
);
6247 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6254 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6261 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6267 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6272 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6276 store_reg_bx(env
, s
, rd
, tmp
);
6279 if (logic_cc
&& rd
== 15) {
6280 /* MOVS r15, ... is used for exception return. */
6284 gen_exception_return(s
, tmp2
);
6289 store_reg_bx(env
, s
, rd
, tmp2
);
6293 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6297 store_reg_bx(env
, s
, rd
, tmp
);
6301 tcg_gen_not_i32(tmp2
, tmp2
);
6305 store_reg_bx(env
, s
, rd
, tmp2
);
6308 if (op1
!= 0x0f && op1
!= 0x0d) {
6312 /* other instructions */
6313 op1
= (insn
>> 24) & 0xf;
6317 /* multiplies, extra load/stores */
6318 sh
= (insn
>> 5) & 3;
6321 rd
= (insn
>> 16) & 0xf;
6322 rn
= (insn
>> 12) & 0xf;
6323 rs
= (insn
>> 8) & 0xf;
6325 op1
= (insn
>> 20) & 0xf;
6327 case 0: case 1: case 2: case 3: case 6:
6329 tmp
= load_reg(s
, rs
);
6330 tmp2
= load_reg(s
, rm
);
6331 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6333 if (insn
& (1 << 22)) {
6334 /* Subtract (mls) */
6336 tmp2
= load_reg(s
, rn
);
6337 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6339 } else if (insn
& (1 << 21)) {
6341 tmp2
= load_reg(s
, rn
);
6342 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6345 if (insn
& (1 << 20))
6347 store_reg(s
, rd
, tmp
);
6351 tmp
= load_reg(s
, rs
);
6352 tmp2
= load_reg(s
, rm
);
6353 if (insn
& (1 << 22))
6354 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6356 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6357 if (insn
& (1 << 21)) /* mult accumulate */
6358 gen_addq(s
, tmp64
, rn
, rd
);
6359 if (!(insn
& (1 << 23))) { /* double accumulate */
6361 gen_addq_lo(s
, tmp64
, rn
);
6362 gen_addq_lo(s
, tmp64
, rd
);
6364 if (insn
& (1 << 20))
6365 gen_logicq_cc(tmp64
);
6366 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6367 tcg_temp_free_i64(tmp64
);
6371 rn
= (insn
>> 16) & 0xf;
6372 rd
= (insn
>> 12) & 0xf;
6373 if (insn
& (1 << 23)) {
6374 /* load/store exclusive */
6375 op1
= (insn
>> 21) & 0x3;
6380 addr
= tcg_temp_local_new_i32();
6381 load_reg_var(s
, addr
, rn
);
6382 if (insn
& (1 << 20)) {
6383 gen_helper_mark_exclusive(cpu_env
, addr
);
6386 tmp
= gen_ld32(addr
, IS_USER(s
));
6388 case 1: /* ldrexd */
6389 tmp
= gen_ld32(addr
, IS_USER(s
));
6390 store_reg(s
, rd
, tmp
);
6391 tcg_gen_addi_i32(addr
, addr
, 4);
6392 tmp
= gen_ld32(addr
, IS_USER(s
));
6395 case 2: /* ldrexb */
6396 tmp
= gen_ld8u(addr
, IS_USER(s
));
6398 case 3: /* ldrexh */
6399 tmp
= gen_ld16u(addr
, IS_USER(s
));
6404 store_reg(s
, rd
, tmp
);
6406 int label
= gen_new_label();
6408 tmp2
= tcg_temp_local_new_i32();
6409 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6410 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6411 tmp
= load_reg(s
,rm
);
6414 gen_st32(tmp
, addr
, IS_USER(s
));
6416 case 1: /* strexd */
6417 gen_st32(tmp
, addr
, IS_USER(s
));
6418 tcg_gen_addi_i32(addr
, addr
, 4);
6419 tmp
= load_reg(s
, rm
+ 1);
6420 gen_st32(tmp
, addr
, IS_USER(s
));
6422 case 2: /* strexb */
6423 gen_st8(tmp
, addr
, IS_USER(s
));
6425 case 3: /* strexh */
6426 gen_st16(tmp
, addr
, IS_USER(s
));
6431 gen_set_label(label
);
6432 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6433 tcg_temp_free(tmp2
);
6435 tcg_temp_free(addr
);
6437 /* SWP instruction */
6440 /* ??? This is not really atomic. However we know
6441 we never have multiple CPUs running in parallel,
6442 so it is good enough. */
6443 addr
= load_reg(s
, rn
);
6444 tmp
= load_reg(s
, rm
);
6445 if (insn
& (1 << 22)) {
6446 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6447 gen_st8(tmp
, addr
, IS_USER(s
));
6449 tmp2
= gen_ld32(addr
, IS_USER(s
));
6450 gen_st32(tmp
, addr
, IS_USER(s
));
6453 store_reg(s
, rd
, tmp2
);
6459 /* Misc load/store */
6460 rn
= (insn
>> 16) & 0xf;
6461 rd
= (insn
>> 12) & 0xf;
6462 addr
= load_reg(s
, rn
);
6463 if (insn
& (1 << 24))
6464 gen_add_datah_offset(s
, insn
, 0, addr
);
6466 if (insn
& (1 << 20)) {
6470 tmp
= gen_ld16u(addr
, IS_USER(s
));
6473 tmp
= gen_ld8s(addr
, IS_USER(s
));
6477 tmp
= gen_ld16s(addr
, IS_USER(s
));
6481 } else if (sh
& 2) {
6485 tmp
= load_reg(s
, rd
);
6486 gen_st32(tmp
, addr
, IS_USER(s
));
6487 tcg_gen_addi_i32(addr
, addr
, 4);
6488 tmp
= load_reg(s
, rd
+ 1);
6489 gen_st32(tmp
, addr
, IS_USER(s
));
6493 tmp
= gen_ld32(addr
, IS_USER(s
));
6494 store_reg(s
, rd
, tmp
);
6495 tcg_gen_addi_i32(addr
, addr
, 4);
6496 tmp
= gen_ld32(addr
, IS_USER(s
));
6500 address_offset
= -4;
6503 tmp
= load_reg(s
, rd
);
6504 gen_st16(tmp
, addr
, IS_USER(s
));
6507 /* Perform base writeback before the loaded value to
6508 ensure correct behavior with overlapping index registers.
6509 ldrd with base writeback is is undefined if the
6510 destination and index registers overlap. */
6511 if (!(insn
& (1 << 24))) {
6512 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6513 store_reg(s
, rn
, addr
);
6514 } else if (insn
& (1 << 21)) {
6516 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6517 store_reg(s
, rn
, addr
);
6522 /* Complete the load. */
6523 store_reg(s
, rd
, tmp
);
6532 if (insn
& (1 << 4)) {
6534 /* Armv6 Media instructions. */
6536 rn
= (insn
>> 16) & 0xf;
6537 rd
= (insn
>> 12) & 0xf;
6538 rs
= (insn
>> 8) & 0xf;
6539 switch ((insn
>> 23) & 3) {
6540 case 0: /* Parallel add/subtract. */
6541 op1
= (insn
>> 20) & 7;
6542 tmp
= load_reg(s
, rn
);
6543 tmp2
= load_reg(s
, rm
);
6544 sh
= (insn
>> 5) & 7;
6545 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6547 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6549 store_reg(s
, rd
, tmp
);
6552 if ((insn
& 0x00700020) == 0) {
6553 /* Halfword pack. */
6554 tmp
= load_reg(s
, rn
);
6555 tmp2
= load_reg(s
, rm
);
6556 shift
= (insn
>> 7) & 0x1f;
6557 if (insn
& (1 << 6)) {
6561 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6562 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6563 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6567 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6568 tcg_gen_ext16u_i32(tmp
, tmp
);
6569 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6571 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6573 store_reg(s
, rd
, tmp
);
6574 } else if ((insn
& 0x00200020) == 0x00200000) {
6576 tmp
= load_reg(s
, rm
);
6577 shift
= (insn
>> 7) & 0x1f;
6578 if (insn
& (1 << 6)) {
6581 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6583 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6585 sh
= (insn
>> 16) & 0x1f;
6587 tmp2
= tcg_const_i32(sh
);
6588 if (insn
& (1 << 22))
6589 gen_helper_usat(tmp
, tmp
, tmp2
);
6591 gen_helper_ssat(tmp
, tmp
, tmp2
);
6592 tcg_temp_free_i32(tmp2
);
6594 store_reg(s
, rd
, tmp
);
6595 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6597 tmp
= load_reg(s
, rm
);
6598 sh
= (insn
>> 16) & 0x1f;
6600 tmp2
= tcg_const_i32(sh
);
6601 if (insn
& (1 << 22))
6602 gen_helper_usat16(tmp
, tmp
, tmp2
);
6604 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6605 tcg_temp_free_i32(tmp2
);
6607 store_reg(s
, rd
, tmp
);
6608 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6610 tmp
= load_reg(s
, rn
);
6611 tmp2
= load_reg(s
, rm
);
6613 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6614 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6617 store_reg(s
, rd
, tmp
);
6618 } else if ((insn
& 0x000003e0) == 0x00000060) {
6619 tmp
= load_reg(s
, rm
);
6620 shift
= (insn
>> 10) & 3;
6621 /* ??? In many cases it's not neccessary to do a
6622 rotate, a shift is sufficient. */
6624 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6625 op1
= (insn
>> 20) & 7;
6627 case 0: gen_sxtb16(tmp
); break;
6628 case 2: gen_sxtb(tmp
); break;
6629 case 3: gen_sxth(tmp
); break;
6630 case 4: gen_uxtb16(tmp
); break;
6631 case 6: gen_uxtb(tmp
); break;
6632 case 7: gen_uxth(tmp
); break;
6633 default: goto illegal_op
;
6636 tmp2
= load_reg(s
, rn
);
6637 if ((op1
& 3) == 0) {
6638 gen_add16(tmp
, tmp2
);
6640 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6644 store_reg(s
, rd
, tmp
);
6645 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6647 tmp
= load_reg(s
, rm
);
6648 if (insn
& (1 << 22)) {
6649 if (insn
& (1 << 7)) {
6653 gen_helper_rbit(tmp
, tmp
);
6656 if (insn
& (1 << 7))
6659 tcg_gen_bswap32_i32(tmp
, tmp
);
6661 store_reg(s
, rd
, tmp
);
6666 case 2: /* Multiplies (Type 3). */
6667 tmp
= load_reg(s
, rm
);
6668 tmp2
= load_reg(s
, rs
);
6669 if (insn
& (1 << 20)) {
6670 /* Signed multiply most significant [accumulate]. */
6671 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6672 if (insn
& (1 << 5))
6673 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6674 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6676 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6677 tcg_temp_free_i64(tmp64
);
6679 tmp2
= load_reg(s
, rd
);
6680 if (insn
& (1 << 6)) {
6681 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6683 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6687 store_reg(s
, rn
, tmp
);
6689 if (insn
& (1 << 5))
6690 gen_swap_half(tmp2
);
6691 gen_smul_dual(tmp
, tmp2
);
6692 /* This addition cannot overflow. */
6693 if (insn
& (1 << 6)) {
6694 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6696 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6699 if (insn
& (1 << 22)) {
6700 /* smlald, smlsld */
6701 tmp64
= tcg_temp_new_i64();
6702 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6704 gen_addq(s
, tmp64
, rd
, rn
);
6705 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6706 tcg_temp_free_i64(tmp64
);
6708 /* smuad, smusd, smlad, smlsd */
6711 tmp2
= load_reg(s
, rd
);
6712 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6715 store_reg(s
, rn
, tmp
);
6720 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6722 case 0: /* Unsigned sum of absolute differences. */
6724 tmp
= load_reg(s
, rm
);
6725 tmp2
= load_reg(s
, rs
);
6726 gen_helper_usad8(tmp
, tmp
, tmp2
);
6729 tmp2
= load_reg(s
, rd
);
6730 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6733 store_reg(s
, rn
, tmp
);
6735 case 0x20: case 0x24: case 0x28: case 0x2c:
6736 /* Bitfield insert/clear. */
6738 shift
= (insn
>> 7) & 0x1f;
6739 i
= (insn
>> 16) & 0x1f;
6743 tcg_gen_movi_i32(tmp
, 0);
6745 tmp
= load_reg(s
, rm
);
6748 tmp2
= load_reg(s
, rd
);
6749 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6752 store_reg(s
, rd
, tmp
);
6754 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6755 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6757 tmp
= load_reg(s
, rm
);
6758 shift
= (insn
>> 7) & 0x1f;
6759 i
= ((insn
>> 16) & 0x1f) + 1;
6764 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6766 gen_sbfx(tmp
, shift
, i
);
6769 store_reg(s
, rd
, tmp
);
6779 /* Check for undefined extension instructions
6780 * per the ARM Bible IE:
6781 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6783 sh
= (0xf << 20) | (0xf << 4);
6784 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6788 /* load/store byte/word */
6789 rn
= (insn
>> 16) & 0xf;
6790 rd
= (insn
>> 12) & 0xf;
6791 tmp2
= load_reg(s
, rn
);
6792 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6793 if (insn
& (1 << 24))
6794 gen_add_data_offset(s
, insn
, tmp2
);
6795 if (insn
& (1 << 20)) {
6797 if (insn
& (1 << 22)) {
6798 tmp
= gen_ld8u(tmp2
, i
);
6800 tmp
= gen_ld32(tmp2
, i
);
6804 tmp
= load_reg(s
, rd
);
6805 if (insn
& (1 << 22))
6806 gen_st8(tmp
, tmp2
, i
);
6808 gen_st32(tmp
, tmp2
, i
);
6810 if (!(insn
& (1 << 24))) {
6811 gen_add_data_offset(s
, insn
, tmp2
);
6812 store_reg(s
, rn
, tmp2
);
6813 } else if (insn
& (1 << 21)) {
6814 store_reg(s
, rn
, tmp2
);
6818 if (insn
& (1 << 20)) {
6819 /* Complete the load. */
6823 store_reg(s
, rd
, tmp
);
6829 int j
, n
, user
, loaded_base
;
6831 /* load/store multiple words */
6832 /* XXX: store correct base if write back */
6834 if (insn
& (1 << 22)) {
6836 goto illegal_op
; /* only usable in supervisor mode */
6838 if ((insn
& (1 << 15)) == 0)
6841 rn
= (insn
>> 16) & 0xf;
6842 addr
= load_reg(s
, rn
);
6844 /* compute total size */
6846 TCGV_UNUSED(loaded_var
);
6849 if (insn
& (1 << i
))
6852 /* XXX: test invalid n == 0 case ? */
6853 if (insn
& (1 << 23)) {
6854 if (insn
& (1 << 24)) {
6856 tcg_gen_addi_i32(addr
, addr
, 4);
6858 /* post increment */
6861 if (insn
& (1 << 24)) {
6863 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6865 /* post decrement */
6867 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6872 if (insn
& (1 << i
)) {
6873 if (insn
& (1 << 20)) {
6875 tmp
= gen_ld32(addr
, IS_USER(s
));
6879 tmp2
= tcg_const_i32(i
);
6880 gen_helper_set_user_reg(tmp2
, tmp
);
6881 tcg_temp_free_i32(tmp2
);
6883 } else if (i
== rn
) {
6887 store_reg(s
, i
, tmp
);
6892 /* special case: r15 = PC + 8 */
6893 val
= (long)s
->pc
+ 4;
6895 tcg_gen_movi_i32(tmp
, val
);
6898 tmp2
= tcg_const_i32(i
);
6899 gen_helper_get_user_reg(tmp
, tmp2
);
6900 tcg_temp_free_i32(tmp2
);
6902 tmp
= load_reg(s
, i
);
6904 gen_st32(tmp
, addr
, IS_USER(s
));
6907 /* no need to add after the last transfer */
6909 tcg_gen_addi_i32(addr
, addr
, 4);
6912 if (insn
& (1 << 21)) {
6914 if (insn
& (1 << 23)) {
6915 if (insn
& (1 << 24)) {
6918 /* post increment */
6919 tcg_gen_addi_i32(addr
, addr
, 4);
6922 if (insn
& (1 << 24)) {
6925 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6927 /* post decrement */
6928 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6931 store_reg(s
, rn
, addr
);
6936 store_reg(s
, rn
, loaded_var
);
6938 if ((insn
& (1 << 22)) && !user
) {
6939 /* Restore CPSR from SPSR. */
6940 tmp
= load_cpu_field(spsr
);
6941 gen_set_cpsr(tmp
, 0xffffffff);
6943 s
->is_jmp
= DISAS_UPDATE
;
6952 /* branch (and link) */
6953 val
= (int32_t)s
->pc
;
6954 if (insn
& (1 << 24)) {
6956 tcg_gen_movi_i32(tmp
, val
);
6957 store_reg(s
, 14, tmp
);
6959 offset
= (((int32_t)insn
<< 8) >> 8);
6960 val
+= (offset
<< 2) + 4;
6968 if (disas_coproc_insn(env
, s
, insn
))
6973 gen_set_pc_im(s
->pc
);
6974 s
->is_jmp
= DISAS_SWI
;
6978 gen_set_condexec(s
);
6979 gen_set_pc_im(s
->pc
- 4);
6980 gen_exception(EXCP_UDEF
);
6981 s
->is_jmp
= DISAS_JUMP
;
6987 /* Return true if this is a Thumb-2 logical op. */
6989 thumb2_logic_op(int op
)
6994 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6995 then set condition code flags based on the result of the operation.
6996 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6997 to the high bit of T1.
6998 Returns zero if the opcode is valid. */
7001 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
7008 tcg_gen_and_i32(t0
, t0
, t1
);
7012 tcg_gen_bic_i32(t0
, t0
, t1
);
7016 tcg_gen_or_i32(t0
, t0
, t1
);
7020 tcg_gen_not_i32(t1
, t1
);
7021 tcg_gen_or_i32(t0
, t0
, t1
);
7025 tcg_gen_xor_i32(t0
, t0
, t1
);
7030 gen_helper_add_cc(t0
, t0
, t1
);
7032 tcg_gen_add_i32(t0
, t0
, t1
);
7036 gen_helper_adc_cc(t0
, t0
, t1
);
7042 gen_helper_sbc_cc(t0
, t0
, t1
);
7044 gen_sub_carry(t0
, t0
, t1
);
7048 gen_helper_sub_cc(t0
, t0
, t1
);
7050 tcg_gen_sub_i32(t0
, t0
, t1
);
7054 gen_helper_sub_cc(t0
, t1
, t0
);
7056 tcg_gen_sub_i32(t0
, t1
, t0
);
7058 default: /* 5, 6, 7, 9, 12, 15. */
7064 gen_set_CF_bit31(t1
);
7069 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7071 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7073 uint32_t insn
, imm
, shift
, offset
;
7074 uint32_t rd
, rn
, rm
, rs
;
7085 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7086 || arm_feature (env
, ARM_FEATURE_M
))) {
7087 /* Thumb-1 cores may need to treat bl and blx as a pair of
7088 16-bit instructions to get correct prefetch abort behavior. */
7090 if ((insn
& (1 << 12)) == 0) {
7091 /* Second half of blx. */
7092 offset
= ((insn
& 0x7ff) << 1);
7093 tmp
= load_reg(s
, 14);
7094 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7095 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7098 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7099 store_reg(s
, 14, tmp2
);
7103 if (insn
& (1 << 11)) {
7104 /* Second half of bl. */
7105 offset
= ((insn
& 0x7ff) << 1) | 1;
7106 tmp
= load_reg(s
, 14);
7107 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7110 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7111 store_reg(s
, 14, tmp2
);
7115 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7116 /* Instruction spans a page boundary. Implement it as two
7117 16-bit instructions in case the second half causes an
7119 offset
= ((int32_t)insn
<< 21) >> 9;
7120 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7123 /* Fall through to 32-bit decode. */
7126 insn
= lduw_code(s
->pc
);
7128 insn
|= (uint32_t)insn_hw1
<< 16;
7130 if ((insn
& 0xf800e800) != 0xf000e800) {
7134 rn
= (insn
>> 16) & 0xf;
7135 rs
= (insn
>> 12) & 0xf;
7136 rd
= (insn
>> 8) & 0xf;
7138 switch ((insn
>> 25) & 0xf) {
7139 case 0: case 1: case 2: case 3:
7140 /* 16-bit instructions. Should never happen. */
7143 if (insn
& (1 << 22)) {
7144 /* Other load/store, table branch. */
7145 if (insn
& 0x01200000) {
7146 /* Load/store doubleword. */
7149 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7151 addr
= load_reg(s
, rn
);
7153 offset
= (insn
& 0xff) * 4;
7154 if ((insn
& (1 << 23)) == 0)
7156 if (insn
& (1 << 24)) {
7157 tcg_gen_addi_i32(addr
, addr
, offset
);
7160 if (insn
& (1 << 20)) {
7162 tmp
= gen_ld32(addr
, IS_USER(s
));
7163 store_reg(s
, rs
, tmp
);
7164 tcg_gen_addi_i32(addr
, addr
, 4);
7165 tmp
= gen_ld32(addr
, IS_USER(s
));
7166 store_reg(s
, rd
, tmp
);
7169 tmp
= load_reg(s
, rs
);
7170 gen_st32(tmp
, addr
, IS_USER(s
));
7171 tcg_gen_addi_i32(addr
, addr
, 4);
7172 tmp
= load_reg(s
, rd
);
7173 gen_st32(tmp
, addr
, IS_USER(s
));
7175 if (insn
& (1 << 21)) {
7176 /* Base writeback. */
7179 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7180 store_reg(s
, rn
, addr
);
7184 } else if ((insn
& (1 << 23)) == 0) {
7185 /* Load/store exclusive word. */
7186 addr
= tcg_temp_local_new();
7187 load_reg_var(s
, addr
, rn
);
7188 if (insn
& (1 << 20)) {
7189 gen_helper_mark_exclusive(cpu_env
, addr
);
7190 tmp
= gen_ld32(addr
, IS_USER(s
));
7191 store_reg(s
, rd
, tmp
);
7193 int label
= gen_new_label();
7194 tmp2
= tcg_temp_local_new();
7195 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7196 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7197 tmp
= load_reg(s
, rs
);
7198 gen_st32(tmp
, addr
, IS_USER(s
));
7199 gen_set_label(label
);
7200 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7201 tcg_temp_free(tmp2
);
7203 tcg_temp_free(addr
);
7204 } else if ((insn
& (1 << 6)) == 0) {
7208 tcg_gen_movi_i32(addr
, s
->pc
);
7210 addr
= load_reg(s
, rn
);
7212 tmp
= load_reg(s
, rm
);
7213 tcg_gen_add_i32(addr
, addr
, tmp
);
7214 if (insn
& (1 << 4)) {
7216 tcg_gen_add_i32(addr
, addr
, tmp
);
7218 tmp
= gen_ld16u(addr
, IS_USER(s
));
7221 tmp
= gen_ld8u(addr
, IS_USER(s
));
7224 tcg_gen_shli_i32(tmp
, tmp
, 1);
7225 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7226 store_reg(s
, 15, tmp
);
7228 /* Load/store exclusive byte/halfword/doubleword. */
7229 /* ??? These are not really atomic. However we know
7230 we never have multiple CPUs running in parallel,
7231 so it is good enough. */
7232 op
= (insn
>> 4) & 0x3;
7233 addr
= tcg_temp_local_new();
7234 load_reg_var(s
, addr
, rn
);
7235 if (insn
& (1 << 20)) {
7236 gen_helper_mark_exclusive(cpu_env
, addr
);
7239 tmp
= gen_ld8u(addr
, IS_USER(s
));
7242 tmp
= gen_ld16u(addr
, IS_USER(s
));
7245 tmp
= gen_ld32(addr
, IS_USER(s
));
7246 tcg_gen_addi_i32(addr
, addr
, 4);
7247 tmp2
= gen_ld32(addr
, IS_USER(s
));
7248 store_reg(s
, rd
, tmp2
);
7253 store_reg(s
, rs
, tmp
);
7255 int label
= gen_new_label();
7256 tmp2
= tcg_temp_local_new();
7257 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7258 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7259 tmp
= load_reg(s
, rs
);
7262 gen_st8(tmp
, addr
, IS_USER(s
));
7265 gen_st16(tmp
, addr
, IS_USER(s
));
7268 gen_st32(tmp
, addr
, IS_USER(s
));
7269 tcg_gen_addi_i32(addr
, addr
, 4);
7270 tmp
= load_reg(s
, rd
);
7271 gen_st32(tmp
, addr
, IS_USER(s
));
7276 gen_set_label(label
);
7277 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7278 tcg_temp_free(tmp2
);
7280 tcg_temp_free(addr
);
7283 /* Load/store multiple, RFE, SRS. */
7284 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7285 /* Not available in user mode. */
7288 if (insn
& (1 << 20)) {
7290 addr
= load_reg(s
, rn
);
7291 if ((insn
& (1 << 24)) == 0)
7292 tcg_gen_addi_i32(addr
, addr
, -8);
7293 /* Load PC into tmp and CPSR into tmp2. */
7294 tmp
= gen_ld32(addr
, 0);
7295 tcg_gen_addi_i32(addr
, addr
, 4);
7296 tmp2
= gen_ld32(addr
, 0);
7297 if (insn
& (1 << 21)) {
7298 /* Base writeback. */
7299 if (insn
& (1 << 24)) {
7300 tcg_gen_addi_i32(addr
, addr
, 4);
7302 tcg_gen_addi_i32(addr
, addr
, -4);
7304 store_reg(s
, rn
, addr
);
7308 gen_rfe(s
, tmp
, tmp2
);
7312 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7313 addr
= load_reg(s
, 13);
7316 tmp
= tcg_const_i32(op
);
7317 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
7318 tcg_temp_free_i32(tmp
);
7320 if ((insn
& (1 << 24)) == 0) {
7321 tcg_gen_addi_i32(addr
, addr
, -8);
7323 tmp
= load_reg(s
, 14);
7324 gen_st32(tmp
, addr
, 0);
7325 tcg_gen_addi_i32(addr
, addr
, 4);
7327 gen_helper_cpsr_read(tmp
);
7328 gen_st32(tmp
, addr
, 0);
7329 if (insn
& (1 << 21)) {
7330 if ((insn
& (1 << 24)) == 0) {
7331 tcg_gen_addi_i32(addr
, addr
, -4);
7333 tcg_gen_addi_i32(addr
, addr
, 4);
7335 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7336 store_reg(s
, 13, addr
);
7338 tmp
= tcg_const_i32(op
);
7339 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
7340 tcg_temp_free_i32(tmp
);
7348 /* Load/store multiple. */
7349 addr
= load_reg(s
, rn
);
7351 for (i
= 0; i
< 16; i
++) {
7352 if (insn
& (1 << i
))
7355 if (insn
& (1 << 24)) {
7356 tcg_gen_addi_i32(addr
, addr
, -offset
);
7359 for (i
= 0; i
< 16; i
++) {
7360 if ((insn
& (1 << i
)) == 0)
7362 if (insn
& (1 << 20)) {
7364 tmp
= gen_ld32(addr
, IS_USER(s
));
7368 store_reg(s
, i
, tmp
);
7372 tmp
= load_reg(s
, i
);
7373 gen_st32(tmp
, addr
, IS_USER(s
));
7375 tcg_gen_addi_i32(addr
, addr
, 4);
7377 if (insn
& (1 << 21)) {
7378 /* Base register writeback. */
7379 if (insn
& (1 << 24)) {
7380 tcg_gen_addi_i32(addr
, addr
, -offset
);
7382 /* Fault if writeback register is in register list. */
7383 if (insn
& (1 << rn
))
7385 store_reg(s
, rn
, addr
);
7392 case 5: /* Data processing register constant shift. */
7395 tcg_gen_movi_i32(tmp
, 0);
7397 tmp
= load_reg(s
, rn
);
7399 tmp2
= load_reg(s
, rm
);
7400 op
= (insn
>> 21) & 0xf;
7401 shiftop
= (insn
>> 4) & 3;
7402 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7403 conds
= (insn
& (1 << 20)) != 0;
7404 logic_cc
= (conds
&& thumb2_logic_op(op
));
7405 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7406 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7410 store_reg(s
, rd
, tmp
);
7415 case 13: /* Misc data processing. */
7416 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7417 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7420 case 0: /* Register controlled shift. */
7421 tmp
= load_reg(s
, rn
);
7422 tmp2
= load_reg(s
, rm
);
7423 if ((insn
& 0x70) != 0)
7425 op
= (insn
>> 21) & 3;
7426 logic_cc
= (insn
& (1 << 20)) != 0;
7427 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7430 store_reg_bx(env
, s
, rd
, tmp
);
7432 case 1: /* Sign/zero extend. */
7433 tmp
= load_reg(s
, rm
);
7434 shift
= (insn
>> 4) & 3;
7435 /* ??? In many cases it's not neccessary to do a
7436 rotate, a shift is sufficient. */
7438 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7439 op
= (insn
>> 20) & 7;
7441 case 0: gen_sxth(tmp
); break;
7442 case 1: gen_uxth(tmp
); break;
7443 case 2: gen_sxtb16(tmp
); break;
7444 case 3: gen_uxtb16(tmp
); break;
7445 case 4: gen_sxtb(tmp
); break;
7446 case 5: gen_uxtb(tmp
); break;
7447 default: goto illegal_op
;
7450 tmp2
= load_reg(s
, rn
);
7451 if ((op
>> 1) == 1) {
7452 gen_add16(tmp
, tmp2
);
7454 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7458 store_reg(s
, rd
, tmp
);
7460 case 2: /* SIMD add/subtract. */
7461 op
= (insn
>> 20) & 7;
7462 shift
= (insn
>> 4) & 7;
7463 if ((op
& 3) == 3 || (shift
& 3) == 3)
7465 tmp
= load_reg(s
, rn
);
7466 tmp2
= load_reg(s
, rm
);
7467 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7469 store_reg(s
, rd
, tmp
);
7471 case 3: /* Other data processing. */
7472 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7474 /* Saturating add/subtract. */
7475 tmp
= load_reg(s
, rn
);
7476 tmp2
= load_reg(s
, rm
);
7478 gen_helper_double_saturate(tmp
, tmp
);
7480 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7482 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7485 tmp
= load_reg(s
, rn
);
7487 case 0x0a: /* rbit */
7488 gen_helper_rbit(tmp
, tmp
);
7490 case 0x08: /* rev */
7491 tcg_gen_bswap32_i32(tmp
, tmp
);
7493 case 0x09: /* rev16 */
7496 case 0x0b: /* revsh */
7499 case 0x10: /* sel */
7500 tmp2
= load_reg(s
, rm
);
7502 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7503 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7507 case 0x18: /* clz */
7508 gen_helper_clz(tmp
, tmp
);
7514 store_reg(s
, rd
, tmp
);
7516 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7517 op
= (insn
>> 4) & 0xf;
7518 tmp
= load_reg(s
, rn
);
7519 tmp2
= load_reg(s
, rm
);
7520 switch ((insn
>> 20) & 7) {
7521 case 0: /* 32 x 32 -> 32 */
7522 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7525 tmp2
= load_reg(s
, rs
);
7527 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7529 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7533 case 1: /* 16 x 16 -> 32 */
7534 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7537 tmp2
= load_reg(s
, rs
);
7538 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7542 case 2: /* Dual multiply add. */
7543 case 4: /* Dual multiply subtract. */
7545 gen_swap_half(tmp2
);
7546 gen_smul_dual(tmp
, tmp2
);
7547 /* This addition cannot overflow. */
7548 if (insn
& (1 << 22)) {
7549 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7551 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7556 tmp2
= load_reg(s
, rs
);
7557 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7561 case 3: /* 32 * 16 -> 32msb */
7563 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7566 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7567 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7569 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7570 tcg_temp_free_i64(tmp64
);
7573 tmp2
= load_reg(s
, rs
);
7574 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7578 case 5: case 6: /* 32 * 32 -> 32msb */
7579 gen_imull(tmp
, tmp2
);
7580 if (insn
& (1 << 5)) {
7581 gen_roundqd(tmp
, tmp2
);
7588 tmp2
= load_reg(s
, rs
);
7589 if (insn
& (1 << 21)) {
7590 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7592 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7597 case 7: /* Unsigned sum of absolute differences. */
7598 gen_helper_usad8(tmp
, tmp
, tmp2
);
7601 tmp2
= load_reg(s
, rs
);
7602 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7607 store_reg(s
, rd
, tmp
);
7609 case 6: case 7: /* 64-bit multiply, Divide. */
7610 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7611 tmp
= load_reg(s
, rn
);
7612 tmp2
= load_reg(s
, rm
);
7613 if ((op
& 0x50) == 0x10) {
7615 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7618 gen_helper_udiv(tmp
, tmp
, tmp2
);
7620 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7622 store_reg(s
, rd
, tmp
);
7623 } else if ((op
& 0xe) == 0xc) {
7624 /* Dual multiply accumulate long. */
7626 gen_swap_half(tmp2
);
7627 gen_smul_dual(tmp
, tmp2
);
7629 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7631 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7635 tmp64
= tcg_temp_new_i64();
7636 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7638 gen_addq(s
, tmp64
, rs
, rd
);
7639 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7640 tcg_temp_free_i64(tmp64
);
7643 /* Unsigned 64-bit multiply */
7644 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7648 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7650 tmp64
= tcg_temp_new_i64();
7651 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7654 /* Signed 64-bit multiply */
7655 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7660 gen_addq_lo(s
, tmp64
, rs
);
7661 gen_addq_lo(s
, tmp64
, rd
);
7662 } else if (op
& 0x40) {
7663 /* 64-bit accumulate. */
7664 gen_addq(s
, tmp64
, rs
, rd
);
7666 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7667 tcg_temp_free_i64(tmp64
);
7672 case 6: case 7: case 14: case 15:
7674 if (((insn
>> 24) & 3) == 3) {
7675 /* Translate into the equivalent ARM encoding. */
7676 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7677 if (disas_neon_data_insn(env
, s
, insn
))
7680 if (insn
& (1 << 28))
7682 if (disas_coproc_insn (env
, s
, insn
))
7686 case 8: case 9: case 10: case 11:
7687 if (insn
& (1 << 15)) {
7688 /* Branches, misc control. */
7689 if (insn
& 0x5000) {
7690 /* Unconditional branch. */
7691 /* signextend(hw1[10:0]) -> offset[:12]. */
7692 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7693 /* hw1[10:0] -> offset[11:1]. */
7694 offset
|= (insn
& 0x7ff) << 1;
7695 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7696 offset[24:22] already have the same value because of the
7697 sign extension above. */
7698 offset
^= ((~insn
) & (1 << 13)) << 10;
7699 offset
^= ((~insn
) & (1 << 11)) << 11;
7701 if (insn
& (1 << 14)) {
7702 /* Branch and link. */
7703 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7707 if (insn
& (1 << 12)) {
7712 offset
&= ~(uint32_t)2;
7713 gen_bx_im(s
, offset
);
7715 } else if (((insn
>> 23) & 7) == 7) {
7717 if (insn
& (1 << 13))
7720 if (insn
& (1 << 26)) {
7721 /* Secure monitor call (v6Z) */
7722 goto illegal_op
; /* not implemented. */
7724 op
= (insn
>> 20) & 7;
7726 case 0: /* msr cpsr. */
7728 tmp
= load_reg(s
, rn
);
7729 addr
= tcg_const_i32(insn
& 0xff);
7730 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7731 tcg_temp_free_i32(addr
);
7737 case 1: /* msr spsr. */
7740 tmp
= load_reg(s
, rn
);
7742 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7746 case 2: /* cps, nop-hint. */
7747 if (((insn
>> 8) & 7) == 0) {
7748 gen_nop_hint(s
, insn
& 0xff);
7750 /* Implemented as NOP in user mode. */
7755 if (insn
& (1 << 10)) {
7756 if (insn
& (1 << 7))
7758 if (insn
& (1 << 6))
7760 if (insn
& (1 << 5))
7762 if (insn
& (1 << 9))
7763 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7765 if (insn
& (1 << 8)) {
7767 imm
|= (insn
& 0x1f);
7770 gen_set_psr_im(s
, offset
, 0, imm
);
7773 case 3: /* Special control operations. */
7774 op
= (insn
>> 4) & 0xf;
7777 gen_helper_clrex(cpu_env
);
7782 /* These execute as NOPs. */
7790 /* Trivial implementation equivalent to bx. */
7791 tmp
= load_reg(s
, rn
);
7794 case 5: /* Exception return. */
7795 /* Unpredictable in user mode. */
7797 case 6: /* mrs cpsr. */
7800 addr
= tcg_const_i32(insn
& 0xff);
7801 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7802 tcg_temp_free_i32(addr
);
7804 gen_helper_cpsr_read(tmp
);
7806 store_reg(s
, rd
, tmp
);
7808 case 7: /* mrs spsr. */
7809 /* Not accessible in user mode. */
7810 if (IS_USER(s
) || IS_M(env
))
7812 tmp
= load_cpu_field(spsr
);
7813 store_reg(s
, rd
, tmp
);
7818 /* Conditional branch. */
7819 op
= (insn
>> 22) & 0xf;
7820 /* Generate a conditional jump to next instruction. */
7821 s
->condlabel
= gen_new_label();
7822 gen_test_cc(op
^ 1, s
->condlabel
);
7825 /* offset[11:1] = insn[10:0] */
7826 offset
= (insn
& 0x7ff) << 1;
7827 /* offset[17:12] = insn[21:16]. */
7828 offset
|= (insn
& 0x003f0000) >> 4;
7829 /* offset[31:20] = insn[26]. */
7830 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7831 /* offset[18] = insn[13]. */
7832 offset
|= (insn
& (1 << 13)) << 5;
7833 /* offset[19] = insn[11]. */
7834 offset
|= (insn
& (1 << 11)) << 8;
7836 /* jump to the offset */
7837 gen_jmp(s
, s
->pc
+ offset
);
7840 /* Data processing immediate. */
7841 if (insn
& (1 << 25)) {
7842 if (insn
& (1 << 24)) {
7843 if (insn
& (1 << 20))
7845 /* Bitfield/Saturate. */
7846 op
= (insn
>> 21) & 7;
7848 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7851 tcg_gen_movi_i32(tmp
, 0);
7853 tmp
= load_reg(s
, rn
);
7856 case 2: /* Signed bitfield extract. */
7858 if (shift
+ imm
> 32)
7861 gen_sbfx(tmp
, shift
, imm
);
7863 case 6: /* Unsigned bitfield extract. */
7865 if (shift
+ imm
> 32)
7868 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7870 case 3: /* Bitfield insert/clear. */
7873 imm
= imm
+ 1 - shift
;
7875 tmp2
= load_reg(s
, rd
);
7876 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7882 default: /* Saturate. */
7885 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7887 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7889 tmp2
= tcg_const_i32(imm
);
7892 if ((op
& 1) && shift
== 0)
7893 gen_helper_usat16(tmp
, tmp
, tmp2
);
7895 gen_helper_usat(tmp
, tmp
, tmp2
);
7898 if ((op
& 1) && shift
== 0)
7899 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7901 gen_helper_ssat(tmp
, tmp
, tmp2
);
7903 tcg_temp_free_i32(tmp2
);
7906 store_reg(s
, rd
, tmp
);
7908 imm
= ((insn
& 0x04000000) >> 15)
7909 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7910 if (insn
& (1 << 22)) {
7911 /* 16-bit immediate. */
7912 imm
|= (insn
>> 4) & 0xf000;
7913 if (insn
& (1 << 23)) {
7915 tmp
= load_reg(s
, rd
);
7916 tcg_gen_ext16u_i32(tmp
, tmp
);
7917 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7921 tcg_gen_movi_i32(tmp
, imm
);
7924 /* Add/sub 12-bit immediate. */
7926 offset
= s
->pc
& ~(uint32_t)3;
7927 if (insn
& (1 << 23))
7932 tcg_gen_movi_i32(tmp
, offset
);
7934 tmp
= load_reg(s
, rn
);
7935 if (insn
& (1 << 23))
7936 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7938 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7941 store_reg(s
, rd
, tmp
);
7944 int shifter_out
= 0;
7945 /* modified 12-bit immediate. */
7946 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7947 imm
= (insn
& 0xff);
7950 /* Nothing to do. */
7952 case 1: /* 00XY00XY */
7955 case 2: /* XY00XY00 */
7959 case 3: /* XYXYXYXY */
7963 default: /* Rotated constant. */
7964 shift
= (shift
<< 1) | (imm
>> 7);
7966 imm
= imm
<< (32 - shift
);
7971 tcg_gen_movi_i32(tmp2
, imm
);
7972 rn
= (insn
>> 16) & 0xf;
7975 tcg_gen_movi_i32(tmp
, 0);
7977 tmp
= load_reg(s
, rn
);
7979 op
= (insn
>> 21) & 0xf;
7980 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7981 shifter_out
, tmp
, tmp2
))
7984 rd
= (insn
>> 8) & 0xf;
7986 store_reg(s
, rd
, tmp
);
7993 case 12: /* Load/store single data item. */
7998 if ((insn
& 0x01100000) == 0x01000000) {
7999 if (disas_neon_ls_insn(env
, s
, insn
))
8007 /* s->pc has already been incremented by 4. */
8008 imm
= s
->pc
& 0xfffffffc;
8009 if (insn
& (1 << 23))
8010 imm
+= insn
& 0xfff;
8012 imm
-= insn
& 0xfff;
8013 tcg_gen_movi_i32(addr
, imm
);
8015 addr
= load_reg(s
, rn
);
8016 if (insn
& (1 << 23)) {
8017 /* Positive offset. */
8019 tcg_gen_addi_i32(addr
, addr
, imm
);
8021 op
= (insn
>> 8) & 7;
8024 case 0: case 8: /* Shifted Register. */
8025 shift
= (insn
>> 4) & 0xf;
8028 tmp
= load_reg(s
, rm
);
8030 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8031 tcg_gen_add_i32(addr
, addr
, tmp
);
8034 case 4: /* Negative offset. */
8035 tcg_gen_addi_i32(addr
, addr
, -imm
);
8037 case 6: /* User privilege. */
8038 tcg_gen_addi_i32(addr
, addr
, imm
);
8041 case 1: /* Post-decrement. */
8044 case 3: /* Post-increment. */
8048 case 5: /* Pre-decrement. */
8051 case 7: /* Pre-increment. */
8052 tcg_gen_addi_i32(addr
, addr
, imm
);
8060 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8061 if (insn
& (1 << 20)) {
8063 if (rs
== 15 && op
!= 2) {
8066 /* Memory hint. Implemented as NOP. */
8069 case 0: tmp
= gen_ld8u(addr
, user
); break;
8070 case 4: tmp
= gen_ld8s(addr
, user
); break;
8071 case 1: tmp
= gen_ld16u(addr
, user
); break;
8072 case 5: tmp
= gen_ld16s(addr
, user
); break;
8073 case 2: tmp
= gen_ld32(addr
, user
); break;
8074 default: goto illegal_op
;
8079 store_reg(s
, rs
, tmp
);
8086 tmp
= load_reg(s
, rs
);
8088 case 0: gen_st8(tmp
, addr
, user
); break;
8089 case 1: gen_st16(tmp
, addr
, user
); break;
8090 case 2: gen_st32(tmp
, addr
, user
); break;
8091 default: goto illegal_op
;
8095 tcg_gen_addi_i32(addr
, addr
, imm
);
8097 store_reg(s
, rn
, addr
);
8111 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8113 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8120 if (s
->condexec_mask
) {
8121 cond
= s
->condexec_cond
;
8122 s
->condlabel
= gen_new_label();
8123 gen_test_cc(cond
^ 1, s
->condlabel
);
8127 insn
= lduw_code(s
->pc
);
8130 switch (insn
>> 12) {
8134 op
= (insn
>> 11) & 3;
8137 rn
= (insn
>> 3) & 7;
8138 tmp
= load_reg(s
, rn
);
8139 if (insn
& (1 << 10)) {
8142 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8145 rm
= (insn
>> 6) & 7;
8146 tmp2
= load_reg(s
, rm
);
8148 if (insn
& (1 << 9)) {
8149 if (s
->condexec_mask
)
8150 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8152 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8154 if (s
->condexec_mask
)
8155 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8157 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8160 store_reg(s
, rd
, tmp
);
8162 /* shift immediate */
8163 rm
= (insn
>> 3) & 7;
8164 shift
= (insn
>> 6) & 0x1f;
8165 tmp
= load_reg(s
, rm
);
8166 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8167 if (!s
->condexec_mask
)
8169 store_reg(s
, rd
, tmp
);
8173 /* arithmetic large immediate */
8174 op
= (insn
>> 11) & 3;
8175 rd
= (insn
>> 8) & 0x7;
8176 if (op
== 0) { /* mov */
8178 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8179 if (!s
->condexec_mask
)
8181 store_reg(s
, rd
, tmp
);
8183 tmp
= load_reg(s
, rd
);
8185 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8188 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8193 if (s
->condexec_mask
)
8194 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8196 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8198 store_reg(s
, rd
, tmp
);
8201 if (s
->condexec_mask
)
8202 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8204 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8206 store_reg(s
, rd
, tmp
);
8212 if (insn
& (1 << 11)) {
8213 rd
= (insn
>> 8) & 7;
8214 /* load pc-relative. Bit 1 of PC is ignored. */
8215 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8216 val
&= ~(uint32_t)2;
8218 tcg_gen_movi_i32(addr
, val
);
8219 tmp
= gen_ld32(addr
, IS_USER(s
));
8221 store_reg(s
, rd
, tmp
);
8224 if (insn
& (1 << 10)) {
8225 /* data processing extended or blx */
8226 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8227 rm
= (insn
>> 3) & 0xf;
8228 op
= (insn
>> 8) & 3;
8231 tmp
= load_reg(s
, rd
);
8232 tmp2
= load_reg(s
, rm
);
8233 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8235 store_reg(s
, rd
, tmp
);
8238 tmp
= load_reg(s
, rd
);
8239 tmp2
= load_reg(s
, rm
);
8240 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8244 case 2: /* mov/cpy */
8245 tmp
= load_reg(s
, rm
);
8246 store_reg(s
, rd
, tmp
);
8248 case 3:/* branch [and link] exchange thumb register */
8249 tmp
= load_reg(s
, rm
);
8250 if (insn
& (1 << 7)) {
8251 val
= (uint32_t)s
->pc
| 1;
8253 tcg_gen_movi_i32(tmp2
, val
);
8254 store_reg(s
, 14, tmp2
);
8262 /* data processing register */
8264 rm
= (insn
>> 3) & 7;
8265 op
= (insn
>> 6) & 0xf;
8266 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8267 /* the shift/rotate ops want the operands backwards */
8276 if (op
== 9) { /* neg */
8278 tcg_gen_movi_i32(tmp
, 0);
8279 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8280 tmp
= load_reg(s
, rd
);
8285 tmp2
= load_reg(s
, rm
);
8288 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8289 if (!s
->condexec_mask
)
8293 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8294 if (!s
->condexec_mask
)
8298 if (s
->condexec_mask
) {
8299 gen_helper_shl(tmp2
, tmp2
, tmp
);
8301 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8306 if (s
->condexec_mask
) {
8307 gen_helper_shr(tmp2
, tmp2
, tmp
);
8309 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8314 if (s
->condexec_mask
) {
8315 gen_helper_sar(tmp2
, tmp2
, tmp
);
8317 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8322 if (s
->condexec_mask
)
8325 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8328 if (s
->condexec_mask
)
8329 gen_sub_carry(tmp
, tmp
, tmp2
);
8331 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8334 if (s
->condexec_mask
) {
8335 gen_helper_ror(tmp2
, tmp2
, tmp
);
8337 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8342 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8347 if (s
->condexec_mask
)
8348 tcg_gen_neg_i32(tmp
, tmp2
);
8350 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8353 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8357 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8361 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8362 if (!s
->condexec_mask
)
8366 gen_mull(tmp
, tmp2
);
8367 if (!s
->condexec_mask
)
8371 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8372 if (!s
->condexec_mask
)
8376 tcg_gen_not_i32(tmp2
, tmp2
);
8377 if (!s
->condexec_mask
)
8385 store_reg(s
, rm
, tmp2
);
8389 store_reg(s
, rd
, tmp
);
8399 /* load/store register offset. */
8401 rn
= (insn
>> 3) & 7;
8402 rm
= (insn
>> 6) & 7;
8403 op
= (insn
>> 9) & 7;
8404 addr
= load_reg(s
, rn
);
8405 tmp
= load_reg(s
, rm
);
8406 tcg_gen_add_i32(addr
, addr
, tmp
);
8409 if (op
< 3) /* store */
8410 tmp
= load_reg(s
, rd
);
8414 gen_st32(tmp
, addr
, IS_USER(s
));
8417 gen_st16(tmp
, addr
, IS_USER(s
));
8420 gen_st8(tmp
, addr
, IS_USER(s
));
8423 tmp
= gen_ld8s(addr
, IS_USER(s
));
8426 tmp
= gen_ld32(addr
, IS_USER(s
));
8429 tmp
= gen_ld16u(addr
, IS_USER(s
));
8432 tmp
= gen_ld8u(addr
, IS_USER(s
));
8435 tmp
= gen_ld16s(addr
, IS_USER(s
));
8438 if (op
>= 3) /* load */
8439 store_reg(s
, rd
, tmp
);
8444 /* load/store word immediate offset */
8446 rn
= (insn
>> 3) & 7;
8447 addr
= load_reg(s
, rn
);
8448 val
= (insn
>> 4) & 0x7c;
8449 tcg_gen_addi_i32(addr
, addr
, val
);
8451 if (insn
& (1 << 11)) {
8453 tmp
= gen_ld32(addr
, IS_USER(s
));
8454 store_reg(s
, rd
, tmp
);
8457 tmp
= load_reg(s
, rd
);
8458 gen_st32(tmp
, addr
, IS_USER(s
));
8464 /* load/store byte immediate offset */
8466 rn
= (insn
>> 3) & 7;
8467 addr
= load_reg(s
, rn
);
8468 val
= (insn
>> 6) & 0x1f;
8469 tcg_gen_addi_i32(addr
, addr
, val
);
8471 if (insn
& (1 << 11)) {
8473 tmp
= gen_ld8u(addr
, IS_USER(s
));
8474 store_reg(s
, rd
, tmp
);
8477 tmp
= load_reg(s
, rd
);
8478 gen_st8(tmp
, addr
, IS_USER(s
));
8484 /* load/store halfword immediate offset */
8486 rn
= (insn
>> 3) & 7;
8487 addr
= load_reg(s
, rn
);
8488 val
= (insn
>> 5) & 0x3e;
8489 tcg_gen_addi_i32(addr
, addr
, val
);
8491 if (insn
& (1 << 11)) {
8493 tmp
= gen_ld16u(addr
, IS_USER(s
));
8494 store_reg(s
, rd
, tmp
);
8497 tmp
= load_reg(s
, rd
);
8498 gen_st16(tmp
, addr
, IS_USER(s
));
8504 /* load/store from stack */
8505 rd
= (insn
>> 8) & 7;
8506 addr
= load_reg(s
, 13);
8507 val
= (insn
& 0xff) * 4;
8508 tcg_gen_addi_i32(addr
, addr
, val
);
8510 if (insn
& (1 << 11)) {
8512 tmp
= gen_ld32(addr
, IS_USER(s
));
8513 store_reg(s
, rd
, tmp
);
8516 tmp
= load_reg(s
, rd
);
8517 gen_st32(tmp
, addr
, IS_USER(s
));
8523 /* add to high reg */
8524 rd
= (insn
>> 8) & 7;
8525 if (insn
& (1 << 11)) {
8527 tmp
= load_reg(s
, 13);
8529 /* PC. bit 1 is ignored. */
8531 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8533 val
= (insn
& 0xff) * 4;
8534 tcg_gen_addi_i32(tmp
, tmp
, val
);
8535 store_reg(s
, rd
, tmp
);
8540 op
= (insn
>> 8) & 0xf;
8543 /* adjust stack pointer */
8544 tmp
= load_reg(s
, 13);
8545 val
= (insn
& 0x7f) * 4;
8546 if (insn
& (1 << 7))
8547 val
= -(int32_t)val
;
8548 tcg_gen_addi_i32(tmp
, tmp
, val
);
8549 store_reg(s
, 13, tmp
);
8552 case 2: /* sign/zero extend. */
8555 rm
= (insn
>> 3) & 7;
8556 tmp
= load_reg(s
, rm
);
8557 switch ((insn
>> 6) & 3) {
8558 case 0: gen_sxth(tmp
); break;
8559 case 1: gen_sxtb(tmp
); break;
8560 case 2: gen_uxth(tmp
); break;
8561 case 3: gen_uxtb(tmp
); break;
8563 store_reg(s
, rd
, tmp
);
8565 case 4: case 5: case 0xc: case 0xd:
8567 addr
= load_reg(s
, 13);
8568 if (insn
& (1 << 8))
8572 for (i
= 0; i
< 8; i
++) {
8573 if (insn
& (1 << i
))
8576 if ((insn
& (1 << 11)) == 0) {
8577 tcg_gen_addi_i32(addr
, addr
, -offset
);
8579 for (i
= 0; i
< 8; i
++) {
8580 if (insn
& (1 << i
)) {
8581 if (insn
& (1 << 11)) {
8583 tmp
= gen_ld32(addr
, IS_USER(s
));
8584 store_reg(s
, i
, tmp
);
8587 tmp
= load_reg(s
, i
);
8588 gen_st32(tmp
, addr
, IS_USER(s
));
8590 /* advance to the next address. */
8591 tcg_gen_addi_i32(addr
, addr
, 4);
8595 if (insn
& (1 << 8)) {
8596 if (insn
& (1 << 11)) {
8598 tmp
= gen_ld32(addr
, IS_USER(s
));
8599 /* don't set the pc until the rest of the instruction
8603 tmp
= load_reg(s
, 14);
8604 gen_st32(tmp
, addr
, IS_USER(s
));
8606 tcg_gen_addi_i32(addr
, addr
, 4);
8608 if ((insn
& (1 << 11)) == 0) {
8609 tcg_gen_addi_i32(addr
, addr
, -offset
);
8611 /* write back the new stack pointer */
8612 store_reg(s
, 13, addr
);
8613 /* set the new PC value */
8614 if ((insn
& 0x0900) == 0x0900)
8618 case 1: case 3: case 9: case 11: /* czb */
8620 tmp
= load_reg(s
, rm
);
8621 s
->condlabel
= gen_new_label();
8623 if (insn
& (1 << 11))
8624 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8626 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8628 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8629 val
= (uint32_t)s
->pc
+ 2;
8634 case 15: /* IT, nop-hint. */
8635 if ((insn
& 0xf) == 0) {
8636 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8640 s
->condexec_cond
= (insn
>> 4) & 0xe;
8641 s
->condexec_mask
= insn
& 0x1f;
8642 /* No actual code generated for this insn, just setup state. */
8645 case 0xe: /* bkpt */
8646 gen_set_condexec(s
);
8647 gen_set_pc_im(s
->pc
- 2);
8648 gen_exception(EXCP_BKPT
);
8649 s
->is_jmp
= DISAS_JUMP
;
8654 rn
= (insn
>> 3) & 0x7;
8656 tmp
= load_reg(s
, rn
);
8657 switch ((insn
>> 6) & 3) {
8658 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8659 case 1: gen_rev16(tmp
); break;
8660 case 3: gen_revsh(tmp
); break;
8661 default: goto illegal_op
;
8663 store_reg(s
, rd
, tmp
);
8671 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8674 addr
= tcg_const_i32(16);
8675 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8676 tcg_temp_free_i32(addr
);
8680 addr
= tcg_const_i32(17);
8681 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8682 tcg_temp_free_i32(addr
);
8684 tcg_temp_free_i32(tmp
);
8687 if (insn
& (1 << 4))
8688 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8691 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8701 /* load/store multiple */
8702 rn
= (insn
>> 8) & 0x7;
8703 addr
= load_reg(s
, rn
);
8704 for (i
= 0; i
< 8; i
++) {
8705 if (insn
& (1 << i
)) {
8706 if (insn
& (1 << 11)) {
8708 tmp
= gen_ld32(addr
, IS_USER(s
));
8709 store_reg(s
, i
, tmp
);
8712 tmp
= load_reg(s
, i
);
8713 gen_st32(tmp
, addr
, IS_USER(s
));
8715 /* advance to the next address */
8716 tcg_gen_addi_i32(addr
, addr
, 4);
8719 /* Base register writeback. */
8720 if ((insn
& (1 << rn
)) == 0) {
8721 store_reg(s
, rn
, addr
);
8728 /* conditional branch or swi */
8729 cond
= (insn
>> 8) & 0xf;
8735 gen_set_condexec(s
);
8736 gen_set_pc_im(s
->pc
);
8737 s
->is_jmp
= DISAS_SWI
;
8740 /* generate a conditional jump to next instruction */
8741 s
->condlabel
= gen_new_label();
8742 gen_test_cc(cond
^ 1, s
->condlabel
);
8745 /* jump to the offset */
8746 val
= (uint32_t)s
->pc
+ 2;
8747 offset
= ((int32_t)insn
<< 24) >> 24;
8753 if (insn
& (1 << 11)) {
8754 if (disas_thumb2_insn(env
, s
, insn
))
8758 /* unconditional branch */
8759 val
= (uint32_t)s
->pc
;
8760 offset
= ((int32_t)insn
<< 21) >> 21;
8761 val
+= (offset
<< 1) + 2;
8766 if (disas_thumb2_insn(env
, s
, insn
))
8772 gen_set_condexec(s
);
8773 gen_set_pc_im(s
->pc
- 4);
8774 gen_exception(EXCP_UDEF
);
8775 s
->is_jmp
= DISAS_JUMP
;
8779 gen_set_condexec(s
);
8780 gen_set_pc_im(s
->pc
- 2);
8781 gen_exception(EXCP_UDEF
);
8782 s
->is_jmp
= DISAS_JUMP
;
8785 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8786 basic block 'tb'. If search_pc is TRUE, also generate PC
8787 information for each intermediate instruction. */
8788 static inline void gen_intermediate_code_internal(CPUState
*env
,
8789 TranslationBlock
*tb
,
8792 DisasContext dc1
, *dc
= &dc1
;
8794 uint16_t *gen_opc_end
;
8796 target_ulong pc_start
;
8797 uint32_t next_page_start
;
8801 /* generate intermediate code */
8808 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8810 dc
->is_jmp
= DISAS_NEXT
;
8812 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8814 dc
->thumb
= env
->thumb
;
8815 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8816 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8817 #if !defined(CONFIG_USER_ONLY)
8819 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8821 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8824 cpu_F0s
= tcg_temp_new_i32();
8825 cpu_F1s
= tcg_temp_new_i32();
8826 cpu_F0d
= tcg_temp_new_i64();
8827 cpu_F1d
= tcg_temp_new_i64();
8830 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8831 cpu_M0
= tcg_temp_new_i64();
8832 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8835 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8837 max_insns
= CF_COUNT_MASK
;
8840 /* Reset the conditional execution bits immediately. This avoids
8841 complications trying to do it at the end of the block. */
8842 if (env
->condexec_bits
)
8844 TCGv tmp
= new_tmp();
8845 tcg_gen_movi_i32(tmp
, 0);
8846 store_cpu_field(tmp
, condexec_bits
);
8849 #ifdef CONFIG_USER_ONLY
8850 /* Intercept jump to the magic kernel page. */
8851 if (dc
->pc
>= 0xffff0000) {
8852 /* We always get here via a jump, so know we are not in a
8853 conditional execution block. */
8854 gen_exception(EXCP_KERNEL_TRAP
);
8855 dc
->is_jmp
= DISAS_UPDATE
;
8859 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8860 /* We always get here via a jump, so know we are not in a
8861 conditional execution block. */
8862 gen_exception(EXCP_EXCEPTION_EXIT
);
8863 dc
->is_jmp
= DISAS_UPDATE
;
8868 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8869 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8870 if (bp
->pc
== dc
->pc
) {
8871 gen_set_condexec(dc
);
8872 gen_set_pc_im(dc
->pc
);
8873 gen_exception(EXCP_DEBUG
);
8874 dc
->is_jmp
= DISAS_JUMP
;
8875 /* Advance PC so that clearing the breakpoint will
8876 invalidate this TB. */
8878 goto done_generating
;
8884 j
= gen_opc_ptr
- gen_opc_buf
;
8888 gen_opc_instr_start
[lj
++] = 0;
8890 gen_opc_pc
[lj
] = dc
->pc
;
8891 gen_opc_instr_start
[lj
] = 1;
8892 gen_opc_icount
[lj
] = num_insns
;
8895 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8899 disas_thumb_insn(env
, dc
);
8900 if (dc
->condexec_mask
) {
8901 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8902 | ((dc
->condexec_mask
>> 4) & 1);
8903 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8904 if (dc
->condexec_mask
== 0) {
8905 dc
->condexec_cond
= 0;
8909 disas_arm_insn(env
, dc
);
8912 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8916 if (dc
->condjmp
&& !dc
->is_jmp
) {
8917 gen_set_label(dc
->condlabel
);
8920 /* Translation stops when a conditional branch is encountered.
8921 * Otherwise the subsequent code could get translated several times.
8922 * Also stop translation when a page boundary is reached. This
8923 * ensures prefetch aborts occur at the right place. */
8925 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8926 !env
->singlestep_enabled
&&
8928 dc
->pc
< next_page_start
&&
8929 num_insns
< max_insns
);
8931 if (tb
->cflags
& CF_LAST_IO
) {
8933 /* FIXME: This can theoretically happen with self-modifying
8935 cpu_abort(env
, "IO on conditional branch instruction");
8940 /* At this stage dc->condjmp will only be set when the skipped
8941 instruction was a conditional branch or trap, and the PC has
8942 already been written. */
8943 if (unlikely(env
->singlestep_enabled
)) {
8944 /* Make sure the pc is updated, and raise a debug exception. */
8946 gen_set_condexec(dc
);
8947 if (dc
->is_jmp
== DISAS_SWI
) {
8948 gen_exception(EXCP_SWI
);
8950 gen_exception(EXCP_DEBUG
);
8952 gen_set_label(dc
->condlabel
);
8954 if (dc
->condjmp
|| !dc
->is_jmp
) {
8955 gen_set_pc_im(dc
->pc
);
8958 gen_set_condexec(dc
);
8959 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8960 gen_exception(EXCP_SWI
);
8962 /* FIXME: Single stepping a WFI insn will not halt
8964 gen_exception(EXCP_DEBUG
);
8967 /* While branches must always occur at the end of an IT block,
8968 there are a few other things that can cause us to terminate
8969 the TB in the middel of an IT block:
8970 - Exception generating instructions (bkpt, swi, undefined).
8972 - Hardware watchpoints.
8973 Hardware breakpoints have already been handled and skip this code.
8975 gen_set_condexec(dc
);
8976 switch(dc
->is_jmp
) {
8978 gen_goto_tb(dc
, 1, dc
->pc
);
8983 /* indicate that the hash table must be used to find the next TB */
8987 /* nothing more to generate */
8993 gen_exception(EXCP_SWI
);
8997 gen_set_label(dc
->condlabel
);
8998 gen_set_condexec(dc
);
8999 gen_goto_tb(dc
, 1, dc
->pc
);
9005 gen_icount_end(tb
, num_insns
);
9006 *gen_opc_ptr
= INDEX_op_end
;
9009 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
9010 qemu_log("----------------\n");
9011 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
9012 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
9017 j
= gen_opc_ptr
- gen_opc_buf
;
9020 gen_opc_instr_start
[lj
++] = 0;
9022 tb
->size
= dc
->pc
- pc_start
;
9023 tb
->icount
= num_insns
;
9027 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
9029 gen_intermediate_code_internal(env
, tb
, 0);
9032 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
9034 gen_intermediate_code_internal(env
, tb
, 1);
9037 static const char *cpu_mode_names
[16] = {
9038 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9039 "???", "???", "???", "und", "???", "???", "???", "sys"
9042 void cpu_dump_state(CPUState
*env
, FILE *f
,
9043 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
9053 /* ??? This assumes float64 and double have the same layout.
9054 Oh well, it's only debug dumps. */
9063 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9065 cpu_fprintf(f
, "\n");
9067 cpu_fprintf(f
, " ");
9069 psr
= cpsr_read(env
);
9070 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9072 psr
& (1 << 31) ? 'N' : '-',
9073 psr
& (1 << 30) ? 'Z' : '-',
9074 psr
& (1 << 29) ? 'C' : '-',
9075 psr
& (1 << 28) ? 'V' : '-',
9076 psr
& CPSR_T
? 'T' : 'A',
9077 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9080 for (i
= 0; i
< 16; i
++) {
9081 d
.d
= env
->vfp
.regs
[i
];
9085 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9086 i
* 2, (int)s0
.i
, s0
.s
,
9087 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9088 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9091 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9095 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9096 unsigned long searched_pc
, int pc_pos
, void *puc
)
9098 env
->regs
[15] = gen_opc_pc
[pc_pos
];