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 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
188 /* Set NZCV flags from the high 4 bits of var. */
189 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
191 static void gen_exception(int excp
)
193 TCGv tmp
= new_tmp();
194 tcg_gen_movi_i32(tmp
, excp
);
195 gen_helper_exception(tmp
);
199 static void gen_smul_dual(TCGv a
, TCGv b
)
201 TCGv tmp1
= new_tmp();
202 TCGv tmp2
= new_tmp();
203 tcg_gen_ext16s_i32(tmp1
, a
);
204 tcg_gen_ext16s_i32(tmp2
, b
);
205 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
207 tcg_gen_sari_i32(a
, a
, 16);
208 tcg_gen_sari_i32(b
, b
, 16);
209 tcg_gen_mul_i32(b
, b
, a
);
210 tcg_gen_mov_i32(a
, tmp1
);
214 /* Byteswap each halfword. */
215 static void gen_rev16(TCGv var
)
217 TCGv tmp
= new_tmp();
218 tcg_gen_shri_i32(tmp
, var
, 8);
219 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
220 tcg_gen_shli_i32(var
, var
, 8);
221 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
222 tcg_gen_or_i32(var
, var
, tmp
);
226 /* Byteswap low halfword and sign extend. */
227 static void gen_revsh(TCGv var
)
229 TCGv tmp
= new_tmp();
230 tcg_gen_shri_i32(tmp
, var
, 8);
231 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
232 tcg_gen_shli_i32(var
, var
, 8);
233 tcg_gen_ext8s_i32(var
, var
);
234 tcg_gen_or_i32(var
, var
, tmp
);
238 /* Unsigned bitfield extract. */
239 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
242 tcg_gen_shri_i32(var
, var
, shift
);
243 tcg_gen_andi_i32(var
, var
, mask
);
246 /* Signed bitfield extract. */
247 static void gen_sbfx(TCGv var
, int shift
, int width
)
252 tcg_gen_sari_i32(var
, var
, shift
);
253 if (shift
+ width
< 32) {
254 signbit
= 1u << (width
- 1);
255 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
256 tcg_gen_xori_i32(var
, var
, signbit
);
257 tcg_gen_subi_i32(var
, var
, signbit
);
261 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
262 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
264 tcg_gen_andi_i32(val
, val
, mask
);
265 tcg_gen_shli_i32(val
, val
, shift
);
266 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
267 tcg_gen_or_i32(dest
, base
, val
);
270 /* Round the top 32 bits of a 64-bit value. */
271 static void gen_roundqd(TCGv a
, TCGv b
)
273 tcg_gen_shri_i32(a
, a
, 31);
274 tcg_gen_add_i32(a
, a
, b
);
277 /* FIXME: Most targets have native widening multiplication.
278 It would be good to use that instead of a full wide multiply. */
279 /* 32x32->64 multiply. Marks inputs as dead. */
280 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
282 TCGv_i64 tmp1
= tcg_temp_new_i64();
283 TCGv_i64 tmp2
= tcg_temp_new_i64();
285 tcg_gen_extu_i32_i64(tmp1
, a
);
287 tcg_gen_extu_i32_i64(tmp2
, b
);
289 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
293 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
295 TCGv_i64 tmp1
= tcg_temp_new_i64();
296 TCGv_i64 tmp2
= tcg_temp_new_i64();
298 tcg_gen_ext_i32_i64(tmp1
, a
);
300 tcg_gen_ext_i32_i64(tmp2
, b
);
302 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
306 /* Unsigned 32x32->64 multiply. */
307 static void gen_mull(TCGv a
, TCGv b
)
309 TCGv_i64 tmp1
= tcg_temp_new_i64();
310 TCGv_i64 tmp2
= tcg_temp_new_i64();
312 tcg_gen_extu_i32_i64(tmp1
, a
);
313 tcg_gen_extu_i32_i64(tmp2
, b
);
314 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
315 tcg_gen_trunc_i64_i32(a
, tmp1
);
316 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
317 tcg_gen_trunc_i64_i32(b
, tmp1
);
320 /* Signed 32x32->64 multiply. */
321 static void gen_imull(TCGv a
, TCGv b
)
323 TCGv_i64 tmp1
= tcg_temp_new_i64();
324 TCGv_i64 tmp2
= tcg_temp_new_i64();
326 tcg_gen_ext_i32_i64(tmp1
, a
);
327 tcg_gen_ext_i32_i64(tmp2
, b
);
328 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
329 tcg_gen_trunc_i64_i32(a
, tmp1
);
330 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
331 tcg_gen_trunc_i64_i32(b
, tmp1
);
334 /* Swap low and high halfwords. */
335 static void gen_swap_half(TCGv var
)
337 TCGv tmp
= new_tmp();
338 tcg_gen_shri_i32(tmp
, var
, 16);
339 tcg_gen_shli_i32(var
, var
, 16);
340 tcg_gen_or_i32(var
, var
, tmp
);
344 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
345 tmp = (t0 ^ t1) & 0x8000;
348 t0 = (t0 + t1) ^ tmp;
351 static void gen_add16(TCGv t0
, TCGv t1
)
353 TCGv tmp
= new_tmp();
354 tcg_gen_xor_i32(tmp
, t0
, t1
);
355 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
356 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
357 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
358 tcg_gen_add_i32(t0
, t0
, t1
);
359 tcg_gen_xor_i32(t0
, t0
, tmp
);
364 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
366 /* Set CF to the top bit of var. */
367 static void gen_set_CF_bit31(TCGv var
)
369 TCGv tmp
= new_tmp();
370 tcg_gen_shri_i32(tmp
, var
, 31);
375 /* Set N and Z flags from var. */
376 static inline void gen_logic_CC(TCGv var
)
378 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
379 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
383 static void gen_adc(TCGv t0
, TCGv t1
)
386 tcg_gen_add_i32(t0
, t0
, t1
);
387 tmp
= load_cpu_field(CF
);
388 tcg_gen_add_i32(t0
, t0
, tmp
);
392 /* dest = T0 + T1 + CF. */
393 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
396 tcg_gen_add_i32(dest
, t0
, t1
);
397 tmp
= load_cpu_field(CF
);
398 tcg_gen_add_i32(dest
, dest
, tmp
);
402 /* dest = T0 - T1 + CF - 1. */
403 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
406 tcg_gen_sub_i32(dest
, t0
, t1
);
407 tmp
= load_cpu_field(CF
);
408 tcg_gen_add_i32(dest
, dest
, tmp
);
409 tcg_gen_subi_i32(dest
, dest
, 1);
413 /* T0 &= ~T1. Clobbers T1. */
414 /* FIXME: Implement bic natively. */
415 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
417 TCGv tmp
= new_tmp();
418 tcg_gen_not_i32(tmp
, t1
);
419 tcg_gen_and_i32(dest
, t0
, tmp
);
423 /* FIXME: Implement this natively. */
424 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
426 /* FIXME: Implement this natively. */
427 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
435 tcg_gen_shri_i32(tmp
, t1
, i
);
436 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
437 tcg_gen_or_i32(t0
, t1
, tmp
);
441 static void shifter_out_im(TCGv var
, int shift
)
443 TCGv tmp
= new_tmp();
445 tcg_gen_andi_i32(tmp
, var
, 1);
447 tcg_gen_shri_i32(tmp
, var
, shift
);
449 tcg_gen_andi_i32(tmp
, tmp
, 1);
455 /* Shift by immediate. Includes special handling for shift == 0. */
456 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
462 shifter_out_im(var
, 32 - shift
);
463 tcg_gen_shli_i32(var
, var
, shift
);
469 tcg_gen_shri_i32(var
, var
, 31);
472 tcg_gen_movi_i32(var
, 0);
475 shifter_out_im(var
, shift
- 1);
476 tcg_gen_shri_i32(var
, var
, shift
);
483 shifter_out_im(var
, shift
- 1);
486 tcg_gen_sari_i32(var
, var
, shift
);
488 case 3: /* ROR/RRX */
491 shifter_out_im(var
, shift
- 1);
492 tcg_gen_rori_i32(var
, var
, shift
); break;
494 TCGv tmp
= load_cpu_field(CF
);
496 shifter_out_im(var
, 0);
497 tcg_gen_shri_i32(var
, var
, 1);
498 tcg_gen_shli_i32(tmp
, tmp
, 31);
499 tcg_gen_or_i32(var
, var
, tmp
);
505 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
506 TCGv shift
, int flags
)
510 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
511 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
512 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
513 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
517 case 0: gen_helper_shl(var
, var
, shift
); break;
518 case 1: gen_helper_shr(var
, var
, shift
); break;
519 case 2: gen_helper_sar(var
, var
, shift
); break;
520 case 3: gen_helper_ror(var
, var
, shift
); break;
526 #define PAS_OP(pfx) \
528 case 0: gen_pas_helper(glue(pfx,add16)); break; \
529 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
530 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
531 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
532 case 4: gen_pas_helper(glue(pfx,add8)); break; \
533 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
535 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
540 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
542 tmp
= tcg_temp_new_ptr();
543 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
547 tmp
= tcg_temp_new_ptr();
548 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
551 #undef gen_pas_helper
552 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
565 #undef gen_pas_helper
570 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
571 #define PAS_OP(pfx) \
573 case 0: gen_pas_helper(glue(pfx,add8)); break; \
574 case 1: gen_pas_helper(glue(pfx,add16)); break; \
575 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
576 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
577 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
578 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
580 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
585 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
587 tmp
= tcg_temp_new_ptr();
588 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
592 tmp
= tcg_temp_new_ptr();
593 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
596 #undef gen_pas_helper
597 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
610 #undef gen_pas_helper
615 static void gen_test_cc(int cc
, int label
)
623 tmp
= load_cpu_field(ZF
);
624 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
627 tmp
= load_cpu_field(ZF
);
628 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
631 tmp
= load_cpu_field(CF
);
632 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
635 tmp
= load_cpu_field(CF
);
636 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
639 tmp
= load_cpu_field(NF
);
640 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
643 tmp
= load_cpu_field(NF
);
644 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
647 tmp
= load_cpu_field(VF
);
648 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
651 tmp
= load_cpu_field(VF
);
652 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
654 case 8: /* hi: C && !Z */
655 inv
= gen_new_label();
656 tmp
= load_cpu_field(CF
);
657 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
659 tmp
= load_cpu_field(ZF
);
660 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
663 case 9: /* ls: !C || Z */
664 tmp
= load_cpu_field(CF
);
665 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
667 tmp
= load_cpu_field(ZF
);
668 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
670 case 10: /* ge: N == V -> N ^ V == 0 */
671 tmp
= load_cpu_field(VF
);
672 tmp2
= load_cpu_field(NF
);
673 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
675 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
677 case 11: /* lt: N != V -> N ^ V != 0 */
678 tmp
= load_cpu_field(VF
);
679 tmp2
= load_cpu_field(NF
);
680 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
682 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
684 case 12: /* gt: !Z && N == V */
685 inv
= gen_new_label();
686 tmp
= load_cpu_field(ZF
);
687 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
689 tmp
= load_cpu_field(VF
);
690 tmp2
= load_cpu_field(NF
);
691 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
693 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
696 case 13: /* le: Z || N != V */
697 tmp
= load_cpu_field(ZF
);
698 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
700 tmp
= load_cpu_field(VF
);
701 tmp2
= load_cpu_field(NF
);
702 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
704 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
707 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
713 static const uint8_t table_logic_cc
[16] = {
732 /* Set PC and Thumb state from an immediate address. */
733 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
737 s
->is_jmp
= DISAS_UPDATE
;
738 if (s
->thumb
!= (addr
& 1)) {
740 tcg_gen_movi_i32(tmp
, addr
& 1);
741 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
744 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
747 /* Set PC and Thumb state from var. var is marked as dead. */
748 static inline void gen_bx(DisasContext
*s
, TCGv var
)
750 s
->is_jmp
= DISAS_UPDATE
;
751 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
752 tcg_gen_andi_i32(var
, var
, 1);
753 store_cpu_field(var
, thumb
);
756 /* Variant of store_reg which uses branch&exchange logic when storing
757 to r15 in ARM architecture v7 and above. The source must be a temporary
758 and will be marked as dead. */
759 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
762 if (reg
== 15 && ENABLE_ARCH_7
) {
765 store_reg(s
, reg
, var
);
769 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
771 TCGv tmp
= new_tmp();
772 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
775 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
777 TCGv tmp
= new_tmp();
778 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
781 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
783 TCGv tmp
= new_tmp();
784 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
787 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
789 TCGv tmp
= new_tmp();
790 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
793 static inline TCGv
gen_ld32(TCGv addr
, int index
)
795 TCGv tmp
= new_tmp();
796 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
799 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
801 tcg_gen_qemu_st8(val
, addr
, index
);
804 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
806 tcg_gen_qemu_st16(val
, addr
, index
);
809 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
811 tcg_gen_qemu_st32(val
, addr
, index
);
815 static inline void gen_set_pc_im(uint32_t val
)
817 tcg_gen_movi_i32(cpu_R
[15], val
);
820 /* Force a TB lookup after an instruction that changes the CPU state. */
821 static inline void gen_lookup_tb(DisasContext
*s
)
823 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
824 s
->is_jmp
= DISAS_UPDATE
;
827 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
830 int val
, rm
, shift
, shiftop
;
833 if (!(insn
& (1 << 25))) {
836 if (!(insn
& (1 << 23)))
839 tcg_gen_addi_i32(var
, var
, val
);
843 shift
= (insn
>> 7) & 0x1f;
844 shiftop
= (insn
>> 5) & 3;
845 offset
= load_reg(s
, rm
);
846 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
847 if (!(insn
& (1 << 23)))
848 tcg_gen_sub_i32(var
, var
, offset
);
850 tcg_gen_add_i32(var
, var
, offset
);
855 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
861 if (insn
& (1 << 22)) {
863 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
864 if (!(insn
& (1 << 23)))
868 tcg_gen_addi_i32(var
, var
, val
);
872 tcg_gen_addi_i32(var
, var
, extra
);
874 offset
= load_reg(s
, rm
);
875 if (!(insn
& (1 << 23)))
876 tcg_gen_sub_i32(var
, var
, offset
);
878 tcg_gen_add_i32(var
, var
, offset
);
883 #define VFP_OP2(name) \
884 static inline void gen_vfp_##name(int dp) \
887 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
889 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
899 static inline void gen_vfp_abs(int dp
)
902 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
904 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
907 static inline void gen_vfp_neg(int dp
)
910 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
912 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
915 static inline void gen_vfp_sqrt(int dp
)
918 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
920 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
923 static inline void gen_vfp_cmp(int dp
)
926 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
928 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
931 static inline void gen_vfp_cmpe(int dp
)
934 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
936 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
939 static inline void gen_vfp_F1_ld0(int dp
)
942 tcg_gen_movi_i64(cpu_F1d
, 0);
944 tcg_gen_movi_i32(cpu_F1s
, 0);
947 static inline void gen_vfp_uito(int dp
)
950 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
952 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
955 static inline void gen_vfp_sito(int dp
)
958 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
960 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
963 static inline void gen_vfp_toui(int dp
)
966 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
968 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
971 static inline void gen_vfp_touiz(int dp
)
974 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
976 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
979 static inline void gen_vfp_tosi(int dp
)
982 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
984 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
987 static inline void gen_vfp_tosiz(int dp
)
990 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
992 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
995 #define VFP_GEN_FIX(name) \
996 static inline void gen_vfp_##name(int dp, int shift) \
999 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1001 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1013 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
1016 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1018 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1021 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
1024 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1026 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1030 vfp_reg_offset (int dp
, int reg
)
1033 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1035 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1036 + offsetof(CPU_DoubleU
, l
.upper
);
1038 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1039 + offsetof(CPU_DoubleU
, l
.lower
);
1043 /* Return the offset of a 32-bit piece of a NEON register.
1044 zero is the least significant end of the register. */
1046 neon_reg_offset (int reg
, int n
)
1050 return vfp_reg_offset(0, sreg
);
1053 static TCGv
neon_load_reg(int reg
, int pass
)
1055 TCGv tmp
= new_tmp();
1056 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1060 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1062 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1066 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1068 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1071 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1073 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1076 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1077 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1078 #define tcg_gen_st_f32 tcg_gen_st_i32
1079 #define tcg_gen_st_f64 tcg_gen_st_i64
1081 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1084 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1086 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1089 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1092 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1094 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1097 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1100 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1102 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1105 #define ARM_CP_RW_BIT (1 << 20)
1107 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1109 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1112 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1114 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1117 static inline TCGv
iwmmxt_load_creg(int reg
)
1119 TCGv var
= new_tmp();
1120 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1124 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1126 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1129 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1131 iwmmxt_store_reg(cpu_M0
, rn
);
1134 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1136 iwmmxt_load_reg(cpu_M0
, rn
);
1139 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1141 iwmmxt_load_reg(cpu_V1
, rn
);
1142 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1145 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1147 iwmmxt_load_reg(cpu_V1
, rn
);
1148 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1151 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1153 iwmmxt_load_reg(cpu_V1
, rn
);
1154 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1157 #define IWMMXT_OP(name) \
1158 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1160 iwmmxt_load_reg(cpu_V1, rn); \
1161 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1164 #define IWMMXT_OP_ENV(name) \
1165 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1167 iwmmxt_load_reg(cpu_V1, rn); \
1168 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1171 #define IWMMXT_OP_ENV_SIZE(name) \
1172 IWMMXT_OP_ENV(name##b) \
1173 IWMMXT_OP_ENV(name##w) \
1174 IWMMXT_OP_ENV(name##l)
1176 #define IWMMXT_OP_ENV1(name) \
1177 static inline void gen_op_iwmmxt_##name##_M0(void) \
1179 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1193 IWMMXT_OP_ENV_SIZE(unpackl
)
1194 IWMMXT_OP_ENV_SIZE(unpackh
)
1196 IWMMXT_OP_ENV1(unpacklub
)
1197 IWMMXT_OP_ENV1(unpackluw
)
1198 IWMMXT_OP_ENV1(unpacklul
)
1199 IWMMXT_OP_ENV1(unpackhub
)
1200 IWMMXT_OP_ENV1(unpackhuw
)
1201 IWMMXT_OP_ENV1(unpackhul
)
1202 IWMMXT_OP_ENV1(unpacklsb
)
1203 IWMMXT_OP_ENV1(unpacklsw
)
1204 IWMMXT_OP_ENV1(unpacklsl
)
1205 IWMMXT_OP_ENV1(unpackhsb
)
1206 IWMMXT_OP_ENV1(unpackhsw
)
1207 IWMMXT_OP_ENV1(unpackhsl
)
1209 IWMMXT_OP_ENV_SIZE(cmpeq
)
1210 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1211 IWMMXT_OP_ENV_SIZE(cmpgts
)
1213 IWMMXT_OP_ENV_SIZE(mins
)
1214 IWMMXT_OP_ENV_SIZE(minu
)
1215 IWMMXT_OP_ENV_SIZE(maxs
)
1216 IWMMXT_OP_ENV_SIZE(maxu
)
1218 IWMMXT_OP_ENV_SIZE(subn
)
1219 IWMMXT_OP_ENV_SIZE(addn
)
1220 IWMMXT_OP_ENV_SIZE(subu
)
1221 IWMMXT_OP_ENV_SIZE(addu
)
1222 IWMMXT_OP_ENV_SIZE(subs
)
1223 IWMMXT_OP_ENV_SIZE(adds
)
1225 IWMMXT_OP_ENV(avgb0
)
1226 IWMMXT_OP_ENV(avgb1
)
1227 IWMMXT_OP_ENV(avgw0
)
1228 IWMMXT_OP_ENV(avgw1
)
1232 IWMMXT_OP_ENV(packuw
)
1233 IWMMXT_OP_ENV(packul
)
1234 IWMMXT_OP_ENV(packuq
)
1235 IWMMXT_OP_ENV(packsw
)
1236 IWMMXT_OP_ENV(packsl
)
1237 IWMMXT_OP_ENV(packsq
)
1239 static void gen_op_iwmmxt_set_mup(void)
1242 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1243 tcg_gen_ori_i32(tmp
, tmp
, 2);
1244 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1247 static void gen_op_iwmmxt_set_cup(void)
1250 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1251 tcg_gen_ori_i32(tmp
, tmp
, 1);
1252 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1255 static void gen_op_iwmmxt_setpsr_nz(void)
1257 TCGv tmp
= new_tmp();
1258 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1259 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1262 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1264 iwmmxt_load_reg(cpu_V1
, rn
);
1265 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1266 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1269 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1275 rd
= (insn
>> 16) & 0xf;
1276 tmp
= load_reg(s
, rd
);
1278 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1279 if (insn
& (1 << 24)) {
1281 if (insn
& (1 << 23))
1282 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1284 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1285 tcg_gen_mov_i32(dest
, tmp
);
1286 if (insn
& (1 << 21))
1287 store_reg(s
, rd
, tmp
);
1290 } else if (insn
& (1 << 21)) {
1292 tcg_gen_mov_i32(dest
, tmp
);
1293 if (insn
& (1 << 23))
1294 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1296 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1297 store_reg(s
, rd
, tmp
);
1298 } else if (!(insn
& (1 << 23)))
1303 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1305 int rd
= (insn
>> 0) & 0xf;
1308 if (insn
& (1 << 8)) {
1309 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1312 tmp
= iwmmxt_load_creg(rd
);
1316 iwmmxt_load_reg(cpu_V0
, rd
);
1317 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1319 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1320 tcg_gen_mov_i32(dest
, tmp
);
1325 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1326 (ie. an undefined instruction). */
1327 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1330 int rdhi
, rdlo
, rd0
, rd1
, i
;
1332 TCGv tmp
, tmp2
, tmp3
;
1334 if ((insn
& 0x0e000e00) == 0x0c000000) {
1335 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1337 rdlo
= (insn
>> 12) & 0xf;
1338 rdhi
= (insn
>> 16) & 0xf;
1339 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1340 iwmmxt_load_reg(cpu_V0
, wrd
);
1341 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1342 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1343 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1344 } else { /* TMCRR */
1345 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1346 iwmmxt_store_reg(cpu_V0
, wrd
);
1347 gen_op_iwmmxt_set_mup();
1352 wrd
= (insn
>> 12) & 0xf;
1354 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1358 if (insn
& ARM_CP_RW_BIT
) {
1359 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1361 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1362 iwmmxt_store_creg(wrd
, tmp
);
1365 if (insn
& (1 << 8)) {
1366 if (insn
& (1 << 22)) { /* WLDRD */
1367 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1369 } else { /* WLDRW wRd */
1370 tmp
= gen_ld32(addr
, IS_USER(s
));
1373 if (insn
& (1 << 22)) { /* WLDRH */
1374 tmp
= gen_ld16u(addr
, IS_USER(s
));
1375 } else { /* WLDRB */
1376 tmp
= gen_ld8u(addr
, IS_USER(s
));
1380 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1383 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1386 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1387 tmp
= iwmmxt_load_creg(wrd
);
1388 gen_st32(tmp
, addr
, IS_USER(s
));
1390 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1392 if (insn
& (1 << 8)) {
1393 if (insn
& (1 << 22)) { /* WSTRD */
1395 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1396 } else { /* WSTRW wRd */
1397 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1398 gen_st32(tmp
, addr
, IS_USER(s
));
1401 if (insn
& (1 << 22)) { /* WSTRH */
1402 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1403 gen_st16(tmp
, addr
, IS_USER(s
));
1404 } else { /* WSTRB */
1405 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1406 gen_st8(tmp
, addr
, IS_USER(s
));
1414 if ((insn
& 0x0f000000) != 0x0e000000)
1417 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1418 case 0x000: /* WOR */
1419 wrd
= (insn
>> 12) & 0xf;
1420 rd0
= (insn
>> 0) & 0xf;
1421 rd1
= (insn
>> 16) & 0xf;
1422 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1423 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1424 gen_op_iwmmxt_setpsr_nz();
1425 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1426 gen_op_iwmmxt_set_mup();
1427 gen_op_iwmmxt_set_cup();
1429 case 0x011: /* TMCR */
1432 rd
= (insn
>> 12) & 0xf;
1433 wrd
= (insn
>> 16) & 0xf;
1435 case ARM_IWMMXT_wCID
:
1436 case ARM_IWMMXT_wCASF
:
1438 case ARM_IWMMXT_wCon
:
1439 gen_op_iwmmxt_set_cup();
1441 case ARM_IWMMXT_wCSSF
:
1442 tmp
= iwmmxt_load_creg(wrd
);
1443 tmp2
= load_reg(s
, rd
);
1444 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
1446 iwmmxt_store_creg(wrd
, tmp
);
1448 case ARM_IWMMXT_wCGR0
:
1449 case ARM_IWMMXT_wCGR1
:
1450 case ARM_IWMMXT_wCGR2
:
1451 case ARM_IWMMXT_wCGR3
:
1452 gen_op_iwmmxt_set_cup();
1453 tmp
= load_reg(s
, rd
);
1454 iwmmxt_store_creg(wrd
, tmp
);
1460 case 0x100: /* WXOR */
1461 wrd
= (insn
>> 12) & 0xf;
1462 rd0
= (insn
>> 0) & 0xf;
1463 rd1
= (insn
>> 16) & 0xf;
1464 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1465 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1466 gen_op_iwmmxt_setpsr_nz();
1467 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1468 gen_op_iwmmxt_set_mup();
1469 gen_op_iwmmxt_set_cup();
1471 case 0x111: /* TMRC */
1474 rd
= (insn
>> 12) & 0xf;
1475 wrd
= (insn
>> 16) & 0xf;
1476 tmp
= iwmmxt_load_creg(wrd
);
1477 store_reg(s
, rd
, tmp
);
1479 case 0x300: /* WANDN */
1480 wrd
= (insn
>> 12) & 0xf;
1481 rd0
= (insn
>> 0) & 0xf;
1482 rd1
= (insn
>> 16) & 0xf;
1483 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1484 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1485 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1486 gen_op_iwmmxt_setpsr_nz();
1487 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1488 gen_op_iwmmxt_set_mup();
1489 gen_op_iwmmxt_set_cup();
1491 case 0x200: /* WAND */
1492 wrd
= (insn
>> 12) & 0xf;
1493 rd0
= (insn
>> 0) & 0xf;
1494 rd1
= (insn
>> 16) & 0xf;
1495 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1496 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1497 gen_op_iwmmxt_setpsr_nz();
1498 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1499 gen_op_iwmmxt_set_mup();
1500 gen_op_iwmmxt_set_cup();
1502 case 0x810: case 0xa10: /* WMADD */
1503 wrd
= (insn
>> 12) & 0xf;
1504 rd0
= (insn
>> 0) & 0xf;
1505 rd1
= (insn
>> 16) & 0xf;
1506 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1507 if (insn
& (1 << 21))
1508 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1510 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1511 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1512 gen_op_iwmmxt_set_mup();
1514 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1515 wrd
= (insn
>> 12) & 0xf;
1516 rd0
= (insn
>> 16) & 0xf;
1517 rd1
= (insn
>> 0) & 0xf;
1518 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1519 switch ((insn
>> 22) & 3) {
1521 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1524 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1527 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1532 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1533 gen_op_iwmmxt_set_mup();
1534 gen_op_iwmmxt_set_cup();
1536 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1537 wrd
= (insn
>> 12) & 0xf;
1538 rd0
= (insn
>> 16) & 0xf;
1539 rd1
= (insn
>> 0) & 0xf;
1540 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1541 switch ((insn
>> 22) & 3) {
1543 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1546 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1549 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1554 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1555 gen_op_iwmmxt_set_mup();
1556 gen_op_iwmmxt_set_cup();
1558 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1559 wrd
= (insn
>> 12) & 0xf;
1560 rd0
= (insn
>> 16) & 0xf;
1561 rd1
= (insn
>> 0) & 0xf;
1562 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1563 if (insn
& (1 << 22))
1564 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1566 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1567 if (!(insn
& (1 << 20)))
1568 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1569 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1570 gen_op_iwmmxt_set_mup();
1572 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1573 wrd
= (insn
>> 12) & 0xf;
1574 rd0
= (insn
>> 16) & 0xf;
1575 rd1
= (insn
>> 0) & 0xf;
1576 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1577 if (insn
& (1 << 21)) {
1578 if (insn
& (1 << 20))
1579 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1581 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1583 if (insn
& (1 << 20))
1584 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1586 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1588 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1589 gen_op_iwmmxt_set_mup();
1591 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1592 wrd
= (insn
>> 12) & 0xf;
1593 rd0
= (insn
>> 16) & 0xf;
1594 rd1
= (insn
>> 0) & 0xf;
1595 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1596 if (insn
& (1 << 21))
1597 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1599 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1600 if (!(insn
& (1 << 20))) {
1601 iwmmxt_load_reg(cpu_V1
, wrd
);
1602 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1604 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1605 gen_op_iwmmxt_set_mup();
1607 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1608 wrd
= (insn
>> 12) & 0xf;
1609 rd0
= (insn
>> 16) & 0xf;
1610 rd1
= (insn
>> 0) & 0xf;
1611 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1612 switch ((insn
>> 22) & 3) {
1614 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1617 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1620 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1625 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1626 gen_op_iwmmxt_set_mup();
1627 gen_op_iwmmxt_set_cup();
1629 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1630 wrd
= (insn
>> 12) & 0xf;
1631 rd0
= (insn
>> 16) & 0xf;
1632 rd1
= (insn
>> 0) & 0xf;
1633 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1634 if (insn
& (1 << 22)) {
1635 if (insn
& (1 << 20))
1636 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1638 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1640 if (insn
& (1 << 20))
1641 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1643 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1645 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1646 gen_op_iwmmxt_set_mup();
1647 gen_op_iwmmxt_set_cup();
1649 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1650 wrd
= (insn
>> 12) & 0xf;
1651 rd0
= (insn
>> 16) & 0xf;
1652 rd1
= (insn
>> 0) & 0xf;
1653 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1654 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1655 tcg_gen_andi_i32(tmp
, tmp
, 7);
1656 iwmmxt_load_reg(cpu_V1
, rd1
);
1657 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1659 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1660 gen_op_iwmmxt_set_mup();
1662 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1663 if (((insn
>> 6) & 3) == 3)
1665 rd
= (insn
>> 12) & 0xf;
1666 wrd
= (insn
>> 16) & 0xf;
1667 tmp
= load_reg(s
, rd
);
1668 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1669 switch ((insn
>> 6) & 3) {
1671 tmp2
= tcg_const_i32(0xff);
1672 tmp3
= tcg_const_i32((insn
& 7) << 3);
1675 tmp2
= tcg_const_i32(0xffff);
1676 tmp3
= tcg_const_i32((insn
& 3) << 4);
1679 tmp2
= tcg_const_i32(0xffffffff);
1680 tmp3
= tcg_const_i32((insn
& 1) << 5);
1686 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1687 tcg_temp_free(tmp3
);
1688 tcg_temp_free(tmp2
);
1690 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1691 gen_op_iwmmxt_set_mup();
1693 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1694 rd
= (insn
>> 12) & 0xf;
1695 wrd
= (insn
>> 16) & 0xf;
1696 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1698 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1700 switch ((insn
>> 22) & 3) {
1702 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1703 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1705 tcg_gen_ext8s_i32(tmp
, tmp
);
1707 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1711 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1712 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1714 tcg_gen_ext16s_i32(tmp
, tmp
);
1716 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1720 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1721 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1724 store_reg(s
, rd
, tmp
);
1726 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1727 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1729 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1730 switch ((insn
>> 22) & 3) {
1732 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1735 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1738 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1741 tcg_gen_shli_i32(tmp
, tmp
, 28);
1745 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1746 if (((insn
>> 6) & 3) == 3)
1748 rd
= (insn
>> 12) & 0xf;
1749 wrd
= (insn
>> 16) & 0xf;
1750 tmp
= load_reg(s
, rd
);
1751 switch ((insn
>> 6) & 3) {
1753 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1756 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1759 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1763 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1764 gen_op_iwmmxt_set_mup();
1766 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1767 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1769 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1771 tcg_gen_mov_i32(tmp2
, tmp
);
1772 switch ((insn
>> 22) & 3) {
1774 for (i
= 0; i
< 7; i
++) {
1775 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1776 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1780 for (i
= 0; i
< 3; i
++) {
1781 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1782 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1786 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1787 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1794 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1795 wrd
= (insn
>> 12) & 0xf;
1796 rd0
= (insn
>> 16) & 0xf;
1797 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1798 switch ((insn
>> 22) & 3) {
1800 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1803 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1806 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1811 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1812 gen_op_iwmmxt_set_mup();
1814 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1815 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1817 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1819 tcg_gen_mov_i32(tmp2
, tmp
);
1820 switch ((insn
>> 22) & 3) {
1822 for (i
= 0; i
< 7; i
++) {
1823 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1824 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1828 for (i
= 0; i
< 3; i
++) {
1829 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1830 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1834 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1835 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1842 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1843 rd
= (insn
>> 12) & 0xf;
1844 rd0
= (insn
>> 16) & 0xf;
1845 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1847 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1849 switch ((insn
>> 22) & 3) {
1851 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1854 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1857 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1860 store_reg(s
, rd
, tmp
);
1862 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1863 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1864 wrd
= (insn
>> 12) & 0xf;
1865 rd0
= (insn
>> 16) & 0xf;
1866 rd1
= (insn
>> 0) & 0xf;
1867 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1868 switch ((insn
>> 22) & 3) {
1870 if (insn
& (1 << 21))
1871 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1873 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1876 if (insn
& (1 << 21))
1877 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1879 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1882 if (insn
& (1 << 21))
1883 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1885 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1890 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1891 gen_op_iwmmxt_set_mup();
1892 gen_op_iwmmxt_set_cup();
1894 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1895 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1896 wrd
= (insn
>> 12) & 0xf;
1897 rd0
= (insn
>> 16) & 0xf;
1898 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1899 switch ((insn
>> 22) & 3) {
1901 if (insn
& (1 << 21))
1902 gen_op_iwmmxt_unpacklsb_M0();
1904 gen_op_iwmmxt_unpacklub_M0();
1907 if (insn
& (1 << 21))
1908 gen_op_iwmmxt_unpacklsw_M0();
1910 gen_op_iwmmxt_unpackluw_M0();
1913 if (insn
& (1 << 21))
1914 gen_op_iwmmxt_unpacklsl_M0();
1916 gen_op_iwmmxt_unpacklul_M0();
1921 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1922 gen_op_iwmmxt_set_mup();
1923 gen_op_iwmmxt_set_cup();
1925 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1926 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1927 wrd
= (insn
>> 12) & 0xf;
1928 rd0
= (insn
>> 16) & 0xf;
1929 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1930 switch ((insn
>> 22) & 3) {
1932 if (insn
& (1 << 21))
1933 gen_op_iwmmxt_unpackhsb_M0();
1935 gen_op_iwmmxt_unpackhub_M0();
1938 if (insn
& (1 << 21))
1939 gen_op_iwmmxt_unpackhsw_M0();
1941 gen_op_iwmmxt_unpackhuw_M0();
1944 if (insn
& (1 << 21))
1945 gen_op_iwmmxt_unpackhsl_M0();
1947 gen_op_iwmmxt_unpackhul_M0();
1952 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1953 gen_op_iwmmxt_set_mup();
1954 gen_op_iwmmxt_set_cup();
1956 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1957 case 0x214: case 0x614: case 0xa14: case 0xe14:
1958 if (((insn
>> 22) & 3) == 0)
1960 wrd
= (insn
>> 12) & 0xf;
1961 rd0
= (insn
>> 16) & 0xf;
1962 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1964 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1968 switch ((insn
>> 22) & 3) {
1970 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1973 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1976 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1980 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1981 gen_op_iwmmxt_set_mup();
1982 gen_op_iwmmxt_set_cup();
1984 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1985 case 0x014: case 0x414: case 0x814: case 0xc14:
1986 if (((insn
>> 22) & 3) == 0)
1988 wrd
= (insn
>> 12) & 0xf;
1989 rd0
= (insn
>> 16) & 0xf;
1990 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1992 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1996 switch ((insn
>> 22) & 3) {
1998 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2001 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2004 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2008 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2009 gen_op_iwmmxt_set_mup();
2010 gen_op_iwmmxt_set_cup();
2012 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2013 case 0x114: case 0x514: case 0x914: case 0xd14:
2014 if (((insn
>> 22) & 3) == 0)
2016 wrd
= (insn
>> 12) & 0xf;
2017 rd0
= (insn
>> 16) & 0xf;
2018 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2020 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2024 switch ((insn
>> 22) & 3) {
2026 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2029 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2032 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2036 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2037 gen_op_iwmmxt_set_mup();
2038 gen_op_iwmmxt_set_cup();
2040 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2041 case 0x314: case 0x714: case 0xb14: case 0xf14:
2042 if (((insn
>> 22) & 3) == 0)
2044 wrd
= (insn
>> 12) & 0xf;
2045 rd0
= (insn
>> 16) & 0xf;
2046 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2048 switch ((insn
>> 22) & 3) {
2050 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2054 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2057 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2061 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2064 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2068 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2072 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2073 gen_op_iwmmxt_set_mup();
2074 gen_op_iwmmxt_set_cup();
2076 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2077 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2078 wrd
= (insn
>> 12) & 0xf;
2079 rd0
= (insn
>> 16) & 0xf;
2080 rd1
= (insn
>> 0) & 0xf;
2081 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2082 switch ((insn
>> 22) & 3) {
2084 if (insn
& (1 << 21))
2085 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2087 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2090 if (insn
& (1 << 21))
2091 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2093 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2096 if (insn
& (1 << 21))
2097 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2099 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2104 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2105 gen_op_iwmmxt_set_mup();
2107 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2108 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2109 wrd
= (insn
>> 12) & 0xf;
2110 rd0
= (insn
>> 16) & 0xf;
2111 rd1
= (insn
>> 0) & 0xf;
2112 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2113 switch ((insn
>> 22) & 3) {
2115 if (insn
& (1 << 21))
2116 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2118 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2121 if (insn
& (1 << 21))
2122 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2124 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2127 if (insn
& (1 << 21))
2128 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2130 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2135 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2136 gen_op_iwmmxt_set_mup();
2138 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2139 case 0x402: case 0x502: case 0x602: case 0x702:
2140 wrd
= (insn
>> 12) & 0xf;
2141 rd0
= (insn
>> 16) & 0xf;
2142 rd1
= (insn
>> 0) & 0xf;
2143 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2144 tmp
= tcg_const_i32((insn
>> 20) & 3);
2145 iwmmxt_load_reg(cpu_V1
, rd1
);
2146 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2148 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2149 gen_op_iwmmxt_set_mup();
2151 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2152 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2153 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2154 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2155 wrd
= (insn
>> 12) & 0xf;
2156 rd0
= (insn
>> 16) & 0xf;
2157 rd1
= (insn
>> 0) & 0xf;
2158 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2159 switch ((insn
>> 20) & 0xf) {
2161 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2164 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2167 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2170 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2173 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2176 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2179 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2182 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2185 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2190 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2191 gen_op_iwmmxt_set_mup();
2192 gen_op_iwmmxt_set_cup();
2194 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2195 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2196 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2197 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2198 wrd
= (insn
>> 12) & 0xf;
2199 rd0
= (insn
>> 16) & 0xf;
2200 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2201 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2202 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2204 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2205 gen_op_iwmmxt_set_mup();
2206 gen_op_iwmmxt_set_cup();
2208 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2209 case 0x418: case 0x518: case 0x618: case 0x718:
2210 case 0x818: case 0x918: case 0xa18: case 0xb18:
2211 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2212 wrd
= (insn
>> 12) & 0xf;
2213 rd0
= (insn
>> 16) & 0xf;
2214 rd1
= (insn
>> 0) & 0xf;
2215 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2216 switch ((insn
>> 20) & 0xf) {
2218 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2221 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2224 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2227 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2230 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2233 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2236 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2239 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2242 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2247 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2248 gen_op_iwmmxt_set_mup();
2249 gen_op_iwmmxt_set_cup();
2251 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2252 case 0x408: case 0x508: case 0x608: case 0x708:
2253 case 0x808: case 0x908: case 0xa08: case 0xb08:
2254 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2255 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2257 wrd
= (insn
>> 12) & 0xf;
2258 rd0
= (insn
>> 16) & 0xf;
2259 rd1
= (insn
>> 0) & 0xf;
2260 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2261 switch ((insn
>> 22) & 3) {
2263 if (insn
& (1 << 21))
2264 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2266 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2269 if (insn
& (1 << 21))
2270 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2272 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2275 if (insn
& (1 << 21))
2276 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2278 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2281 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2282 gen_op_iwmmxt_set_mup();
2283 gen_op_iwmmxt_set_cup();
2285 case 0x201: case 0x203: case 0x205: case 0x207:
2286 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2287 case 0x211: case 0x213: case 0x215: case 0x217:
2288 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2289 wrd
= (insn
>> 5) & 0xf;
2290 rd0
= (insn
>> 12) & 0xf;
2291 rd1
= (insn
>> 0) & 0xf;
2292 if (rd0
== 0xf || rd1
== 0xf)
2294 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2295 tmp
= load_reg(s
, rd0
);
2296 tmp2
= load_reg(s
, rd1
);
2297 switch ((insn
>> 16) & 0xf) {
2298 case 0x0: /* TMIA */
2299 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2301 case 0x8: /* TMIAPH */
2302 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2304 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2305 if (insn
& (1 << 16))
2306 tcg_gen_shri_i32(tmp
, tmp
, 16);
2307 if (insn
& (1 << 17))
2308 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2309 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2318 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2319 gen_op_iwmmxt_set_mup();
2328 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2329 (ie. an undefined instruction). */
2330 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2332 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2335 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2336 /* Multiply with Internal Accumulate Format */
2337 rd0
= (insn
>> 12) & 0xf;
2339 acc
= (insn
>> 5) & 7;
2344 tmp
= load_reg(s
, rd0
);
2345 tmp2
= load_reg(s
, rd1
);
2346 switch ((insn
>> 16) & 0xf) {
2348 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2350 case 0x8: /* MIAPH */
2351 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2353 case 0xc: /* MIABB */
2354 case 0xd: /* MIABT */
2355 case 0xe: /* MIATB */
2356 case 0xf: /* MIATT */
2357 if (insn
& (1 << 16))
2358 tcg_gen_shri_i32(tmp
, tmp
, 16);
2359 if (insn
& (1 << 17))
2360 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2361 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2369 gen_op_iwmmxt_movq_wRn_M0(acc
);
2373 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2374 /* Internal Accumulator Access Format */
2375 rdhi
= (insn
>> 16) & 0xf;
2376 rdlo
= (insn
>> 12) & 0xf;
2382 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2383 iwmmxt_load_reg(cpu_V0
, acc
);
2384 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2385 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2386 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2387 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2389 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2390 iwmmxt_store_reg(cpu_V0
, acc
);
2398 /* Disassemble system coprocessor instruction. Return nonzero if
2399 instruction is not defined. */
2400 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2403 uint32_t rd
= (insn
>> 12) & 0xf;
2404 uint32_t cp
= (insn
>> 8) & 0xf;
2409 if (insn
& ARM_CP_RW_BIT
) {
2410 if (!env
->cp
[cp
].cp_read
)
2412 gen_set_pc_im(s
->pc
);
2414 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2415 store_reg(s
, rd
, tmp
);
2417 if (!env
->cp
[cp
].cp_write
)
2419 gen_set_pc_im(s
->pc
);
2420 tmp
= load_reg(s
, rd
);
2421 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2427 static int cp15_user_ok(uint32_t insn
)
2429 int cpn
= (insn
>> 16) & 0xf;
2430 int cpm
= insn
& 0xf;
2431 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2433 if (cpn
== 13 && cpm
== 0) {
2435 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2439 /* ISB, DSB, DMB. */
2440 if ((cpm
== 5 && op
== 4)
2441 || (cpm
== 10 && (op
== 4 || op
== 5)))
2447 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2448 instruction is not defined. */
2449 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2454 /* M profile cores use memory mapped registers instead of cp15. */
2455 if (arm_feature(env
, ARM_FEATURE_M
))
2458 if ((insn
& (1 << 25)) == 0) {
2459 if (insn
& (1 << 20)) {
2463 /* mcrr. Used for block cache operations, so implement as no-op. */
2466 if ((insn
& (1 << 4)) == 0) {
2470 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2473 if ((insn
& 0x0fff0fff) == 0x0e070f90
2474 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2475 /* Wait for interrupt. */
2476 gen_set_pc_im(s
->pc
);
2477 s
->is_jmp
= DISAS_WFI
;
2480 rd
= (insn
>> 12) & 0xf;
2481 if (insn
& ARM_CP_RW_BIT
) {
2483 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2484 /* If the destination register is r15 then sets condition codes. */
2486 store_reg(s
, rd
, tmp
);
2490 tmp
= load_reg(s
, rd
);
2491 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2493 /* Normally we would always end the TB here, but Linux
2494 * arch/arm/mach-pxa/sleep.S expects two instructions following
2495 * an MMU enable to execute from cache. Imitate this behaviour. */
2496 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2497 (insn
& 0x0fff0fff) != 0x0e010f10)
2503 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2504 #define VFP_SREG(insn, bigbit, smallbit) \
2505 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2506 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2507 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2508 reg = (((insn) >> (bigbit)) & 0x0f) \
2509 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2511 if (insn & (1 << (smallbit))) \
2513 reg = ((insn) >> (bigbit)) & 0x0f; \
2516 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2517 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2518 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2519 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2520 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2521 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2523 /* Move between integer and VFP cores. */
2524 static TCGv
gen_vfp_mrs(void)
2526 TCGv tmp
= new_tmp();
2527 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2531 static void gen_vfp_msr(TCGv tmp
)
2533 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2538 vfp_enabled(CPUState
* env
)
2540 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2543 static void gen_neon_dup_u8(TCGv var
, int shift
)
2545 TCGv tmp
= new_tmp();
2547 tcg_gen_shri_i32(var
, var
, shift
);
2548 tcg_gen_ext8u_i32(var
, var
);
2549 tcg_gen_shli_i32(tmp
, var
, 8);
2550 tcg_gen_or_i32(var
, var
, tmp
);
2551 tcg_gen_shli_i32(tmp
, var
, 16);
2552 tcg_gen_or_i32(var
, var
, tmp
);
2556 static void gen_neon_dup_low16(TCGv var
)
2558 TCGv tmp
= new_tmp();
2559 tcg_gen_ext16u_i32(var
, var
);
2560 tcg_gen_shli_i32(tmp
, var
, 16);
2561 tcg_gen_or_i32(var
, var
, tmp
);
2565 static void gen_neon_dup_high16(TCGv var
)
2567 TCGv tmp
= new_tmp();
2568 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2569 tcg_gen_shri_i32(tmp
, var
, 16);
2570 tcg_gen_or_i32(var
, var
, tmp
);
2574 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2575 (ie. an undefined instruction). */
2576 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2578 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2584 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2587 if (!vfp_enabled(env
)) {
2588 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2589 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2591 rn
= (insn
>> 16) & 0xf;
2592 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2593 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2596 dp
= ((insn
& 0xf00) == 0xb00);
2597 switch ((insn
>> 24) & 0xf) {
2599 if (insn
& (1 << 4)) {
2600 /* single register transfer */
2601 rd
= (insn
>> 12) & 0xf;
2606 VFP_DREG_N(rn
, insn
);
2609 if (insn
& 0x00c00060
2610 && !arm_feature(env
, ARM_FEATURE_NEON
))
2613 pass
= (insn
>> 21) & 1;
2614 if (insn
& (1 << 22)) {
2616 offset
= ((insn
>> 5) & 3) * 8;
2617 } else if (insn
& (1 << 5)) {
2619 offset
= (insn
& (1 << 6)) ? 16 : 0;
2624 if (insn
& ARM_CP_RW_BIT
) {
2626 tmp
= neon_load_reg(rn
, pass
);
2630 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2631 if (insn
& (1 << 23))
2637 if (insn
& (1 << 23)) {
2639 tcg_gen_shri_i32(tmp
, tmp
, 16);
2645 tcg_gen_sari_i32(tmp
, tmp
, 16);
2654 store_reg(s
, rd
, tmp
);
2657 tmp
= load_reg(s
, rd
);
2658 if (insn
& (1 << 23)) {
2661 gen_neon_dup_u8(tmp
, 0);
2662 } else if (size
== 1) {
2663 gen_neon_dup_low16(tmp
);
2665 for (n
= 0; n
<= pass
* 2; n
++) {
2667 tcg_gen_mov_i32(tmp2
, tmp
);
2668 neon_store_reg(rn
, n
, tmp2
);
2670 neon_store_reg(rn
, n
, tmp
);
2675 tmp2
= neon_load_reg(rn
, pass
);
2676 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2680 tmp2
= neon_load_reg(rn
, pass
);
2681 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2687 neon_store_reg(rn
, pass
, tmp
);
2691 if ((insn
& 0x6f) != 0x00)
2693 rn
= VFP_SREG_N(insn
);
2694 if (insn
& ARM_CP_RW_BIT
) {
2696 if (insn
& (1 << 21)) {
2697 /* system register */
2702 /* VFP2 allows access to FSID from userspace.
2703 VFP3 restricts all id registers to privileged
2706 && arm_feature(env
, ARM_FEATURE_VFP3
))
2708 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2713 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2715 case ARM_VFP_FPINST
:
2716 case ARM_VFP_FPINST2
:
2717 /* Not present in VFP3. */
2719 || arm_feature(env
, ARM_FEATURE_VFP3
))
2721 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2725 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2726 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2729 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2735 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2737 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2743 gen_mov_F0_vreg(0, rn
);
2744 tmp
= gen_vfp_mrs();
2747 /* Set the 4 flag bits in the CPSR. */
2751 store_reg(s
, rd
, tmp
);
2755 tmp
= load_reg(s
, rd
);
2756 if (insn
& (1 << 21)) {
2758 /* system register */
2763 /* Writes are ignored. */
2766 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2773 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2776 case ARM_VFP_FPINST
:
2777 case ARM_VFP_FPINST2
:
2778 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2785 gen_mov_vreg_F0(0, rn
);
2790 /* data processing */
2791 /* The opcode is in bits 23, 21, 20 and 6. */
2792 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2796 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2798 /* rn is register number */
2799 VFP_DREG_N(rn
, insn
);
2802 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2803 /* Integer or single precision destination. */
2804 rd
= VFP_SREG_D(insn
);
2806 VFP_DREG_D(rd
, insn
);
2809 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2810 /* Integer source. */
2811 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2813 VFP_DREG_M(rm
, insn
);
2816 rn
= VFP_SREG_N(insn
);
2817 if (op
== 15 && rn
== 15) {
2818 /* Double precision destination. */
2819 VFP_DREG_D(rd
, insn
);
2821 rd
= VFP_SREG_D(insn
);
2823 rm
= VFP_SREG_M(insn
);
2826 veclen
= env
->vfp
.vec_len
;
2827 if (op
== 15 && rn
> 3)
2830 /* Shut up compiler warnings. */
2841 /* Figure out what type of vector operation this is. */
2842 if ((rd
& bank_mask
) == 0) {
2847 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2849 delta_d
= env
->vfp
.vec_stride
+ 1;
2851 if ((rm
& bank_mask
) == 0) {
2852 /* mixed scalar/vector */
2861 /* Load the initial operands. */
2866 /* Integer source */
2867 gen_mov_F0_vreg(0, rm
);
2872 gen_mov_F0_vreg(dp
, rd
);
2873 gen_mov_F1_vreg(dp
, rm
);
2877 /* Compare with zero */
2878 gen_mov_F0_vreg(dp
, rd
);
2889 /* Source and destination the same. */
2890 gen_mov_F0_vreg(dp
, rd
);
2893 /* One source operand. */
2894 gen_mov_F0_vreg(dp
, rm
);
2898 /* Two source operands. */
2899 gen_mov_F0_vreg(dp
, rn
);
2900 gen_mov_F1_vreg(dp
, rm
);
2904 /* Perform the calculation. */
2906 case 0: /* mac: fd + (fn * fm) */
2908 gen_mov_F1_vreg(dp
, rd
);
2911 case 1: /* nmac: fd - (fn * fm) */
2914 gen_mov_F1_vreg(dp
, rd
);
2917 case 2: /* msc: -fd + (fn * fm) */
2919 gen_mov_F1_vreg(dp
, rd
);
2922 case 3: /* nmsc: -fd - (fn * fm) */
2925 gen_mov_F1_vreg(dp
, rd
);
2928 case 4: /* mul: fn * fm */
2931 case 5: /* nmul: -(fn * fm) */
2935 case 6: /* add: fn + fm */
2938 case 7: /* sub: fn - fm */
2941 case 8: /* div: fn / fm */
2944 case 14: /* fconst */
2945 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2948 n
= (insn
<< 12) & 0x80000000;
2949 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2956 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
2963 tcg_gen_movi_i32(cpu_F0s
, n
);
2966 case 15: /* extension space */
2989 case 11: /* cmpez */
2993 case 15: /* single<->double conversion */
2995 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
2997 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
2999 case 16: /* fuito */
3002 case 17: /* fsito */
3005 case 20: /* fshto */
3006 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3008 gen_vfp_shto(dp
, 16 - rm
);
3010 case 21: /* fslto */
3011 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3013 gen_vfp_slto(dp
, 32 - rm
);
3015 case 22: /* fuhto */
3016 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3018 gen_vfp_uhto(dp
, 16 - rm
);
3020 case 23: /* fulto */
3021 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3023 gen_vfp_ulto(dp
, 32 - rm
);
3025 case 24: /* ftoui */
3028 case 25: /* ftouiz */
3031 case 26: /* ftosi */
3034 case 27: /* ftosiz */
3037 case 28: /* ftosh */
3038 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3040 gen_vfp_tosh(dp
, 16 - rm
);
3042 case 29: /* ftosl */
3043 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3045 gen_vfp_tosl(dp
, 32 - rm
);
3047 case 30: /* ftouh */
3048 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3050 gen_vfp_touh(dp
, 16 - rm
);
3052 case 31: /* ftoul */
3053 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3055 gen_vfp_toul(dp
, 32 - rm
);
3057 default: /* undefined */
3058 printf ("rn:%d\n", rn
);
3062 default: /* undefined */
3063 printf ("op:%d\n", op
);
3067 /* Write back the result. */
3068 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3069 ; /* Comparison, do nothing. */
3070 else if (op
== 15 && rn
> 17)
3071 /* Integer result. */
3072 gen_mov_vreg_F0(0, rd
);
3073 else if (op
== 15 && rn
== 15)
3075 gen_mov_vreg_F0(!dp
, rd
);
3077 gen_mov_vreg_F0(dp
, rd
);
3079 /* break out of the loop if we have finished */
3083 if (op
== 15 && delta_m
== 0) {
3084 /* single source one-many */
3086 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3088 gen_mov_vreg_F0(dp
, rd
);
3092 /* Setup the next operands. */
3094 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3098 /* One source operand. */
3099 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3101 gen_mov_F0_vreg(dp
, rm
);
3103 /* Two source operands. */
3104 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3106 gen_mov_F0_vreg(dp
, rn
);
3108 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3110 gen_mov_F1_vreg(dp
, rm
);
3118 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3119 /* two-register transfer */
3120 rn
= (insn
>> 16) & 0xf;
3121 rd
= (insn
>> 12) & 0xf;
3123 VFP_DREG_M(rm
, insn
);
3125 rm
= VFP_SREG_M(insn
);
3128 if (insn
& ARM_CP_RW_BIT
) {
3131 gen_mov_F0_vreg(0, rm
* 2);
3132 tmp
= gen_vfp_mrs();
3133 store_reg(s
, rd
, tmp
);
3134 gen_mov_F0_vreg(0, rm
* 2 + 1);
3135 tmp
= gen_vfp_mrs();
3136 store_reg(s
, rn
, tmp
);
3138 gen_mov_F0_vreg(0, rm
);
3139 tmp
= gen_vfp_mrs();
3140 store_reg(s
, rn
, tmp
);
3141 gen_mov_F0_vreg(0, rm
+ 1);
3142 tmp
= gen_vfp_mrs();
3143 store_reg(s
, rd
, tmp
);
3148 tmp
= load_reg(s
, rd
);
3150 gen_mov_vreg_F0(0, rm
* 2);
3151 tmp
= load_reg(s
, rn
);
3153 gen_mov_vreg_F0(0, rm
* 2 + 1);
3155 tmp
= load_reg(s
, rn
);
3157 gen_mov_vreg_F0(0, rm
);
3158 tmp
= load_reg(s
, rd
);
3160 gen_mov_vreg_F0(0, rm
+ 1);
3165 rn
= (insn
>> 16) & 0xf;
3167 VFP_DREG_D(rd
, insn
);
3169 rd
= VFP_SREG_D(insn
);
3170 if (s
->thumb
&& rn
== 15) {
3172 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3174 addr
= load_reg(s
, rn
);
3176 if ((insn
& 0x01200000) == 0x01000000) {
3177 /* Single load/store */
3178 offset
= (insn
& 0xff) << 2;
3179 if ((insn
& (1 << 23)) == 0)
3181 tcg_gen_addi_i32(addr
, addr
, offset
);
3182 if (insn
& (1 << 20)) {
3183 gen_vfp_ld(s
, dp
, addr
);
3184 gen_mov_vreg_F0(dp
, rd
);
3186 gen_mov_F0_vreg(dp
, rd
);
3187 gen_vfp_st(s
, dp
, addr
);
3191 /* load/store multiple */
3193 n
= (insn
>> 1) & 0x7f;
3197 if (insn
& (1 << 24)) /* pre-decrement */
3198 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3204 for (i
= 0; i
< n
; i
++) {
3205 if (insn
& ARM_CP_RW_BIT
) {
3207 gen_vfp_ld(s
, dp
, addr
);
3208 gen_mov_vreg_F0(dp
, rd
+ i
);
3211 gen_mov_F0_vreg(dp
, rd
+ i
);
3212 gen_vfp_st(s
, dp
, addr
);
3214 tcg_gen_addi_i32(addr
, addr
, offset
);
3216 if (insn
& (1 << 21)) {
3218 if (insn
& (1 << 24))
3219 offset
= -offset
* n
;
3220 else if (dp
&& (insn
& 1))
3226 tcg_gen_addi_i32(addr
, addr
, offset
);
3227 store_reg(s
, rn
, addr
);
3235 /* Should never happen. */
3241 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3243 TranslationBlock
*tb
;
3246 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3248 gen_set_pc_im(dest
);
3249 tcg_gen_exit_tb((long)tb
+ n
);
3251 gen_set_pc_im(dest
);
3256 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3258 if (unlikely(s
->singlestep_enabled
)) {
3259 /* An indirect jump so that we still trigger the debug exception. */
3264 gen_goto_tb(s
, 0, dest
);
3265 s
->is_jmp
= DISAS_TB_JUMP
;
3269 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3272 tcg_gen_sari_i32(t0
, t0
, 16);
3276 tcg_gen_sari_i32(t1
, t1
, 16);
3279 tcg_gen_mul_i32(t0
, t0
, t1
);
3282 /* Return the mask of PSR bits set by a MSR instruction. */
3283 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3287 if (flags
& (1 << 0))
3289 if (flags
& (1 << 1))
3291 if (flags
& (1 << 2))
3293 if (flags
& (1 << 3))
3296 /* Mask out undefined bits. */
3297 mask
&= ~CPSR_RESERVED
;
3298 if (!arm_feature(env
, ARM_FEATURE_V6
))
3299 mask
&= ~(CPSR_E
| CPSR_GE
);
3300 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3302 /* Mask out execution state bits. */
3305 /* Mask out privileged bits. */
3311 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3312 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3316 /* ??? This is also undefined in system mode. */
3320 tmp
= load_cpu_field(spsr
);
3321 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3322 tcg_gen_andi_i32(t0
, t0
, mask
);
3323 tcg_gen_or_i32(tmp
, tmp
, t0
);
3324 store_cpu_field(tmp
, spsr
);
3326 gen_set_cpsr(t0
, mask
);
3333 /* Returns nonzero if access to the PSR is not permitted. */
3334 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3338 tcg_gen_movi_i32(tmp
, val
);
3339 return gen_set_psr(s
, mask
, spsr
, tmp
);
3342 /* Generate an old-style exception return. Marks pc as dead. */
3343 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3346 store_reg(s
, 15, pc
);
3347 tmp
= load_cpu_field(spsr
);
3348 gen_set_cpsr(tmp
, 0xffffffff);
3350 s
->is_jmp
= DISAS_UPDATE
;
3353 /* Generate a v6 exception return. Marks both values as dead. */
3354 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3356 gen_set_cpsr(cpsr
, 0xffffffff);
3358 store_reg(s
, 15, pc
);
3359 s
->is_jmp
= DISAS_UPDATE
;
3363 gen_set_condexec (DisasContext
*s
)
3365 if (s
->condexec_mask
) {
3366 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3367 TCGv tmp
= new_tmp();
3368 tcg_gen_movi_i32(tmp
, val
);
3369 store_cpu_field(tmp
, condexec_bits
);
3373 static void gen_nop_hint(DisasContext
*s
, int val
)
3377 gen_set_pc_im(s
->pc
);
3378 s
->is_jmp
= DISAS_WFI
;
3382 /* TODO: Implement SEV and WFE. May help SMP performance. */
3388 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3390 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3393 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3394 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3395 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3401 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3404 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3405 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3406 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3411 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3412 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3413 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3414 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3415 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3417 /* FIXME: This is wrong. They set the wrong overflow bit. */
3418 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3419 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3420 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3421 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3423 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3424 switch ((size << 1) | u) { \
3426 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3429 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3432 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3435 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3438 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3441 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3443 default: return 1; \
3446 #define GEN_NEON_INTEGER_OP(name) do { \
3447 switch ((size << 1) | u) { \
3449 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3452 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3455 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3458 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3461 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3464 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3466 default: return 1; \
3469 static TCGv
neon_load_scratch(int scratch
)
3471 TCGv tmp
= new_tmp();
3472 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3476 static void neon_store_scratch(int scratch
, TCGv var
)
3478 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3482 static inline TCGv
neon_get_scalar(int size
, int reg
)
3486 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3488 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3490 gen_neon_dup_low16(tmp
);
3492 gen_neon_dup_high16(tmp
);
3498 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3506 tcg_gen_andi_i32(rd
, t0
, 0xff);
3507 tcg_gen_shri_i32(tmp
, t0
, 8);
3508 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3509 tcg_gen_or_i32(rd
, rd
, tmp
);
3510 tcg_gen_shli_i32(tmp
, t1
, 16);
3511 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3512 tcg_gen_or_i32(rd
, rd
, tmp
);
3513 tcg_gen_shli_i32(tmp
, t1
, 8);
3514 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3515 tcg_gen_or_i32(rd
, rd
, tmp
);
3517 tcg_gen_shri_i32(rm
, t0
, 8);
3518 tcg_gen_andi_i32(rm
, rm
, 0xff);
3519 tcg_gen_shri_i32(tmp
, t0
, 16);
3520 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3521 tcg_gen_or_i32(rm
, rm
, tmp
);
3522 tcg_gen_shli_i32(tmp
, t1
, 8);
3523 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3524 tcg_gen_or_i32(rm
, rm
, tmp
);
3525 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3526 tcg_gen_or_i32(t1
, rm
, tmp
);
3527 tcg_gen_mov_i32(t0
, rd
);
3534 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3542 tcg_gen_andi_i32(rd
, t0
, 0xff);
3543 tcg_gen_shli_i32(tmp
, t1
, 8);
3544 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3545 tcg_gen_or_i32(rd
, rd
, tmp
);
3546 tcg_gen_shli_i32(tmp
, t0
, 16);
3547 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3548 tcg_gen_or_i32(rd
, rd
, tmp
);
3549 tcg_gen_shli_i32(tmp
, t1
, 24);
3550 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3551 tcg_gen_or_i32(rd
, rd
, tmp
);
3553 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3554 tcg_gen_shri_i32(tmp
, t0
, 8);
3555 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3556 tcg_gen_or_i32(rm
, rm
, tmp
);
3557 tcg_gen_shri_i32(tmp
, t1
, 8);
3558 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3559 tcg_gen_or_i32(rm
, rm
, tmp
);
3560 tcg_gen_shri_i32(tmp
, t0
, 16);
3561 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3562 tcg_gen_or_i32(t1
, rm
, tmp
);
3563 tcg_gen_mov_i32(t0
, rd
);
3570 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3577 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3578 tcg_gen_shli_i32(tmp2
, t1
, 16);
3579 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3580 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3581 tcg_gen_shri_i32(tmp2
, t0
, 16);
3582 tcg_gen_or_i32(t1
, t1
, tmp2
);
3583 tcg_gen_mov_i32(t0
, tmp
);
3589 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3594 for (n
= 0; n
< q
+ 1; n
+= 2) {
3595 t0
= neon_load_reg(reg
, n
);
3596 t1
= neon_load_reg(reg
, n
+ 1);
3598 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3599 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3600 case 2: /* no-op */; break;
3603 neon_store_scratch(tmp
+ n
, t0
);
3604 neon_store_scratch(tmp
+ n
+ 1, t1
);
3608 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3615 tcg_gen_shli_i32(rd
, t0
, 8);
3616 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3617 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3618 tcg_gen_or_i32(rd
, rd
, tmp
);
3620 tcg_gen_shri_i32(t1
, t1
, 8);
3621 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3622 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3623 tcg_gen_or_i32(t1
, t1
, tmp
);
3624 tcg_gen_mov_i32(t0
, rd
);
3630 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3637 tcg_gen_shli_i32(rd
, t0
, 16);
3638 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3639 tcg_gen_or_i32(rd
, rd
, tmp
);
3640 tcg_gen_shri_i32(t1
, t1
, 16);
3641 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3642 tcg_gen_or_i32(t1
, t1
, tmp
);
3643 tcg_gen_mov_i32(t0
, rd
);
3654 } neon_ls_element_type
[11] = {
3668 /* Translate a NEON load/store element instruction. Return nonzero if the
3669 instruction is invalid. */
3670 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3687 if (!vfp_enabled(env
))
3689 VFP_DREG_D(rd
, insn
);
3690 rn
= (insn
>> 16) & 0xf;
3692 load
= (insn
& (1 << 21)) != 0;
3694 if ((insn
& (1 << 23)) == 0) {
3695 /* Load store all elements. */
3696 op
= (insn
>> 8) & 0xf;
3697 size
= (insn
>> 6) & 3;
3698 if (op
> 10 || size
== 3)
3700 nregs
= neon_ls_element_type
[op
].nregs
;
3701 interleave
= neon_ls_element_type
[op
].interleave
;
3702 load_reg_var(s
, addr
, rn
);
3703 stride
= (1 << size
) * interleave
;
3704 for (reg
= 0; reg
< nregs
; reg
++) {
3705 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3706 load_reg_var(s
, addr
, rn
);
3707 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3708 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3709 load_reg_var(s
, addr
, rn
);
3710 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3712 for (pass
= 0; pass
< 2; pass
++) {
3715 tmp
= gen_ld32(addr
, IS_USER(s
));
3716 neon_store_reg(rd
, pass
, tmp
);
3718 tmp
= neon_load_reg(rd
, pass
);
3719 gen_st32(tmp
, addr
, IS_USER(s
));
3721 tcg_gen_addi_i32(addr
, addr
, stride
);
3722 } else if (size
== 1) {
3724 tmp
= gen_ld16u(addr
, IS_USER(s
));
3725 tcg_gen_addi_i32(addr
, addr
, stride
);
3726 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3727 tcg_gen_addi_i32(addr
, addr
, stride
);
3728 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3730 neon_store_reg(rd
, pass
, tmp
);
3732 tmp
= neon_load_reg(rd
, pass
);
3734 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3735 gen_st16(tmp
, addr
, IS_USER(s
));
3736 tcg_gen_addi_i32(addr
, addr
, stride
);
3737 gen_st16(tmp2
, addr
, IS_USER(s
));
3738 tcg_gen_addi_i32(addr
, addr
, stride
);
3740 } else /* size == 0 */ {
3743 for (n
= 0; n
< 4; n
++) {
3744 tmp
= gen_ld8u(addr
, IS_USER(s
));
3745 tcg_gen_addi_i32(addr
, addr
, stride
);
3749 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3753 neon_store_reg(rd
, pass
, tmp2
);
3755 tmp2
= neon_load_reg(rd
, pass
);
3756 for (n
= 0; n
< 4; n
++) {
3759 tcg_gen_mov_i32(tmp
, tmp2
);
3761 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3763 gen_st8(tmp
, addr
, IS_USER(s
));
3764 tcg_gen_addi_i32(addr
, addr
, stride
);
3770 rd
+= neon_ls_element_type
[op
].spacing
;
3774 size
= (insn
>> 10) & 3;
3776 /* Load single element to all lanes. */
3779 size
= (insn
>> 6) & 3;
3780 nregs
= ((insn
>> 8) & 3) + 1;
3781 stride
= (insn
& (1 << 5)) ? 2 : 1;
3782 load_reg_var(s
, addr
, rn
);
3783 for (reg
= 0; reg
< nregs
; reg
++) {
3786 tmp
= gen_ld8u(addr
, IS_USER(s
));
3787 gen_neon_dup_u8(tmp
, 0);
3790 tmp
= gen_ld16u(addr
, IS_USER(s
));
3791 gen_neon_dup_low16(tmp
);
3794 tmp
= gen_ld32(addr
, IS_USER(s
));
3798 default: /* Avoid compiler warnings. */
3801 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3803 tcg_gen_mov_i32(tmp2
, tmp
);
3804 neon_store_reg(rd
, 0, tmp2
);
3805 neon_store_reg(rd
, 1, tmp
);
3808 stride
= (1 << size
) * nregs
;
3810 /* Single element. */
3811 pass
= (insn
>> 7) & 1;
3814 shift
= ((insn
>> 5) & 3) * 8;
3818 shift
= ((insn
>> 6) & 1) * 16;
3819 stride
= (insn
& (1 << 5)) ? 2 : 1;
3823 stride
= (insn
& (1 << 6)) ? 2 : 1;
3828 nregs
= ((insn
>> 8) & 3) + 1;
3829 load_reg_var(s
, addr
, rn
);
3830 for (reg
= 0; reg
< nregs
; reg
++) {
3834 tmp
= gen_ld8u(addr
, IS_USER(s
));
3837 tmp
= gen_ld16u(addr
, IS_USER(s
));
3840 tmp
= gen_ld32(addr
, IS_USER(s
));
3842 default: /* Avoid compiler warnings. */
3846 tmp2
= neon_load_reg(rd
, pass
);
3847 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3850 neon_store_reg(rd
, pass
, tmp
);
3851 } else { /* Store */
3852 tmp
= neon_load_reg(rd
, pass
);
3854 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3857 gen_st8(tmp
, addr
, IS_USER(s
));
3860 gen_st16(tmp
, addr
, IS_USER(s
));
3863 gen_st32(tmp
, addr
, IS_USER(s
));
3868 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3870 stride
= nregs
* (1 << size
);
3877 base
= load_reg(s
, rn
);
3879 tcg_gen_addi_i32(base
, base
, stride
);
3882 index
= load_reg(s
, rm
);
3883 tcg_gen_add_i32(base
, base
, index
);
3886 store_reg(s
, rn
, base
);
3891 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3892 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3894 tcg_gen_and_i32(t
, t
, c
);
3895 tcg_gen_bic_i32(f
, f
, c
);
3896 tcg_gen_or_i32(dest
, t
, f
);
3899 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3902 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3903 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3904 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3909 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3912 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3913 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3914 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3919 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3922 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3923 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3924 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3929 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3935 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3936 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3941 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3942 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3949 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3950 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3955 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3956 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3963 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3967 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3968 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3969 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3974 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3975 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3976 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3983 static inline void gen_neon_addl(int size
)
3986 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3987 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3988 case 2: tcg_gen_add_i64(CPU_V001
); break;
3993 static inline void gen_neon_subl(int size
)
3996 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
3997 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
3998 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4003 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4006 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4007 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4008 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4013 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4016 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4017 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4022 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4026 switch ((size
<< 1) | u
) {
4027 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4028 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4029 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4030 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4032 tmp
= gen_muls_i64_i32(a
, b
);
4033 tcg_gen_mov_i64(dest
, tmp
);
4036 tmp
= gen_mulu_i64_i32(a
, b
);
4037 tcg_gen_mov_i64(dest
, tmp
);
4043 /* Translate a NEON data processing instruction. Return nonzero if the
4044 instruction is invalid.
4045 We process data in a mixture of 32-bit and 64-bit chunks.
4046 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4048 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4066 if (!vfp_enabled(env
))
4068 q
= (insn
& (1 << 6)) != 0;
4069 u
= (insn
>> 24) & 1;
4070 VFP_DREG_D(rd
, insn
);
4071 VFP_DREG_N(rn
, insn
);
4072 VFP_DREG_M(rm
, insn
);
4073 size
= (insn
>> 20) & 3;
4074 if ((insn
& (1 << 23)) == 0) {
4075 /* Three register same length. */
4076 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4077 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4078 || op
== 10 || op
== 11 || op
== 16)) {
4079 /* 64-bit element instructions. */
4080 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4081 neon_load_reg64(cpu_V0
, rn
+ pass
);
4082 neon_load_reg64(cpu_V1
, rm
+ pass
);
4086 gen_helper_neon_add_saturate_u64(CPU_V001
);
4088 gen_helper_neon_add_saturate_s64(CPU_V001
);
4093 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4095 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4100 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4102 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4107 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4110 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4114 case 10: /* VRSHL */
4116 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4118 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4121 case 11: /* VQRSHL */
4123 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4126 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4132 tcg_gen_sub_i64(CPU_V001
);
4134 tcg_gen_add_i64(CPU_V001
);
4140 neon_store_reg64(cpu_V0
, rd
+ pass
);
4147 case 10: /* VRSHL */
4148 case 11: /* VQRSHL */
4151 /* Shift instruction operands are reversed. */
4158 case 20: /* VPMAX */
4159 case 21: /* VPMIN */
4160 case 23: /* VPADD */
4163 case 26: /* VPADD (float) */
4164 pairwise
= (u
&& size
< 2);
4166 case 30: /* VPMIN/VPMAX (float) */
4174 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4183 tmp
= neon_load_reg(rn
, n
);
4184 tmp2
= neon_load_reg(rn
, n
+ 1);
4186 tmp
= neon_load_reg(rm
, n
);
4187 tmp2
= neon_load_reg(rm
, n
+ 1);
4191 tmp
= neon_load_reg(rn
, pass
);
4192 tmp2
= neon_load_reg(rm
, pass
);
4196 GEN_NEON_INTEGER_OP(hadd
);
4199 GEN_NEON_INTEGER_OP_ENV(qadd
);
4201 case 2: /* VRHADD */
4202 GEN_NEON_INTEGER_OP(rhadd
);
4204 case 3: /* Logic ops. */
4205 switch ((u
<< 2) | size
) {
4207 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4210 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4213 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4216 tcg_gen_not_i32(tmp2
, tmp2
);
4217 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4220 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4223 tmp3
= neon_load_reg(rd
, pass
);
4224 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4228 tmp3
= neon_load_reg(rd
, pass
);
4229 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4233 tmp3
= neon_load_reg(rd
, pass
);
4234 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4240 GEN_NEON_INTEGER_OP(hsub
);
4243 GEN_NEON_INTEGER_OP_ENV(qsub
);
4246 GEN_NEON_INTEGER_OP(cgt
);
4249 GEN_NEON_INTEGER_OP(cge
);
4252 GEN_NEON_INTEGER_OP(shl
);
4255 GEN_NEON_INTEGER_OP_ENV(qshl
);
4257 case 10: /* VRSHL */
4258 GEN_NEON_INTEGER_OP(rshl
);
4260 case 11: /* VQRSHL */
4261 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4264 GEN_NEON_INTEGER_OP(max
);
4267 GEN_NEON_INTEGER_OP(min
);
4270 GEN_NEON_INTEGER_OP(abd
);
4273 GEN_NEON_INTEGER_OP(abd
);
4275 tmp2
= neon_load_reg(rd
, pass
);
4276 gen_neon_add(size
, tmp
, tmp2
);
4279 if (!u
) { /* VADD */
4280 if (gen_neon_add(size
, tmp
, tmp2
))
4284 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4285 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4286 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4292 if (!u
) { /* VTST */
4294 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4295 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4296 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4301 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4302 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4303 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4308 case 18: /* Multiply. */
4310 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4311 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4312 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4316 tmp2
= neon_load_reg(rd
, pass
);
4318 gen_neon_rsb(size
, tmp
, tmp2
);
4320 gen_neon_add(size
, tmp
, tmp2
);
4324 if (u
) { /* polynomial */
4325 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4326 } else { /* Integer */
4328 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4329 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4330 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4335 case 20: /* VPMAX */
4336 GEN_NEON_INTEGER_OP(pmax
);
4338 case 21: /* VPMIN */
4339 GEN_NEON_INTEGER_OP(pmin
);
4341 case 22: /* Hultiply high. */
4342 if (!u
) { /* VQDMULH */
4344 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4345 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4348 } else { /* VQRDHMUL */
4350 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4351 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4356 case 23: /* VPADD */
4360 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4361 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4362 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4366 case 26: /* Floating point arithnetic. */
4367 switch ((u
<< 2) | size
) {
4369 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4372 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4375 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4378 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4384 case 27: /* Float multiply. */
4385 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4388 tmp2
= neon_load_reg(rd
, pass
);
4390 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4392 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4396 case 28: /* Float compare. */
4398 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4401 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4403 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4406 case 29: /* Float compare absolute. */
4410 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4412 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4414 case 30: /* Float min/max. */
4416 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4418 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4422 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4424 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4431 /* Save the result. For elementwise operations we can put it
4432 straight into the destination register. For pairwise operations
4433 we have to be careful to avoid clobbering the source operands. */
4434 if (pairwise
&& rd
== rm
) {
4435 neon_store_scratch(pass
, tmp
);
4437 neon_store_reg(rd
, pass
, tmp
);
4441 if (pairwise
&& rd
== rm
) {
4442 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4443 tmp
= neon_load_scratch(pass
);
4444 neon_store_reg(rd
, pass
, tmp
);
4447 /* End of 3 register same size operations. */
4448 } else if (insn
& (1 << 4)) {
4449 if ((insn
& 0x00380080) != 0) {
4450 /* Two registers and shift. */
4451 op
= (insn
>> 8) & 0xf;
4452 if (insn
& (1 << 7)) {
4457 while ((insn
& (1 << (size
+ 19))) == 0)
4460 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4461 /* To avoid excessive dumplication of ops we implement shift
4462 by immediate using the variable shift operations. */
4464 /* Shift by immediate:
4465 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4466 /* Right shifts are encoded as N - shift, where N is the
4467 element size in bits. */
4469 shift
= shift
- (1 << (size
+ 3));
4477 imm
= (uint8_t) shift
;
4482 imm
= (uint16_t) shift
;
4493 for (pass
= 0; pass
< count
; pass
++) {
4495 neon_load_reg64(cpu_V0
, rm
+ pass
);
4496 tcg_gen_movi_i64(cpu_V1
, imm
);
4501 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4503 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4508 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4510 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4515 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4517 case 5: /* VSHL, VSLI */
4518 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4522 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4524 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4526 case 7: /* VQSHLU */
4527 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4530 if (op
== 1 || op
== 3) {
4532 neon_load_reg64(cpu_V0
, rd
+ pass
);
4533 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4534 } else if (op
== 4 || (op
== 5 && u
)) {
4536 cpu_abort(env
, "VS[LR]I.64 not implemented");
4538 neon_store_reg64(cpu_V0
, rd
+ pass
);
4539 } else { /* size < 3 */
4540 /* Operands in T0 and T1. */
4541 tmp
= neon_load_reg(rm
, pass
);
4543 tcg_gen_movi_i32(tmp2
, imm
);
4547 GEN_NEON_INTEGER_OP(shl
);
4551 GEN_NEON_INTEGER_OP(rshl
);
4556 GEN_NEON_INTEGER_OP(shl
);
4558 case 5: /* VSHL, VSLI */
4560 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4561 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4562 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4567 GEN_NEON_INTEGER_OP_ENV(qshl
);
4569 case 7: /* VQSHLU */
4571 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4572 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4573 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4580 if (op
== 1 || op
== 3) {
4582 tmp2
= neon_load_reg(rd
, pass
);
4583 gen_neon_add(size
, tmp2
, tmp
);
4585 } else if (op
== 4 || (op
== 5 && u
)) {
4590 imm
= 0xff >> -shift
;
4592 imm
= (uint8_t)(0xff << shift
);
4598 imm
= 0xffff >> -shift
;
4600 imm
= (uint16_t)(0xffff << shift
);
4605 imm
= 0xffffffffu
>> -shift
;
4607 imm
= 0xffffffffu
<< shift
;
4612 tmp2
= neon_load_reg(rd
, pass
);
4613 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4614 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4615 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4618 neon_store_reg(rd
, pass
, tmp
);
4621 } else if (op
< 10) {
4622 /* Shift by immediate and narrow:
4623 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4624 shift
= shift
- (1 << (size
+ 3));
4628 imm
= (uint16_t)shift
;
4630 tmp2
= tcg_const_i32(imm
);
4631 TCGV_UNUSED_I64(tmp64
);
4634 imm
= (uint32_t)shift
;
4635 tmp2
= tcg_const_i32(imm
);
4636 TCGV_UNUSED_I64(tmp64
);
4639 tmp64
= tcg_const_i64(shift
);
4646 for (pass
= 0; pass
< 2; pass
++) {
4648 neon_load_reg64(cpu_V0
, rm
+ pass
);
4651 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4653 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4656 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4658 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4661 tmp
= neon_load_reg(rm
+ pass
, 0);
4662 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4663 tmp3
= neon_load_reg(rm
+ pass
, 1);
4664 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4665 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4670 if (op
== 8 && !u
) {
4671 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4674 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4676 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4681 neon_store_reg(rd
, 0, tmp2
);
4682 neon_store_reg(rd
, 1, tmp
);
4685 } else if (op
== 10) {
4689 tmp
= neon_load_reg(rm
, 0);
4690 tmp2
= neon_load_reg(rm
, 1);
4691 for (pass
= 0; pass
< 2; pass
++) {
4695 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4698 /* The shift is less than the width of the source
4699 type, so we can just shift the whole register. */
4700 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4701 if (size
< 2 || !u
) {
4704 imm
= (0xffu
>> (8 - shift
));
4707 imm
= 0xffff >> (16 - shift
);
4709 imm64
= imm
| (((uint64_t)imm
) << 32);
4710 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4713 neon_store_reg64(cpu_V0
, rd
+ pass
);
4715 } else if (op
== 15 || op
== 16) {
4716 /* VCVT fixed-point. */
4717 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4718 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4721 gen_vfp_ulto(0, shift
);
4723 gen_vfp_slto(0, shift
);
4726 gen_vfp_toul(0, shift
);
4728 gen_vfp_tosl(0, shift
);
4730 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4735 } else { /* (insn & 0x00380080) == 0 */
4738 op
= (insn
>> 8) & 0xf;
4739 /* One register and immediate. */
4740 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4741 invert
= (insn
& (1 << 5)) != 0;
4759 imm
= (imm
<< 8) | (imm
<< 24);
4762 imm
= (imm
< 8) | 0xff;
4765 imm
= (imm
<< 16) | 0xffff;
4768 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4773 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4774 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4780 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4781 if (op
& 1 && op
< 12) {
4782 tmp
= neon_load_reg(rd
, pass
);
4784 /* The immediate value has already been inverted, so
4786 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4788 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4793 if (op
== 14 && invert
) {
4796 for (n
= 0; n
< 4; n
++) {
4797 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4798 val
|= 0xff << (n
* 8);
4800 tcg_gen_movi_i32(tmp
, val
);
4802 tcg_gen_movi_i32(tmp
, imm
);
4805 neon_store_reg(rd
, pass
, tmp
);
4808 } else { /* (insn & 0x00800010 == 0x00800000) */
4810 op
= (insn
>> 8) & 0xf;
4811 if ((insn
& (1 << 6)) == 0) {
4812 /* Three registers of different lengths. */
4816 /* prewiden, src1_wide, src2_wide */
4817 static const int neon_3reg_wide
[16][3] = {
4818 {1, 0, 0}, /* VADDL */
4819 {1, 1, 0}, /* VADDW */
4820 {1, 0, 0}, /* VSUBL */
4821 {1, 1, 0}, /* VSUBW */
4822 {0, 1, 1}, /* VADDHN */
4823 {0, 0, 0}, /* VABAL */
4824 {0, 1, 1}, /* VSUBHN */
4825 {0, 0, 0}, /* VABDL */
4826 {0, 0, 0}, /* VMLAL */
4827 {0, 0, 0}, /* VQDMLAL */
4828 {0, 0, 0}, /* VMLSL */
4829 {0, 0, 0}, /* VQDMLSL */
4830 {0, 0, 0}, /* Integer VMULL */
4831 {0, 0, 0}, /* VQDMULL */
4832 {0, 0, 0} /* Polynomial VMULL */
4835 prewiden
= neon_3reg_wide
[op
][0];
4836 src1_wide
= neon_3reg_wide
[op
][1];
4837 src2_wide
= neon_3reg_wide
[op
][2];
4839 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4842 /* Avoid overlapping operands. Wide source operands are
4843 always aligned so will never overlap with wide
4844 destinations in problematic ways. */
4845 if (rd
== rm
&& !src2_wide
) {
4846 tmp
= neon_load_reg(rm
, 1);
4847 neon_store_scratch(2, tmp
);
4848 } else if (rd
== rn
&& !src1_wide
) {
4849 tmp
= neon_load_reg(rn
, 1);
4850 neon_store_scratch(2, tmp
);
4853 for (pass
= 0; pass
< 2; pass
++) {
4855 neon_load_reg64(cpu_V0
, rn
+ pass
);
4858 if (pass
== 1 && rd
== rn
) {
4859 tmp
= neon_load_scratch(2);
4861 tmp
= neon_load_reg(rn
, pass
);
4864 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4868 neon_load_reg64(cpu_V1
, rm
+ pass
);
4871 if (pass
== 1 && rd
== rm
) {
4872 tmp2
= neon_load_scratch(2);
4874 tmp2
= neon_load_reg(rm
, pass
);
4877 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4881 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4882 gen_neon_addl(size
);
4884 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4885 gen_neon_subl(size
);
4887 case 5: case 7: /* VABAL, VABDL */
4888 switch ((size
<< 1) | u
) {
4890 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4893 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4896 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4899 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4902 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4905 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4912 case 8: case 9: case 10: case 11: case 12: case 13:
4913 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4914 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4918 case 14: /* Polynomial VMULL */
4919 cpu_abort(env
, "Polynomial VMULL not implemented");
4921 default: /* 15 is RESERVED. */
4924 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4926 if (op
== 10 || op
== 11) {
4927 gen_neon_negl(cpu_V0
, size
);
4931 neon_load_reg64(cpu_V1
, rd
+ pass
);
4935 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4936 gen_neon_addl(size
);
4938 case 9: case 11: /* VQDMLAL, VQDMLSL */
4939 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4940 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4943 case 13: /* VQDMULL */
4944 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4949 neon_store_reg64(cpu_V0
, rd
+ pass
);
4950 } else if (op
== 4 || op
== 6) {
4951 /* Narrowing operation. */
4956 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4959 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4962 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4963 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4970 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4973 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4976 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4977 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4978 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4986 neon_store_reg(rd
, 0, tmp3
);
4987 neon_store_reg(rd
, 1, tmp
);
4990 /* Write back the result. */
4991 neon_store_reg64(cpu_V0
, rd
+ pass
);
4995 /* Two registers and a scalar. */
4997 case 0: /* Integer VMLA scalar */
4998 case 1: /* Float VMLA scalar */
4999 case 4: /* Integer VMLS scalar */
5000 case 5: /* Floating point VMLS scalar */
5001 case 8: /* Integer VMUL scalar */
5002 case 9: /* Floating point VMUL scalar */
5003 case 12: /* VQDMULH scalar */
5004 case 13: /* VQRDMULH scalar */
5005 tmp
= neon_get_scalar(size
, rm
);
5006 neon_store_scratch(0, tmp
);
5007 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5008 tmp
= neon_load_scratch(0);
5009 tmp2
= neon_load_reg(rn
, pass
);
5012 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5014 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5016 } else if (op
== 13) {
5018 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5020 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5022 } else if (op
& 1) {
5023 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
5026 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5027 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5028 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5035 tmp2
= neon_load_reg(rd
, pass
);
5038 gen_neon_add(size
, tmp
, tmp2
);
5041 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
5044 gen_neon_rsb(size
, tmp
, tmp2
);
5047 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5054 neon_store_reg(rd
, pass
, tmp
);
5057 case 2: /* VMLAL sclar */
5058 case 3: /* VQDMLAL scalar */
5059 case 6: /* VMLSL scalar */
5060 case 7: /* VQDMLSL scalar */
5061 case 10: /* VMULL scalar */
5062 case 11: /* VQDMULL scalar */
5063 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5066 tmp2
= neon_get_scalar(size
, rm
);
5067 tmp3
= neon_load_reg(rn
, 1);
5069 for (pass
= 0; pass
< 2; pass
++) {
5071 tmp
= neon_load_reg(rn
, 0);
5075 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5077 if (op
== 6 || op
== 7) {
5078 gen_neon_negl(cpu_V0
, size
);
5081 neon_load_reg64(cpu_V1
, rd
+ pass
);
5085 gen_neon_addl(size
);
5088 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5089 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5095 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5100 neon_store_reg64(cpu_V0
, rd
+ pass
);
5106 default: /* 14 and 15 are RESERVED */
5110 } else { /* size == 3 */
5113 imm
= (insn
>> 8) & 0xf;
5120 neon_load_reg64(cpu_V0
, rn
);
5122 neon_load_reg64(cpu_V1
, rn
+ 1);
5124 } else if (imm
== 8) {
5125 neon_load_reg64(cpu_V0
, rn
+ 1);
5127 neon_load_reg64(cpu_V1
, rm
);
5130 tmp64
= tcg_temp_new_i64();
5132 neon_load_reg64(cpu_V0
, rn
);
5133 neon_load_reg64(tmp64
, rn
+ 1);
5135 neon_load_reg64(cpu_V0
, rn
+ 1);
5136 neon_load_reg64(tmp64
, rm
);
5138 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5139 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5140 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5142 neon_load_reg64(cpu_V1
, rm
);
5144 neon_load_reg64(cpu_V1
, rm
+ 1);
5147 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5148 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5149 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5152 neon_load_reg64(cpu_V0
, rn
);
5153 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5154 neon_load_reg64(cpu_V1
, rm
);
5155 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5156 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5158 neon_store_reg64(cpu_V0
, rd
);
5160 neon_store_reg64(cpu_V1
, rd
+ 1);
5162 } else if ((insn
& (1 << 11)) == 0) {
5163 /* Two register misc. */
5164 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5165 size
= (insn
>> 18) & 3;
5167 case 0: /* VREV64 */
5170 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5171 tmp
= neon_load_reg(rm
, pass
* 2);
5172 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5174 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5175 case 1: gen_swap_half(tmp
); break;
5176 case 2: /* no-op */ break;
5179 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5181 neon_store_reg(rd
, pass
* 2, tmp2
);
5184 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5185 case 1: gen_swap_half(tmp2
); break;
5188 neon_store_reg(rd
, pass
* 2, tmp2
);
5192 case 4: case 5: /* VPADDL */
5193 case 12: case 13: /* VPADAL */
5196 for (pass
= 0; pass
< q
+ 1; pass
++) {
5197 tmp
= neon_load_reg(rm
, pass
* 2);
5198 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5199 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5200 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5202 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5203 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5204 case 2: tcg_gen_add_i64(CPU_V001
); break;
5209 neon_load_reg64(cpu_V1
, rd
+ pass
);
5210 gen_neon_addl(size
);
5212 neon_store_reg64(cpu_V0
, rd
+ pass
);
5217 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5218 tmp
= neon_load_reg(rm
, n
);
5219 tmp2
= neon_load_reg(rd
, n
+ 1);
5220 neon_store_reg(rm
, n
, tmp2
);
5221 neon_store_reg(rd
, n
+ 1, tmp
);
5229 Rd A3 A2 A1 A0 B2 B0 A2 A0
5230 Rm B3 B2 B1 B0 B3 B1 A3 A1
5234 gen_neon_unzip(rd
, q
, 0, size
);
5235 gen_neon_unzip(rm
, q
, 4, size
);
5237 static int unzip_order_q
[8] =
5238 {0, 2, 4, 6, 1, 3, 5, 7};
5239 for (n
= 0; n
< 8; n
++) {
5240 int reg
= (n
< 4) ? rd
: rm
;
5241 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5242 neon_store_reg(reg
, n
% 4, tmp
);
5245 static int unzip_order
[4] =
5247 for (n
= 0; n
< 4; n
++) {
5248 int reg
= (n
< 2) ? rd
: rm
;
5249 tmp
= neon_load_scratch(unzip_order
[n
]);
5250 neon_store_reg(reg
, n
% 2, tmp
);
5256 Rd A3 A2 A1 A0 B1 A1 B0 A0
5257 Rm B3 B2 B1 B0 B3 A3 B2 A2
5261 count
= (q
? 4 : 2);
5262 for (n
= 0; n
< count
; n
++) {
5263 tmp
= neon_load_reg(rd
, n
);
5264 tmp2
= neon_load_reg(rd
, n
);
5266 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5267 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5268 case 2: /* no-op */; break;
5271 neon_store_scratch(n
* 2, tmp
);
5272 neon_store_scratch(n
* 2 + 1, tmp2
);
5274 for (n
= 0; n
< count
* 2; n
++) {
5275 int reg
= (n
< count
) ? rd
: rm
;
5276 tmp
= neon_load_scratch(n
);
5277 neon_store_reg(reg
, n
% count
, tmp
);
5280 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5284 for (pass
= 0; pass
< 2; pass
++) {
5285 neon_load_reg64(cpu_V0
, rm
+ pass
);
5287 if (op
== 36 && q
== 0) {
5288 gen_neon_narrow(size
, tmp
, cpu_V0
);
5290 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5292 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5297 neon_store_reg(rd
, 0, tmp2
);
5298 neon_store_reg(rd
, 1, tmp
);
5302 case 38: /* VSHLL */
5305 tmp
= neon_load_reg(rm
, 0);
5306 tmp2
= neon_load_reg(rm
, 1);
5307 for (pass
= 0; pass
< 2; pass
++) {
5310 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5311 neon_store_reg64(cpu_V0
, rd
+ pass
);
5316 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5317 if (op
== 30 || op
== 31 || op
>= 58) {
5318 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5319 neon_reg_offset(rm
, pass
));
5322 tmp
= neon_load_reg(rm
, pass
);
5325 case 1: /* VREV32 */
5327 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5328 case 1: gen_swap_half(tmp
); break;
5332 case 2: /* VREV16 */
5339 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5340 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5341 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5347 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5348 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5349 case 2: gen_helper_clz(tmp
, tmp
); break;
5356 gen_helper_neon_cnt_u8(tmp
, tmp
);
5361 tcg_gen_not_i32(tmp
, tmp
);
5363 case 14: /* VQABS */
5365 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5366 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5367 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5371 case 15: /* VQNEG */
5373 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5374 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5375 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5379 case 16: case 19: /* VCGT #0, VCLE #0 */
5380 tmp2
= tcg_const_i32(0);
5382 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5383 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5384 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5387 tcg_temp_free(tmp2
);
5389 tcg_gen_not_i32(tmp
, tmp
);
5391 case 17: case 20: /* VCGE #0, VCLT #0 */
5392 tmp2
= tcg_const_i32(0);
5394 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5395 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5396 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5399 tcg_temp_free(tmp2
);
5401 tcg_gen_not_i32(tmp
, tmp
);
5403 case 18: /* VCEQ #0 */
5404 tmp2
= tcg_const_i32(0);
5406 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5407 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5408 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5411 tcg_temp_free(tmp2
);
5415 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5416 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5417 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5424 tmp2
= tcg_const_i32(0);
5425 gen_neon_rsb(size
, tmp
, tmp2
);
5426 tcg_temp_free(tmp2
);
5428 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5429 tmp2
= tcg_const_i32(0);
5430 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5431 tcg_temp_free(tmp2
);
5433 tcg_gen_not_i32(tmp
, tmp
);
5435 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5436 tmp2
= tcg_const_i32(0);
5437 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5438 tcg_temp_free(tmp2
);
5440 tcg_gen_not_i32(tmp
, tmp
);
5442 case 26: /* Float VCEQ #0 */
5443 tmp2
= tcg_const_i32(0);
5444 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5445 tcg_temp_free(tmp2
);
5447 case 30: /* Float VABS */
5450 case 31: /* Float VNEG */
5454 tmp2
= neon_load_reg(rd
, pass
);
5455 neon_store_reg(rm
, pass
, tmp2
);
5458 tmp2
= neon_load_reg(rd
, pass
);
5460 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5461 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5465 neon_store_reg(rm
, pass
, tmp2
);
5467 case 56: /* Integer VRECPE */
5468 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5470 case 57: /* Integer VRSQRTE */
5471 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5473 case 58: /* Float VRECPE */
5474 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5476 case 59: /* Float VRSQRTE */
5477 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5479 case 60: /* VCVT.F32.S32 */
5482 case 61: /* VCVT.F32.U32 */
5485 case 62: /* VCVT.S32.F32 */
5488 case 63: /* VCVT.U32.F32 */
5492 /* Reserved: 21, 29, 39-56 */
5495 if (op
== 30 || op
== 31 || op
>= 58) {
5496 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5497 neon_reg_offset(rd
, pass
));
5499 neon_store_reg(rd
, pass
, tmp
);
5504 } else if ((insn
& (1 << 10)) == 0) {
5506 n
= ((insn
>> 5) & 0x18) + 8;
5507 if (insn
& (1 << 6)) {
5508 tmp
= neon_load_reg(rd
, 0);
5511 tcg_gen_movi_i32(tmp
, 0);
5513 tmp2
= neon_load_reg(rm
, 0);
5514 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5517 if (insn
& (1 << 6)) {
5518 tmp
= neon_load_reg(rd
, 1);
5521 tcg_gen_movi_i32(tmp
, 0);
5523 tmp3
= neon_load_reg(rm
, 1);
5524 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5526 neon_store_reg(rd
, 0, tmp2
);
5527 neon_store_reg(rd
, 1, tmp3
);
5529 } else if ((insn
& 0x380) == 0) {
5531 if (insn
& (1 << 19)) {
5532 tmp
= neon_load_reg(rm
, 1);
5534 tmp
= neon_load_reg(rm
, 0);
5536 if (insn
& (1 << 16)) {
5537 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5538 } else if (insn
& (1 << 17)) {
5539 if ((insn
>> 18) & 1)
5540 gen_neon_dup_high16(tmp
);
5542 gen_neon_dup_low16(tmp
);
5544 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5546 tcg_gen_mov_i32(tmp2
, tmp
);
5547 neon_store_reg(rd
, pass
, tmp2
);
5558 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5560 int crn
= (insn
>> 16) & 0xf;
5561 int crm
= insn
& 0xf;
5562 int op1
= (insn
>> 21) & 7;
5563 int op2
= (insn
>> 5) & 7;
5564 int rt
= (insn
>> 12) & 0xf;
5567 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5568 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5572 tmp
= load_cpu_field(teecr
);
5573 store_reg(s
, rt
, tmp
);
5576 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5578 if (IS_USER(s
) && (env
->teecr
& 1))
5580 tmp
= load_cpu_field(teehbr
);
5581 store_reg(s
, rt
, tmp
);
5585 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5586 op1
, crn
, crm
, op2
);
5590 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5592 int crn
= (insn
>> 16) & 0xf;
5593 int crm
= insn
& 0xf;
5594 int op1
= (insn
>> 21) & 7;
5595 int op2
= (insn
>> 5) & 7;
5596 int rt
= (insn
>> 12) & 0xf;
5599 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5600 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5604 tmp
= load_reg(s
, rt
);
5605 gen_helper_set_teecr(cpu_env
, tmp
);
5609 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5611 if (IS_USER(s
) && (env
->teecr
& 1))
5613 tmp
= load_reg(s
, rt
);
5614 store_cpu_field(tmp
, teehbr
);
5618 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5619 op1
, crn
, crm
, op2
);
5623 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5627 cpnum
= (insn
>> 8) & 0xf;
5628 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5629 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5635 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5636 return disas_iwmmxt_insn(env
, s
, insn
);
5637 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5638 return disas_dsp_insn(env
, s
, insn
);
5643 return disas_vfp_insn (env
, s
, insn
);
5645 /* Coprocessors 7-15 are architecturally reserved by ARM.
5646 Unfortunately Intel decided to ignore this. */
5647 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5649 if (insn
& (1 << 20))
5650 return disas_cp14_read(env
, s
, insn
);
5652 return disas_cp14_write(env
, s
, insn
);
5654 return disas_cp15_insn (env
, s
, insn
);
5657 /* Unknown coprocessor. See if the board has hooked it. */
5658 return disas_cp_insn (env
, s
, insn
);
5663 /* Store a 64-bit value to a register pair. Clobbers val. */
5664 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5668 tcg_gen_trunc_i64_i32(tmp
, val
);
5669 store_reg(s
, rlow
, tmp
);
5671 tcg_gen_shri_i64(val
, val
, 32);
5672 tcg_gen_trunc_i64_i32(tmp
, val
);
5673 store_reg(s
, rhigh
, tmp
);
5676 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5677 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5682 /* Load value and extend to 64 bits. */
5683 tmp
= tcg_temp_new_i64();
5684 tmp2
= load_reg(s
, rlow
);
5685 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5687 tcg_gen_add_i64(val
, val
, tmp
);
5690 /* load and add a 64-bit value from a register pair. */
5691 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5697 /* Load 64-bit value rd:rn. */
5698 tmpl
= load_reg(s
, rlow
);
5699 tmph
= load_reg(s
, rhigh
);
5700 tmp
= tcg_temp_new_i64();
5701 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5704 tcg_gen_add_i64(val
, val
, tmp
);
5707 /* Set N and Z flags from a 64-bit value. */
5708 static void gen_logicq_cc(TCGv_i64 val
)
5710 TCGv tmp
= new_tmp();
5711 gen_helper_logicq_cc(tmp
, val
);
5716 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5718 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5725 insn
= ldl_code(s
->pc
);
5728 /* M variants do not implement ARM mode. */
5733 /* Unconditional instructions. */
5734 if (((insn
>> 25) & 7) == 1) {
5735 /* NEON Data processing. */
5736 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5739 if (disas_neon_data_insn(env
, s
, insn
))
5743 if ((insn
& 0x0f100000) == 0x04000000) {
5744 /* NEON load/store. */
5745 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5748 if (disas_neon_ls_insn(env
, s
, insn
))
5752 if ((insn
& 0x0d70f000) == 0x0550f000)
5754 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5757 if (insn
& (1 << 9)) {
5758 /* BE8 mode not implemented. */
5762 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5763 switch ((insn
>> 4) & 0xf) {
5766 gen_helper_clrex(cpu_env
);
5772 /* We don't emulate caches so these are a no-op. */
5777 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5783 op1
= (insn
& 0x1f);
5784 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5785 addr
= load_reg(s
, 13);
5788 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5790 i
= (insn
>> 23) & 3;
5792 case 0: offset
= -4; break; /* DA */
5793 case 1: offset
= 0; break; /* IA */
5794 case 2: offset
= -8; break; /* DB */
5795 case 3: offset
= 4; break; /* IB */
5799 tcg_gen_addi_i32(addr
, addr
, offset
);
5800 tmp
= load_reg(s
, 14);
5801 gen_st32(tmp
, addr
, 0);
5802 tmp
= load_cpu_field(spsr
);
5803 tcg_gen_addi_i32(addr
, addr
, 4);
5804 gen_st32(tmp
, addr
, 0);
5805 if (insn
& (1 << 21)) {
5806 /* Base writeback. */
5808 case 0: offset
= -8; break;
5809 case 1: offset
= 4; break;
5810 case 2: offset
= -4; break;
5811 case 3: offset
= 0; break;
5815 tcg_gen_addi_i32(addr
, addr
, offset
);
5816 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5817 store_reg(s
, 13, addr
);
5819 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5825 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5831 rn
= (insn
>> 16) & 0xf;
5832 addr
= load_reg(s
, rn
);
5833 i
= (insn
>> 23) & 3;
5835 case 0: offset
= -4; break; /* DA */
5836 case 1: offset
= 0; break; /* IA */
5837 case 2: offset
= -8; break; /* DB */
5838 case 3: offset
= 4; break; /* IB */
5842 tcg_gen_addi_i32(addr
, addr
, offset
);
5843 /* Load PC into tmp and CPSR into tmp2. */
5844 tmp
= gen_ld32(addr
, 0);
5845 tcg_gen_addi_i32(addr
, addr
, 4);
5846 tmp2
= gen_ld32(addr
, 0);
5847 if (insn
& (1 << 21)) {
5848 /* Base writeback. */
5850 case 0: offset
= -8; break;
5851 case 1: offset
= 4; break;
5852 case 2: offset
= -4; break;
5853 case 3: offset
= 0; break;
5857 tcg_gen_addi_i32(addr
, addr
, offset
);
5858 store_reg(s
, rn
, addr
);
5862 gen_rfe(s
, tmp
, tmp2
);
5864 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5865 /* branch link and change to thumb (blx <offset>) */
5868 val
= (uint32_t)s
->pc
;
5870 tcg_gen_movi_i32(tmp
, val
);
5871 store_reg(s
, 14, tmp
);
5872 /* Sign-extend the 24-bit offset */
5873 offset
= (((int32_t)insn
) << 8) >> 8;
5874 /* offset * 4 + bit24 * 2 + (thumb bit) */
5875 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5876 /* pipeline offset */
5880 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5881 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5882 /* iWMMXt register transfer. */
5883 if (env
->cp15
.c15_cpar
& (1 << 1))
5884 if (!disas_iwmmxt_insn(env
, s
, insn
))
5887 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5888 /* Coprocessor double register transfer. */
5889 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5890 /* Additional coprocessor register transfer. */
5891 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5894 /* cps (privileged) */
5898 if (insn
& (1 << 19)) {
5899 if (insn
& (1 << 8))
5901 if (insn
& (1 << 7))
5903 if (insn
& (1 << 6))
5905 if (insn
& (1 << 18))
5908 if (insn
& (1 << 17)) {
5910 val
|= (insn
& 0x1f);
5913 gen_set_psr_im(s
, mask
, 0, val
);
5920 /* if not always execute, we generate a conditional jump to
5922 s
->condlabel
= gen_new_label();
5923 gen_test_cc(cond
^ 1, s
->condlabel
);
5926 if ((insn
& 0x0f900000) == 0x03000000) {
5927 if ((insn
& (1 << 21)) == 0) {
5929 rd
= (insn
>> 12) & 0xf;
5930 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5931 if ((insn
& (1 << 22)) == 0) {
5934 tcg_gen_movi_i32(tmp
, val
);
5937 tmp
= load_reg(s
, rd
);
5938 tcg_gen_ext16u_i32(tmp
, tmp
);
5939 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5941 store_reg(s
, rd
, tmp
);
5943 if (((insn
>> 12) & 0xf) != 0xf)
5945 if (((insn
>> 16) & 0xf) == 0) {
5946 gen_nop_hint(s
, insn
& 0xff);
5948 /* CPSR = immediate */
5950 shift
= ((insn
>> 8) & 0xf) * 2;
5952 val
= (val
>> shift
) | (val
<< (32 - shift
));
5953 i
= ((insn
& (1 << 22)) != 0);
5954 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5958 } else if ((insn
& 0x0f900000) == 0x01000000
5959 && (insn
& 0x00000090) != 0x00000090) {
5960 /* miscellaneous instructions */
5961 op1
= (insn
>> 21) & 3;
5962 sh
= (insn
>> 4) & 0xf;
5965 case 0x0: /* move program status register */
5968 tmp
= load_reg(s
, rm
);
5969 i
= ((op1
& 2) != 0);
5970 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
5974 rd
= (insn
>> 12) & 0xf;
5978 tmp
= load_cpu_field(spsr
);
5981 gen_helper_cpsr_read(tmp
);
5983 store_reg(s
, rd
, tmp
);
5988 /* branch/exchange thumb (bx). */
5989 tmp
= load_reg(s
, rm
);
5991 } else if (op1
== 3) {
5993 rd
= (insn
>> 12) & 0xf;
5994 tmp
= load_reg(s
, rm
);
5995 gen_helper_clz(tmp
, tmp
);
5996 store_reg(s
, rd
, tmp
);
6004 /* Trivial implementation equivalent to bx. */
6005 tmp
= load_reg(s
, rm
);
6015 /* branch link/exchange thumb (blx) */
6016 tmp
= load_reg(s
, rm
);
6018 tcg_gen_movi_i32(tmp2
, s
->pc
);
6019 store_reg(s
, 14, tmp2
);
6022 case 0x5: /* saturating add/subtract */
6023 rd
= (insn
>> 12) & 0xf;
6024 rn
= (insn
>> 16) & 0xf;
6025 tmp
= load_reg(s
, rm
);
6026 tmp2
= load_reg(s
, rn
);
6028 gen_helper_double_saturate(tmp2
, tmp2
);
6030 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6032 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6034 store_reg(s
, rd
, tmp
);
6037 gen_set_condexec(s
);
6038 gen_set_pc_im(s
->pc
- 4);
6039 gen_exception(EXCP_BKPT
);
6040 s
->is_jmp
= DISAS_JUMP
;
6042 case 0x8: /* signed multiply */
6046 rs
= (insn
>> 8) & 0xf;
6047 rn
= (insn
>> 12) & 0xf;
6048 rd
= (insn
>> 16) & 0xf;
6050 /* (32 * 16) >> 16 */
6051 tmp
= load_reg(s
, rm
);
6052 tmp2
= load_reg(s
, rs
);
6054 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6057 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6058 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6060 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6061 if ((sh
& 2) == 0) {
6062 tmp2
= load_reg(s
, rn
);
6063 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6066 store_reg(s
, rd
, tmp
);
6069 tmp
= load_reg(s
, rm
);
6070 tmp2
= load_reg(s
, rs
);
6071 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6074 tmp64
= tcg_temp_new_i64();
6075 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6077 gen_addq(s
, tmp64
, rn
, rd
);
6078 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6081 tmp2
= load_reg(s
, rn
);
6082 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6085 store_reg(s
, rd
, tmp
);
6092 } else if (((insn
& 0x0e000000) == 0 &&
6093 (insn
& 0x00000090) != 0x90) ||
6094 ((insn
& 0x0e000000) == (1 << 25))) {
6095 int set_cc
, logic_cc
, shiftop
;
6097 op1
= (insn
>> 21) & 0xf;
6098 set_cc
= (insn
>> 20) & 1;
6099 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6101 /* data processing instruction */
6102 if (insn
& (1 << 25)) {
6103 /* immediate operand */
6105 shift
= ((insn
>> 8) & 0xf) * 2;
6107 val
= (val
>> shift
) | (val
<< (32 - shift
));
6110 tcg_gen_movi_i32(tmp2
, val
);
6111 if (logic_cc
&& shift
) {
6112 gen_set_CF_bit31(tmp2
);
6117 tmp2
= load_reg(s
, rm
);
6118 shiftop
= (insn
>> 5) & 3;
6119 if (!(insn
& (1 << 4))) {
6120 shift
= (insn
>> 7) & 0x1f;
6121 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6123 rs
= (insn
>> 8) & 0xf;
6124 tmp
= load_reg(s
, rs
);
6125 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6128 if (op1
!= 0x0f && op1
!= 0x0d) {
6129 rn
= (insn
>> 16) & 0xf;
6130 tmp
= load_reg(s
, rn
);
6134 rd
= (insn
>> 12) & 0xf;
6137 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6141 store_reg_bx(env
, s
, rd
, tmp
);
6144 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6148 store_reg_bx(env
, s
, rd
, tmp
);
6151 if (set_cc
&& rd
== 15) {
6152 /* SUBS r15, ... is used for exception return. */
6156 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6157 gen_exception_return(s
, tmp
);
6160 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6162 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6164 store_reg_bx(env
, s
, rd
, tmp
);
6169 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6171 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6173 store_reg_bx(env
, s
, rd
, tmp
);
6177 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6179 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6181 store_reg_bx(env
, s
, rd
, tmp
);
6185 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6187 gen_add_carry(tmp
, tmp
, tmp2
);
6189 store_reg_bx(env
, s
, rd
, tmp
);
6193 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6195 gen_sub_carry(tmp
, tmp
, tmp2
);
6197 store_reg_bx(env
, s
, rd
, tmp
);
6201 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6203 gen_sub_carry(tmp
, tmp2
, tmp
);
6205 store_reg_bx(env
, s
, rd
, tmp
);
6209 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6216 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6223 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6229 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6234 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6238 store_reg_bx(env
, s
, rd
, tmp
);
6241 if (logic_cc
&& rd
== 15) {
6242 /* MOVS r15, ... is used for exception return. */
6246 gen_exception_return(s
, tmp2
);
6251 store_reg_bx(env
, s
, rd
, tmp2
);
6255 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6259 store_reg_bx(env
, s
, rd
, tmp
);
6263 tcg_gen_not_i32(tmp2
, tmp2
);
6267 store_reg_bx(env
, s
, rd
, tmp2
);
6270 if (op1
!= 0x0f && op1
!= 0x0d) {
6274 /* other instructions */
6275 op1
= (insn
>> 24) & 0xf;
6279 /* multiplies, extra load/stores */
6280 sh
= (insn
>> 5) & 3;
6283 rd
= (insn
>> 16) & 0xf;
6284 rn
= (insn
>> 12) & 0xf;
6285 rs
= (insn
>> 8) & 0xf;
6287 op1
= (insn
>> 20) & 0xf;
6289 case 0: case 1: case 2: case 3: case 6:
6291 tmp
= load_reg(s
, rs
);
6292 tmp2
= load_reg(s
, rm
);
6293 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6295 if (insn
& (1 << 22)) {
6296 /* Subtract (mls) */
6298 tmp2
= load_reg(s
, rn
);
6299 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6301 } else if (insn
& (1 << 21)) {
6303 tmp2
= load_reg(s
, rn
);
6304 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6307 if (insn
& (1 << 20))
6309 store_reg(s
, rd
, tmp
);
6313 tmp
= load_reg(s
, rs
);
6314 tmp2
= load_reg(s
, rm
);
6315 if (insn
& (1 << 22))
6316 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6318 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6319 if (insn
& (1 << 21)) /* mult accumulate */
6320 gen_addq(s
, tmp64
, rn
, rd
);
6321 if (!(insn
& (1 << 23))) { /* double accumulate */
6323 gen_addq_lo(s
, tmp64
, rn
);
6324 gen_addq_lo(s
, tmp64
, rd
);
6326 if (insn
& (1 << 20))
6327 gen_logicq_cc(tmp64
);
6328 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6332 rn
= (insn
>> 16) & 0xf;
6333 rd
= (insn
>> 12) & 0xf;
6334 if (insn
& (1 << 23)) {
6335 /* load/store exclusive */
6336 op1
= (insn
>> 21) & 0x3;
6341 addr
= tcg_temp_local_new_i32();
6342 load_reg_var(s
, addr
, rn
);
6343 if (insn
& (1 << 20)) {
6344 gen_helper_mark_exclusive(cpu_env
, addr
);
6347 tmp
= gen_ld32(addr
, IS_USER(s
));
6349 case 1: /* ldrexd */
6350 tmp
= gen_ld32(addr
, IS_USER(s
));
6351 store_reg(s
, rd
, tmp
);
6352 tcg_gen_addi_i32(addr
, addr
, 4);
6353 tmp
= gen_ld32(addr
, IS_USER(s
));
6356 case 2: /* ldrexb */
6357 tmp
= gen_ld8u(addr
, IS_USER(s
));
6359 case 3: /* ldrexh */
6360 tmp
= gen_ld16u(addr
, IS_USER(s
));
6365 store_reg(s
, rd
, tmp
);
6367 int label
= gen_new_label();
6369 tmp2
= tcg_temp_local_new_i32();
6370 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6371 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6372 tmp
= load_reg(s
,rm
);
6375 gen_st32(tmp
, addr
, IS_USER(s
));
6377 case 1: /* strexd */
6378 gen_st32(tmp
, addr
, IS_USER(s
));
6379 tcg_gen_addi_i32(addr
, addr
, 4);
6380 tmp
= load_reg(s
, rm
+ 1);
6381 gen_st32(tmp
, addr
, IS_USER(s
));
6383 case 2: /* strexb */
6384 gen_st8(tmp
, addr
, IS_USER(s
));
6386 case 3: /* strexh */
6387 gen_st16(tmp
, addr
, IS_USER(s
));
6392 gen_set_label(label
);
6393 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6394 tcg_temp_free(tmp2
);
6396 tcg_temp_free(addr
);
6398 /* SWP instruction */
6401 /* ??? This is not really atomic. However we know
6402 we never have multiple CPUs running in parallel,
6403 so it is good enough. */
6404 addr
= load_reg(s
, rn
);
6405 tmp
= load_reg(s
, rm
);
6406 if (insn
& (1 << 22)) {
6407 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6408 gen_st8(tmp
, addr
, IS_USER(s
));
6410 tmp2
= gen_ld32(addr
, IS_USER(s
));
6411 gen_st32(tmp
, addr
, IS_USER(s
));
6414 store_reg(s
, rd
, tmp2
);
6420 /* Misc load/store */
6421 rn
= (insn
>> 16) & 0xf;
6422 rd
= (insn
>> 12) & 0xf;
6423 addr
= load_reg(s
, rn
);
6424 if (insn
& (1 << 24))
6425 gen_add_datah_offset(s
, insn
, 0, addr
);
6427 if (insn
& (1 << 20)) {
6431 tmp
= gen_ld16u(addr
, IS_USER(s
));
6434 tmp
= gen_ld8s(addr
, IS_USER(s
));
6438 tmp
= gen_ld16s(addr
, IS_USER(s
));
6442 } else if (sh
& 2) {
6446 tmp
= load_reg(s
, rd
);
6447 gen_st32(tmp
, addr
, IS_USER(s
));
6448 tcg_gen_addi_i32(addr
, addr
, 4);
6449 tmp
= load_reg(s
, rd
+ 1);
6450 gen_st32(tmp
, addr
, IS_USER(s
));
6454 tmp
= gen_ld32(addr
, IS_USER(s
));
6455 store_reg(s
, rd
, tmp
);
6456 tcg_gen_addi_i32(addr
, addr
, 4);
6457 tmp
= gen_ld32(addr
, IS_USER(s
));
6461 address_offset
= -4;
6464 tmp
= load_reg(s
, rd
);
6465 gen_st16(tmp
, addr
, IS_USER(s
));
6468 /* Perform base writeback before the loaded value to
6469 ensure correct behavior with overlapping index registers.
6470 ldrd with base writeback is is undefined if the
6471 destination and index registers overlap. */
6472 if (!(insn
& (1 << 24))) {
6473 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6474 store_reg(s
, rn
, addr
);
6475 } else if (insn
& (1 << 21)) {
6477 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6478 store_reg(s
, rn
, addr
);
6483 /* Complete the load. */
6484 store_reg(s
, rd
, tmp
);
6493 if (insn
& (1 << 4)) {
6495 /* Armv6 Media instructions. */
6497 rn
= (insn
>> 16) & 0xf;
6498 rd
= (insn
>> 12) & 0xf;
6499 rs
= (insn
>> 8) & 0xf;
6500 switch ((insn
>> 23) & 3) {
6501 case 0: /* Parallel add/subtract. */
6502 op1
= (insn
>> 20) & 7;
6503 tmp
= load_reg(s
, rn
);
6504 tmp2
= load_reg(s
, rm
);
6505 sh
= (insn
>> 5) & 7;
6506 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6508 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6510 store_reg(s
, rd
, tmp
);
6513 if ((insn
& 0x00700020) == 0) {
6514 /* Halfword pack. */
6515 tmp
= load_reg(s
, rn
);
6516 tmp2
= load_reg(s
, rm
);
6517 shift
= (insn
>> 7) & 0x1f;
6518 if (insn
& (1 << 6)) {
6522 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6523 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6524 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6528 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6529 tcg_gen_ext16u_i32(tmp
, tmp
);
6530 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6532 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6534 store_reg(s
, rd
, tmp
);
6535 } else if ((insn
& 0x00200020) == 0x00200000) {
6537 tmp
= load_reg(s
, rm
);
6538 shift
= (insn
>> 7) & 0x1f;
6539 if (insn
& (1 << 6)) {
6542 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6544 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6546 sh
= (insn
>> 16) & 0x1f;
6548 if (insn
& (1 << 22))
6549 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6551 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6553 store_reg(s
, rd
, tmp
);
6554 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6556 tmp
= load_reg(s
, rm
);
6557 sh
= (insn
>> 16) & 0x1f;
6559 if (insn
& (1 << 22))
6560 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6562 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6564 store_reg(s
, rd
, tmp
);
6565 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6567 tmp
= load_reg(s
, rn
);
6568 tmp2
= load_reg(s
, rm
);
6570 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6571 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6574 store_reg(s
, rd
, tmp
);
6575 } else if ((insn
& 0x000003e0) == 0x00000060) {
6576 tmp
= load_reg(s
, rm
);
6577 shift
= (insn
>> 10) & 3;
6578 /* ??? In many cases it's not neccessary to do a
6579 rotate, a shift is sufficient. */
6581 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6582 op1
= (insn
>> 20) & 7;
6584 case 0: gen_sxtb16(tmp
); break;
6585 case 2: gen_sxtb(tmp
); break;
6586 case 3: gen_sxth(tmp
); break;
6587 case 4: gen_uxtb16(tmp
); break;
6588 case 6: gen_uxtb(tmp
); break;
6589 case 7: gen_uxth(tmp
); break;
6590 default: goto illegal_op
;
6593 tmp2
= load_reg(s
, rn
);
6594 if ((op1
& 3) == 0) {
6595 gen_add16(tmp
, tmp2
);
6597 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6601 store_reg(s
, rd
, tmp
);
6602 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6604 tmp
= load_reg(s
, rm
);
6605 if (insn
& (1 << 22)) {
6606 if (insn
& (1 << 7)) {
6610 gen_helper_rbit(tmp
, tmp
);
6613 if (insn
& (1 << 7))
6616 tcg_gen_bswap32_i32(tmp
, tmp
);
6618 store_reg(s
, rd
, tmp
);
6623 case 2: /* Multiplies (Type 3). */
6624 tmp
= load_reg(s
, rm
);
6625 tmp2
= load_reg(s
, rs
);
6626 if (insn
& (1 << 20)) {
6627 /* Signed multiply most significant [accumulate]. */
6628 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6629 if (insn
& (1 << 5))
6630 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6631 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6633 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6635 tmp2
= load_reg(s
, rd
);
6636 if (insn
& (1 << 6)) {
6637 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6639 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6643 store_reg(s
, rn
, tmp
);
6645 if (insn
& (1 << 5))
6646 gen_swap_half(tmp2
);
6647 gen_smul_dual(tmp
, tmp2
);
6648 /* This addition cannot overflow. */
6649 if (insn
& (1 << 6)) {
6650 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6652 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6655 if (insn
& (1 << 22)) {
6656 /* smlald, smlsld */
6657 tmp64
= tcg_temp_new_i64();
6658 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6660 gen_addq(s
, tmp64
, rd
, rn
);
6661 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6663 /* smuad, smusd, smlad, smlsd */
6666 tmp2
= load_reg(s
, rd
);
6667 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6670 store_reg(s
, rn
, tmp
);
6675 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6677 case 0: /* Unsigned sum of absolute differences. */
6679 tmp
= load_reg(s
, rm
);
6680 tmp2
= load_reg(s
, rs
);
6681 gen_helper_usad8(tmp
, tmp
, tmp2
);
6684 tmp2
= load_reg(s
, rd
);
6685 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6688 store_reg(s
, rn
, tmp
);
6690 case 0x20: case 0x24: case 0x28: case 0x2c:
6691 /* Bitfield insert/clear. */
6693 shift
= (insn
>> 7) & 0x1f;
6694 i
= (insn
>> 16) & 0x1f;
6698 tcg_gen_movi_i32(tmp
, 0);
6700 tmp
= load_reg(s
, rm
);
6703 tmp2
= load_reg(s
, rd
);
6704 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6707 store_reg(s
, rd
, tmp
);
6709 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6710 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6712 tmp
= load_reg(s
, rm
);
6713 shift
= (insn
>> 7) & 0x1f;
6714 i
= ((insn
>> 16) & 0x1f) + 1;
6719 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6721 gen_sbfx(tmp
, shift
, i
);
6724 store_reg(s
, rd
, tmp
);
6734 /* Check for undefined extension instructions
6735 * per the ARM Bible IE:
6736 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6738 sh
= (0xf << 20) | (0xf << 4);
6739 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6743 /* load/store byte/word */
6744 rn
= (insn
>> 16) & 0xf;
6745 rd
= (insn
>> 12) & 0xf;
6746 tmp2
= load_reg(s
, rn
);
6747 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6748 if (insn
& (1 << 24))
6749 gen_add_data_offset(s
, insn
, tmp2
);
6750 if (insn
& (1 << 20)) {
6752 if (insn
& (1 << 22)) {
6753 tmp
= gen_ld8u(tmp2
, i
);
6755 tmp
= gen_ld32(tmp2
, i
);
6759 tmp
= load_reg(s
, rd
);
6760 if (insn
& (1 << 22))
6761 gen_st8(tmp
, tmp2
, i
);
6763 gen_st32(tmp
, tmp2
, i
);
6765 if (!(insn
& (1 << 24))) {
6766 gen_add_data_offset(s
, insn
, tmp2
);
6767 store_reg(s
, rn
, tmp2
);
6768 } else if (insn
& (1 << 21)) {
6769 store_reg(s
, rn
, tmp2
);
6773 if (insn
& (1 << 20)) {
6774 /* Complete the load. */
6778 store_reg(s
, rd
, tmp
);
6784 int j
, n
, user
, loaded_base
;
6786 /* load/store multiple words */
6787 /* XXX: store correct base if write back */
6789 if (insn
& (1 << 22)) {
6791 goto illegal_op
; /* only usable in supervisor mode */
6793 if ((insn
& (1 << 15)) == 0)
6796 rn
= (insn
>> 16) & 0xf;
6797 addr
= load_reg(s
, rn
);
6799 /* compute total size */
6801 TCGV_UNUSED(loaded_var
);
6804 if (insn
& (1 << i
))
6807 /* XXX: test invalid n == 0 case ? */
6808 if (insn
& (1 << 23)) {
6809 if (insn
& (1 << 24)) {
6811 tcg_gen_addi_i32(addr
, addr
, 4);
6813 /* post increment */
6816 if (insn
& (1 << 24)) {
6818 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6820 /* post decrement */
6822 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6827 if (insn
& (1 << i
)) {
6828 if (insn
& (1 << 20)) {
6830 tmp
= gen_ld32(addr
, IS_USER(s
));
6834 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6836 } else if (i
== rn
) {
6840 store_reg(s
, i
, tmp
);
6845 /* special case: r15 = PC + 8 */
6846 val
= (long)s
->pc
+ 4;
6848 tcg_gen_movi_i32(tmp
, val
);
6851 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6853 tmp
= load_reg(s
, i
);
6855 gen_st32(tmp
, addr
, IS_USER(s
));
6858 /* no need to add after the last transfer */
6860 tcg_gen_addi_i32(addr
, addr
, 4);
6863 if (insn
& (1 << 21)) {
6865 if (insn
& (1 << 23)) {
6866 if (insn
& (1 << 24)) {
6869 /* post increment */
6870 tcg_gen_addi_i32(addr
, addr
, 4);
6873 if (insn
& (1 << 24)) {
6876 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6878 /* post decrement */
6879 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6882 store_reg(s
, rn
, addr
);
6887 store_reg(s
, rn
, loaded_var
);
6889 if ((insn
& (1 << 22)) && !user
) {
6890 /* Restore CPSR from SPSR. */
6891 tmp
= load_cpu_field(spsr
);
6892 gen_set_cpsr(tmp
, 0xffffffff);
6894 s
->is_jmp
= DISAS_UPDATE
;
6903 /* branch (and link) */
6904 val
= (int32_t)s
->pc
;
6905 if (insn
& (1 << 24)) {
6907 tcg_gen_movi_i32(tmp
, val
);
6908 store_reg(s
, 14, tmp
);
6910 offset
= (((int32_t)insn
<< 8) >> 8);
6911 val
+= (offset
<< 2) + 4;
6919 if (disas_coproc_insn(env
, s
, insn
))
6924 gen_set_pc_im(s
->pc
);
6925 s
->is_jmp
= DISAS_SWI
;
6929 gen_set_condexec(s
);
6930 gen_set_pc_im(s
->pc
- 4);
6931 gen_exception(EXCP_UDEF
);
6932 s
->is_jmp
= DISAS_JUMP
;
6938 /* Return true if this is a Thumb-2 logical op. */
6940 thumb2_logic_op(int op
)
6945 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6946 then set condition code flags based on the result of the operation.
6947 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6948 to the high bit of T1.
6949 Returns zero if the opcode is valid. */
6952 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
6959 tcg_gen_and_i32(t0
, t0
, t1
);
6963 tcg_gen_bic_i32(t0
, t0
, t1
);
6967 tcg_gen_or_i32(t0
, t0
, t1
);
6971 tcg_gen_not_i32(t1
, t1
);
6972 tcg_gen_or_i32(t0
, t0
, t1
);
6976 tcg_gen_xor_i32(t0
, t0
, t1
);
6981 gen_helper_add_cc(t0
, t0
, t1
);
6983 tcg_gen_add_i32(t0
, t0
, t1
);
6987 gen_helper_adc_cc(t0
, t0
, t1
);
6993 gen_helper_sbc_cc(t0
, t0
, t1
);
6995 gen_sub_carry(t0
, t0
, t1
);
6999 gen_helper_sub_cc(t0
, t0
, t1
);
7001 tcg_gen_sub_i32(t0
, t0
, t1
);
7005 gen_helper_sub_cc(t0
, t1
, t0
);
7007 tcg_gen_sub_i32(t0
, t1
, t0
);
7009 default: /* 5, 6, 7, 9, 12, 15. */
7015 gen_set_CF_bit31(t1
);
7020 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7022 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7024 uint32_t insn
, imm
, shift
, offset
;
7025 uint32_t rd
, rn
, rm
, rs
;
7036 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7037 || arm_feature (env
, ARM_FEATURE_M
))) {
7038 /* Thumb-1 cores may need to treat bl and blx as a pair of
7039 16-bit instructions to get correct prefetch abort behavior. */
7041 if ((insn
& (1 << 12)) == 0) {
7042 /* Second half of blx. */
7043 offset
= ((insn
& 0x7ff) << 1);
7044 tmp
= load_reg(s
, 14);
7045 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7046 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7049 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7050 store_reg(s
, 14, tmp2
);
7054 if (insn
& (1 << 11)) {
7055 /* Second half of bl. */
7056 offset
= ((insn
& 0x7ff) << 1) | 1;
7057 tmp
= load_reg(s
, 14);
7058 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7061 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7062 store_reg(s
, 14, tmp2
);
7066 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7067 /* Instruction spans a page boundary. Implement it as two
7068 16-bit instructions in case the second half causes an
7070 offset
= ((int32_t)insn
<< 21) >> 9;
7071 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7074 /* Fall through to 32-bit decode. */
7077 insn
= lduw_code(s
->pc
);
7079 insn
|= (uint32_t)insn_hw1
<< 16;
7081 if ((insn
& 0xf800e800) != 0xf000e800) {
7085 rn
= (insn
>> 16) & 0xf;
7086 rs
= (insn
>> 12) & 0xf;
7087 rd
= (insn
>> 8) & 0xf;
7089 switch ((insn
>> 25) & 0xf) {
7090 case 0: case 1: case 2: case 3:
7091 /* 16-bit instructions. Should never happen. */
7094 if (insn
& (1 << 22)) {
7095 /* Other load/store, table branch. */
7096 if (insn
& 0x01200000) {
7097 /* Load/store doubleword. */
7100 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7102 addr
= load_reg(s
, rn
);
7104 offset
= (insn
& 0xff) * 4;
7105 if ((insn
& (1 << 23)) == 0)
7107 if (insn
& (1 << 24)) {
7108 tcg_gen_addi_i32(addr
, addr
, offset
);
7111 if (insn
& (1 << 20)) {
7113 tmp
= gen_ld32(addr
, IS_USER(s
));
7114 store_reg(s
, rs
, tmp
);
7115 tcg_gen_addi_i32(addr
, addr
, 4);
7116 tmp
= gen_ld32(addr
, IS_USER(s
));
7117 store_reg(s
, rd
, tmp
);
7120 tmp
= load_reg(s
, rs
);
7121 gen_st32(tmp
, addr
, IS_USER(s
));
7122 tcg_gen_addi_i32(addr
, addr
, 4);
7123 tmp
= load_reg(s
, rd
);
7124 gen_st32(tmp
, addr
, IS_USER(s
));
7126 if (insn
& (1 << 21)) {
7127 /* Base writeback. */
7130 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7131 store_reg(s
, rn
, addr
);
7135 } else if ((insn
& (1 << 23)) == 0) {
7136 /* Load/store exclusive word. */
7137 addr
= tcg_temp_local_new();
7138 load_reg_var(s
, addr
, rn
);
7139 if (insn
& (1 << 20)) {
7140 gen_helper_mark_exclusive(cpu_env
, addr
);
7141 tmp
= gen_ld32(addr
, IS_USER(s
));
7142 store_reg(s
, rd
, tmp
);
7144 int label
= gen_new_label();
7145 tmp2
= tcg_temp_local_new();
7146 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7147 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7148 tmp
= load_reg(s
, rs
);
7149 gen_st32(tmp
, addr
, IS_USER(s
));
7150 gen_set_label(label
);
7151 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7152 tcg_temp_free(tmp2
);
7154 tcg_temp_free(addr
);
7155 } else if ((insn
& (1 << 6)) == 0) {
7159 tcg_gen_movi_i32(addr
, s
->pc
);
7161 addr
= load_reg(s
, rn
);
7163 tmp
= load_reg(s
, rm
);
7164 tcg_gen_add_i32(addr
, addr
, tmp
);
7165 if (insn
& (1 << 4)) {
7167 tcg_gen_add_i32(addr
, addr
, tmp
);
7169 tmp
= gen_ld16u(addr
, IS_USER(s
));
7172 tmp
= gen_ld8u(addr
, IS_USER(s
));
7175 tcg_gen_shli_i32(tmp
, tmp
, 1);
7176 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7177 store_reg(s
, 15, tmp
);
7179 /* Load/store exclusive byte/halfword/doubleword. */
7180 /* ??? These are not really atomic. However we know
7181 we never have multiple CPUs running in parallel,
7182 so it is good enough. */
7183 op
= (insn
>> 4) & 0x3;
7184 addr
= tcg_temp_local_new();
7185 load_reg_var(s
, addr
, rn
);
7186 if (insn
& (1 << 20)) {
7187 gen_helper_mark_exclusive(cpu_env
, addr
);
7190 tmp
= gen_ld8u(addr
, IS_USER(s
));
7193 tmp
= gen_ld16u(addr
, IS_USER(s
));
7196 tmp
= gen_ld32(addr
, IS_USER(s
));
7197 tcg_gen_addi_i32(addr
, addr
, 4);
7198 tmp2
= gen_ld32(addr
, IS_USER(s
));
7199 store_reg(s
, rd
, tmp2
);
7204 store_reg(s
, rs
, tmp
);
7206 int label
= gen_new_label();
7207 tmp2
= tcg_temp_local_new();
7208 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7209 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7210 tmp
= load_reg(s
, rs
);
7213 gen_st8(tmp
, addr
, IS_USER(s
));
7216 gen_st16(tmp
, addr
, IS_USER(s
));
7219 gen_st32(tmp
, addr
, IS_USER(s
));
7220 tcg_gen_addi_i32(addr
, addr
, 4);
7221 tmp
= load_reg(s
, rd
);
7222 gen_st32(tmp
, addr
, IS_USER(s
));
7227 gen_set_label(label
);
7228 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7229 tcg_temp_free(tmp2
);
7231 tcg_temp_free(addr
);
7234 /* Load/store multiple, RFE, SRS. */
7235 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7236 /* Not available in user mode. */
7239 if (insn
& (1 << 20)) {
7241 addr
= load_reg(s
, rn
);
7242 if ((insn
& (1 << 24)) == 0)
7243 tcg_gen_addi_i32(addr
, addr
, -8);
7244 /* Load PC into tmp and CPSR into tmp2. */
7245 tmp
= gen_ld32(addr
, 0);
7246 tcg_gen_addi_i32(addr
, addr
, 4);
7247 tmp2
= gen_ld32(addr
, 0);
7248 if (insn
& (1 << 21)) {
7249 /* Base writeback. */
7250 if (insn
& (1 << 24)) {
7251 tcg_gen_addi_i32(addr
, addr
, 4);
7253 tcg_gen_addi_i32(addr
, addr
, -4);
7255 store_reg(s
, rn
, addr
);
7259 gen_rfe(s
, tmp
, tmp2
);
7263 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7264 addr
= load_reg(s
, 13);
7267 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7269 if ((insn
& (1 << 24)) == 0) {
7270 tcg_gen_addi_i32(addr
, addr
, -8);
7272 tmp
= load_reg(s
, 14);
7273 gen_st32(tmp
, addr
, 0);
7274 tcg_gen_addi_i32(addr
, addr
, 4);
7276 gen_helper_cpsr_read(tmp
);
7277 gen_st32(tmp
, addr
, 0);
7278 if (insn
& (1 << 21)) {
7279 if ((insn
& (1 << 24)) == 0) {
7280 tcg_gen_addi_i32(addr
, addr
, -4);
7282 tcg_gen_addi_i32(addr
, addr
, 4);
7284 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7285 store_reg(s
, 13, addr
);
7287 gen_helper_set_r13_banked(cpu_env
,
7288 tcg_const_i32(op
), addr
);
7296 /* Load/store multiple. */
7297 addr
= load_reg(s
, rn
);
7299 for (i
= 0; i
< 16; i
++) {
7300 if (insn
& (1 << i
))
7303 if (insn
& (1 << 24)) {
7304 tcg_gen_addi_i32(addr
, addr
, -offset
);
7307 for (i
= 0; i
< 16; i
++) {
7308 if ((insn
& (1 << i
)) == 0)
7310 if (insn
& (1 << 20)) {
7312 tmp
= gen_ld32(addr
, IS_USER(s
));
7316 store_reg(s
, i
, tmp
);
7320 tmp
= load_reg(s
, i
);
7321 gen_st32(tmp
, addr
, IS_USER(s
));
7323 tcg_gen_addi_i32(addr
, addr
, 4);
7325 if (insn
& (1 << 21)) {
7326 /* Base register writeback. */
7327 if (insn
& (1 << 24)) {
7328 tcg_gen_addi_i32(addr
, addr
, -offset
);
7330 /* Fault if writeback register is in register list. */
7331 if (insn
& (1 << rn
))
7333 store_reg(s
, rn
, addr
);
7340 case 5: /* Data processing register constant shift. */
7343 tcg_gen_movi_i32(tmp
, 0);
7345 tmp
= load_reg(s
, rn
);
7347 tmp2
= load_reg(s
, rm
);
7348 op
= (insn
>> 21) & 0xf;
7349 shiftop
= (insn
>> 4) & 3;
7350 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7351 conds
= (insn
& (1 << 20)) != 0;
7352 logic_cc
= (conds
&& thumb2_logic_op(op
));
7353 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7354 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7358 store_reg(s
, rd
, tmp
);
7363 case 13: /* Misc data processing. */
7364 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7365 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7368 case 0: /* Register controlled shift. */
7369 tmp
= load_reg(s
, rn
);
7370 tmp2
= load_reg(s
, rm
);
7371 if ((insn
& 0x70) != 0)
7373 op
= (insn
>> 21) & 3;
7374 logic_cc
= (insn
& (1 << 20)) != 0;
7375 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7378 store_reg_bx(env
, s
, rd
, tmp
);
7380 case 1: /* Sign/zero extend. */
7381 tmp
= load_reg(s
, rm
);
7382 shift
= (insn
>> 4) & 3;
7383 /* ??? In many cases it's not neccessary to do a
7384 rotate, a shift is sufficient. */
7386 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7387 op
= (insn
>> 20) & 7;
7389 case 0: gen_sxth(tmp
); break;
7390 case 1: gen_uxth(tmp
); break;
7391 case 2: gen_sxtb16(tmp
); break;
7392 case 3: gen_uxtb16(tmp
); break;
7393 case 4: gen_sxtb(tmp
); break;
7394 case 5: gen_uxtb(tmp
); break;
7395 default: goto illegal_op
;
7398 tmp2
= load_reg(s
, rn
);
7399 if ((op
>> 1) == 1) {
7400 gen_add16(tmp
, tmp2
);
7402 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7406 store_reg(s
, rd
, tmp
);
7408 case 2: /* SIMD add/subtract. */
7409 op
= (insn
>> 20) & 7;
7410 shift
= (insn
>> 4) & 7;
7411 if ((op
& 3) == 3 || (shift
& 3) == 3)
7413 tmp
= load_reg(s
, rn
);
7414 tmp2
= load_reg(s
, rm
);
7415 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7417 store_reg(s
, rd
, tmp
);
7419 case 3: /* Other data processing. */
7420 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7422 /* Saturating add/subtract. */
7423 tmp
= load_reg(s
, rn
);
7424 tmp2
= load_reg(s
, rm
);
7426 gen_helper_double_saturate(tmp
, tmp
);
7428 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7430 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7433 tmp
= load_reg(s
, rn
);
7435 case 0x0a: /* rbit */
7436 gen_helper_rbit(tmp
, tmp
);
7438 case 0x08: /* rev */
7439 tcg_gen_bswap32_i32(tmp
, tmp
);
7441 case 0x09: /* rev16 */
7444 case 0x0b: /* revsh */
7447 case 0x10: /* sel */
7448 tmp2
= load_reg(s
, rm
);
7450 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7451 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7455 case 0x18: /* clz */
7456 gen_helper_clz(tmp
, tmp
);
7462 store_reg(s
, rd
, tmp
);
7464 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7465 op
= (insn
>> 4) & 0xf;
7466 tmp
= load_reg(s
, rn
);
7467 tmp2
= load_reg(s
, rm
);
7468 switch ((insn
>> 20) & 7) {
7469 case 0: /* 32 x 32 -> 32 */
7470 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7473 tmp2
= load_reg(s
, rs
);
7475 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7477 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7481 case 1: /* 16 x 16 -> 32 */
7482 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7485 tmp2
= load_reg(s
, rs
);
7486 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7490 case 2: /* Dual multiply add. */
7491 case 4: /* Dual multiply subtract. */
7493 gen_swap_half(tmp2
);
7494 gen_smul_dual(tmp
, tmp2
);
7495 /* This addition cannot overflow. */
7496 if (insn
& (1 << 22)) {
7497 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7499 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7504 tmp2
= load_reg(s
, rs
);
7505 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7509 case 3: /* 32 * 16 -> 32msb */
7511 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7514 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7515 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7517 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7520 tmp2
= load_reg(s
, rs
);
7521 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7525 case 5: case 6: /* 32 * 32 -> 32msb */
7526 gen_imull(tmp
, tmp2
);
7527 if (insn
& (1 << 5)) {
7528 gen_roundqd(tmp
, tmp2
);
7535 tmp2
= load_reg(s
, rs
);
7536 if (insn
& (1 << 21)) {
7537 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7539 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7544 case 7: /* Unsigned sum of absolute differences. */
7545 gen_helper_usad8(tmp
, tmp
, tmp2
);
7548 tmp2
= load_reg(s
, rs
);
7549 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7554 store_reg(s
, rd
, tmp
);
7556 case 6: case 7: /* 64-bit multiply, Divide. */
7557 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7558 tmp
= load_reg(s
, rn
);
7559 tmp2
= load_reg(s
, rm
);
7560 if ((op
& 0x50) == 0x10) {
7562 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7565 gen_helper_udiv(tmp
, tmp
, tmp2
);
7567 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7569 store_reg(s
, rd
, tmp
);
7570 } else if ((op
& 0xe) == 0xc) {
7571 /* Dual multiply accumulate long. */
7573 gen_swap_half(tmp2
);
7574 gen_smul_dual(tmp
, tmp2
);
7576 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7578 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7582 tmp64
= tcg_temp_new_i64();
7583 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7585 gen_addq(s
, tmp64
, rs
, rd
);
7586 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7589 /* Unsigned 64-bit multiply */
7590 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7594 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7596 tmp64
= tcg_temp_new_i64();
7597 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7600 /* Signed 64-bit multiply */
7601 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7606 gen_addq_lo(s
, tmp64
, rs
);
7607 gen_addq_lo(s
, tmp64
, rd
);
7608 } else if (op
& 0x40) {
7609 /* 64-bit accumulate. */
7610 gen_addq(s
, tmp64
, rs
, rd
);
7612 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7617 case 6: case 7: case 14: case 15:
7619 if (((insn
>> 24) & 3) == 3) {
7620 /* Translate into the equivalent ARM encoding. */
7621 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7622 if (disas_neon_data_insn(env
, s
, insn
))
7625 if (insn
& (1 << 28))
7627 if (disas_coproc_insn (env
, s
, insn
))
7631 case 8: case 9: case 10: case 11:
7632 if (insn
& (1 << 15)) {
7633 /* Branches, misc control. */
7634 if (insn
& 0x5000) {
7635 /* Unconditional branch. */
7636 /* signextend(hw1[10:0]) -> offset[:12]. */
7637 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7638 /* hw1[10:0] -> offset[11:1]. */
7639 offset
|= (insn
& 0x7ff) << 1;
7640 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7641 offset[24:22] already have the same value because of the
7642 sign extension above. */
7643 offset
^= ((~insn
) & (1 << 13)) << 10;
7644 offset
^= ((~insn
) & (1 << 11)) << 11;
7646 if (insn
& (1 << 14)) {
7647 /* Branch and link. */
7648 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7652 if (insn
& (1 << 12)) {
7657 offset
&= ~(uint32_t)2;
7658 gen_bx_im(s
, offset
);
7660 } else if (((insn
>> 23) & 7) == 7) {
7662 if (insn
& (1 << 13))
7665 if (insn
& (1 << 26)) {
7666 /* Secure monitor call (v6Z) */
7667 goto illegal_op
; /* not implemented. */
7669 op
= (insn
>> 20) & 7;
7671 case 0: /* msr cpsr. */
7673 tmp
= load_reg(s
, rn
);
7674 addr
= tcg_const_i32(insn
& 0xff);
7675 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7680 case 1: /* msr spsr. */
7683 tmp
= load_reg(s
, rn
);
7685 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7689 case 2: /* cps, nop-hint. */
7690 if (((insn
>> 8) & 7) == 0) {
7691 gen_nop_hint(s
, insn
& 0xff);
7693 /* Implemented as NOP in user mode. */
7698 if (insn
& (1 << 10)) {
7699 if (insn
& (1 << 7))
7701 if (insn
& (1 << 6))
7703 if (insn
& (1 << 5))
7705 if (insn
& (1 << 9))
7706 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7708 if (insn
& (1 << 8)) {
7710 imm
|= (insn
& 0x1f);
7713 gen_set_psr_im(s
, offset
, 0, imm
);
7716 case 3: /* Special control operations. */
7717 op
= (insn
>> 4) & 0xf;
7720 gen_helper_clrex(cpu_env
);
7725 /* These execute as NOPs. */
7733 /* Trivial implementation equivalent to bx. */
7734 tmp
= load_reg(s
, rn
);
7737 case 5: /* Exception return. */
7738 /* Unpredictable in user mode. */
7740 case 6: /* mrs cpsr. */
7743 addr
= tcg_const_i32(insn
& 0xff);
7744 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7746 gen_helper_cpsr_read(tmp
);
7748 store_reg(s
, rd
, tmp
);
7750 case 7: /* mrs spsr. */
7751 /* Not accessible in user mode. */
7752 if (IS_USER(s
) || IS_M(env
))
7754 tmp
= load_cpu_field(spsr
);
7755 store_reg(s
, rd
, tmp
);
7760 /* Conditional branch. */
7761 op
= (insn
>> 22) & 0xf;
7762 /* Generate a conditional jump to next instruction. */
7763 s
->condlabel
= gen_new_label();
7764 gen_test_cc(op
^ 1, s
->condlabel
);
7767 /* offset[11:1] = insn[10:0] */
7768 offset
= (insn
& 0x7ff) << 1;
7769 /* offset[17:12] = insn[21:16]. */
7770 offset
|= (insn
& 0x003f0000) >> 4;
7771 /* offset[31:20] = insn[26]. */
7772 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7773 /* offset[18] = insn[13]. */
7774 offset
|= (insn
& (1 << 13)) << 5;
7775 /* offset[19] = insn[11]. */
7776 offset
|= (insn
& (1 << 11)) << 8;
7778 /* jump to the offset */
7779 gen_jmp(s
, s
->pc
+ offset
);
7782 /* Data processing immediate. */
7783 if (insn
& (1 << 25)) {
7784 if (insn
& (1 << 24)) {
7785 if (insn
& (1 << 20))
7787 /* Bitfield/Saturate. */
7788 op
= (insn
>> 21) & 7;
7790 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7793 tcg_gen_movi_i32(tmp
, 0);
7795 tmp
= load_reg(s
, rn
);
7798 case 2: /* Signed bitfield extract. */
7800 if (shift
+ imm
> 32)
7803 gen_sbfx(tmp
, shift
, imm
);
7805 case 6: /* Unsigned bitfield extract. */
7807 if (shift
+ imm
> 32)
7810 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7812 case 3: /* Bitfield insert/clear. */
7815 imm
= imm
+ 1 - shift
;
7817 tmp2
= load_reg(s
, rd
);
7818 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7824 default: /* Saturate. */
7827 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7829 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7831 tmp2
= tcg_const_i32(imm
);
7834 if ((op
& 1) && shift
== 0)
7835 gen_helper_usat16(tmp
, tmp
, tmp2
);
7837 gen_helper_usat(tmp
, tmp
, tmp2
);
7840 if ((op
& 1) && shift
== 0)
7841 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7843 gen_helper_ssat(tmp
, tmp
, tmp2
);
7847 store_reg(s
, rd
, tmp
);
7849 imm
= ((insn
& 0x04000000) >> 15)
7850 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7851 if (insn
& (1 << 22)) {
7852 /* 16-bit immediate. */
7853 imm
|= (insn
>> 4) & 0xf000;
7854 if (insn
& (1 << 23)) {
7856 tmp
= load_reg(s
, rd
);
7857 tcg_gen_ext16u_i32(tmp
, tmp
);
7858 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7862 tcg_gen_movi_i32(tmp
, imm
);
7865 /* Add/sub 12-bit immediate. */
7867 offset
= s
->pc
& ~(uint32_t)3;
7868 if (insn
& (1 << 23))
7873 tcg_gen_movi_i32(tmp
, offset
);
7875 tmp
= load_reg(s
, rn
);
7876 if (insn
& (1 << 23))
7877 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7879 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7882 store_reg(s
, rd
, tmp
);
7885 int shifter_out
= 0;
7886 /* modified 12-bit immediate. */
7887 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7888 imm
= (insn
& 0xff);
7891 /* Nothing to do. */
7893 case 1: /* 00XY00XY */
7896 case 2: /* XY00XY00 */
7900 case 3: /* XYXYXYXY */
7904 default: /* Rotated constant. */
7905 shift
= (shift
<< 1) | (imm
>> 7);
7907 imm
= imm
<< (32 - shift
);
7912 tcg_gen_movi_i32(tmp2
, imm
);
7913 rn
= (insn
>> 16) & 0xf;
7916 tcg_gen_movi_i32(tmp
, 0);
7918 tmp
= load_reg(s
, rn
);
7920 op
= (insn
>> 21) & 0xf;
7921 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7922 shifter_out
, tmp
, tmp2
))
7925 rd
= (insn
>> 8) & 0xf;
7927 store_reg(s
, rd
, tmp
);
7934 case 12: /* Load/store single data item. */
7939 if ((insn
& 0x01100000) == 0x01000000) {
7940 if (disas_neon_ls_insn(env
, s
, insn
))
7948 /* s->pc has already been incremented by 4. */
7949 imm
= s
->pc
& 0xfffffffc;
7950 if (insn
& (1 << 23))
7951 imm
+= insn
& 0xfff;
7953 imm
-= insn
& 0xfff;
7954 tcg_gen_movi_i32(addr
, imm
);
7956 addr
= load_reg(s
, rn
);
7957 if (insn
& (1 << 23)) {
7958 /* Positive offset. */
7960 tcg_gen_addi_i32(addr
, addr
, imm
);
7962 op
= (insn
>> 8) & 7;
7965 case 0: case 8: /* Shifted Register. */
7966 shift
= (insn
>> 4) & 0xf;
7969 tmp
= load_reg(s
, rm
);
7971 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7972 tcg_gen_add_i32(addr
, addr
, tmp
);
7975 case 4: /* Negative offset. */
7976 tcg_gen_addi_i32(addr
, addr
, -imm
);
7978 case 6: /* User privilege. */
7979 tcg_gen_addi_i32(addr
, addr
, imm
);
7982 case 1: /* Post-decrement. */
7985 case 3: /* Post-increment. */
7989 case 5: /* Pre-decrement. */
7992 case 7: /* Pre-increment. */
7993 tcg_gen_addi_i32(addr
, addr
, imm
);
8001 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8002 if (insn
& (1 << 20)) {
8004 if (rs
== 15 && op
!= 2) {
8007 /* Memory hint. Implemented as NOP. */
8010 case 0: tmp
= gen_ld8u(addr
, user
); break;
8011 case 4: tmp
= gen_ld8s(addr
, user
); break;
8012 case 1: tmp
= gen_ld16u(addr
, user
); break;
8013 case 5: tmp
= gen_ld16s(addr
, user
); break;
8014 case 2: tmp
= gen_ld32(addr
, user
); break;
8015 default: goto illegal_op
;
8020 store_reg(s
, rs
, tmp
);
8027 tmp
= load_reg(s
, rs
);
8029 case 0: gen_st8(tmp
, addr
, user
); break;
8030 case 1: gen_st16(tmp
, addr
, user
); break;
8031 case 2: gen_st32(tmp
, addr
, user
); break;
8032 default: goto illegal_op
;
8036 tcg_gen_addi_i32(addr
, addr
, imm
);
8038 store_reg(s
, rn
, addr
);
8052 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8054 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8061 if (s
->condexec_mask
) {
8062 cond
= s
->condexec_cond
;
8063 s
->condlabel
= gen_new_label();
8064 gen_test_cc(cond
^ 1, s
->condlabel
);
8068 insn
= lduw_code(s
->pc
);
8071 switch (insn
>> 12) {
8075 op
= (insn
>> 11) & 3;
8078 rn
= (insn
>> 3) & 7;
8079 tmp
= load_reg(s
, rn
);
8080 if (insn
& (1 << 10)) {
8083 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8086 rm
= (insn
>> 6) & 7;
8087 tmp2
= load_reg(s
, rm
);
8089 if (insn
& (1 << 9)) {
8090 if (s
->condexec_mask
)
8091 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8093 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8095 if (s
->condexec_mask
)
8096 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8098 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8101 store_reg(s
, rd
, tmp
);
8103 /* shift immediate */
8104 rm
= (insn
>> 3) & 7;
8105 shift
= (insn
>> 6) & 0x1f;
8106 tmp
= load_reg(s
, rm
);
8107 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8108 if (!s
->condexec_mask
)
8110 store_reg(s
, rd
, tmp
);
8114 /* arithmetic large immediate */
8115 op
= (insn
>> 11) & 3;
8116 rd
= (insn
>> 8) & 0x7;
8117 if (op
== 0) { /* mov */
8119 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8120 if (!s
->condexec_mask
)
8122 store_reg(s
, rd
, tmp
);
8124 tmp
= load_reg(s
, rd
);
8126 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8129 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8134 if (s
->condexec_mask
)
8135 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8137 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8139 store_reg(s
, rd
, tmp
);
8142 if (s
->condexec_mask
)
8143 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8145 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8147 store_reg(s
, rd
, tmp
);
8153 if (insn
& (1 << 11)) {
8154 rd
= (insn
>> 8) & 7;
8155 /* load pc-relative. Bit 1 of PC is ignored. */
8156 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8157 val
&= ~(uint32_t)2;
8159 tcg_gen_movi_i32(addr
, val
);
8160 tmp
= gen_ld32(addr
, IS_USER(s
));
8162 store_reg(s
, rd
, tmp
);
8165 if (insn
& (1 << 10)) {
8166 /* data processing extended or blx */
8167 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8168 rm
= (insn
>> 3) & 0xf;
8169 op
= (insn
>> 8) & 3;
8172 tmp
= load_reg(s
, rd
);
8173 tmp2
= load_reg(s
, rm
);
8174 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8176 store_reg(s
, rd
, tmp
);
8179 tmp
= load_reg(s
, rd
);
8180 tmp2
= load_reg(s
, rm
);
8181 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8185 case 2: /* mov/cpy */
8186 tmp
= load_reg(s
, rm
);
8187 store_reg(s
, rd
, tmp
);
8189 case 3:/* branch [and link] exchange thumb register */
8190 tmp
= load_reg(s
, rm
);
8191 if (insn
& (1 << 7)) {
8192 val
= (uint32_t)s
->pc
| 1;
8194 tcg_gen_movi_i32(tmp2
, val
);
8195 store_reg(s
, 14, tmp2
);
8203 /* data processing register */
8205 rm
= (insn
>> 3) & 7;
8206 op
= (insn
>> 6) & 0xf;
8207 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8208 /* the shift/rotate ops want the operands backwards */
8217 if (op
== 9) { /* neg */
8219 tcg_gen_movi_i32(tmp
, 0);
8220 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8221 tmp
= load_reg(s
, rd
);
8226 tmp2
= load_reg(s
, rm
);
8229 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8230 if (!s
->condexec_mask
)
8234 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8235 if (!s
->condexec_mask
)
8239 if (s
->condexec_mask
) {
8240 gen_helper_shl(tmp2
, tmp2
, tmp
);
8242 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8247 if (s
->condexec_mask
) {
8248 gen_helper_shr(tmp2
, tmp2
, tmp
);
8250 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8255 if (s
->condexec_mask
) {
8256 gen_helper_sar(tmp2
, tmp2
, tmp
);
8258 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8263 if (s
->condexec_mask
)
8266 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8269 if (s
->condexec_mask
)
8270 gen_sub_carry(tmp
, tmp
, tmp2
);
8272 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8275 if (s
->condexec_mask
) {
8276 gen_helper_ror(tmp2
, tmp2
, tmp
);
8278 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8283 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8288 if (s
->condexec_mask
)
8289 tcg_gen_neg_i32(tmp
, tmp2
);
8291 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8294 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8298 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8302 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8303 if (!s
->condexec_mask
)
8307 gen_mull(tmp
, tmp2
);
8308 if (!s
->condexec_mask
)
8312 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8313 if (!s
->condexec_mask
)
8317 tcg_gen_not_i32(tmp2
, tmp2
);
8318 if (!s
->condexec_mask
)
8326 store_reg(s
, rm
, tmp2
);
8330 store_reg(s
, rd
, tmp
);
8340 /* load/store register offset. */
8342 rn
= (insn
>> 3) & 7;
8343 rm
= (insn
>> 6) & 7;
8344 op
= (insn
>> 9) & 7;
8345 addr
= load_reg(s
, rn
);
8346 tmp
= load_reg(s
, rm
);
8347 tcg_gen_add_i32(addr
, addr
, tmp
);
8350 if (op
< 3) /* store */
8351 tmp
= load_reg(s
, rd
);
8355 gen_st32(tmp
, addr
, IS_USER(s
));
8358 gen_st16(tmp
, addr
, IS_USER(s
));
8361 gen_st8(tmp
, addr
, IS_USER(s
));
8364 tmp
= gen_ld8s(addr
, IS_USER(s
));
8367 tmp
= gen_ld32(addr
, IS_USER(s
));
8370 tmp
= gen_ld16u(addr
, IS_USER(s
));
8373 tmp
= gen_ld8u(addr
, IS_USER(s
));
8376 tmp
= gen_ld16s(addr
, IS_USER(s
));
8379 if (op
>= 3) /* load */
8380 store_reg(s
, rd
, tmp
);
8385 /* load/store word immediate offset */
8387 rn
= (insn
>> 3) & 7;
8388 addr
= load_reg(s
, rn
);
8389 val
= (insn
>> 4) & 0x7c;
8390 tcg_gen_addi_i32(addr
, addr
, val
);
8392 if (insn
& (1 << 11)) {
8394 tmp
= gen_ld32(addr
, IS_USER(s
));
8395 store_reg(s
, rd
, tmp
);
8398 tmp
= load_reg(s
, rd
);
8399 gen_st32(tmp
, addr
, IS_USER(s
));
8405 /* load/store byte immediate offset */
8407 rn
= (insn
>> 3) & 7;
8408 addr
= load_reg(s
, rn
);
8409 val
= (insn
>> 6) & 0x1f;
8410 tcg_gen_addi_i32(addr
, addr
, val
);
8412 if (insn
& (1 << 11)) {
8414 tmp
= gen_ld8u(addr
, IS_USER(s
));
8415 store_reg(s
, rd
, tmp
);
8418 tmp
= load_reg(s
, rd
);
8419 gen_st8(tmp
, addr
, IS_USER(s
));
8425 /* load/store halfword immediate offset */
8427 rn
= (insn
>> 3) & 7;
8428 addr
= load_reg(s
, rn
);
8429 val
= (insn
>> 5) & 0x3e;
8430 tcg_gen_addi_i32(addr
, addr
, val
);
8432 if (insn
& (1 << 11)) {
8434 tmp
= gen_ld16u(addr
, IS_USER(s
));
8435 store_reg(s
, rd
, tmp
);
8438 tmp
= load_reg(s
, rd
);
8439 gen_st16(tmp
, addr
, IS_USER(s
));
8445 /* load/store from stack */
8446 rd
= (insn
>> 8) & 7;
8447 addr
= load_reg(s
, 13);
8448 val
= (insn
& 0xff) * 4;
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 /* add to high reg */
8465 rd
= (insn
>> 8) & 7;
8466 if (insn
& (1 << 11)) {
8468 tmp
= load_reg(s
, 13);
8470 /* PC. bit 1 is ignored. */
8472 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8474 val
= (insn
& 0xff) * 4;
8475 tcg_gen_addi_i32(tmp
, tmp
, val
);
8476 store_reg(s
, rd
, tmp
);
8481 op
= (insn
>> 8) & 0xf;
8484 /* adjust stack pointer */
8485 tmp
= load_reg(s
, 13);
8486 val
= (insn
& 0x7f) * 4;
8487 if (insn
& (1 << 7))
8488 val
= -(int32_t)val
;
8489 tcg_gen_addi_i32(tmp
, tmp
, val
);
8490 store_reg(s
, 13, tmp
);
8493 case 2: /* sign/zero extend. */
8496 rm
= (insn
>> 3) & 7;
8497 tmp
= load_reg(s
, rm
);
8498 switch ((insn
>> 6) & 3) {
8499 case 0: gen_sxth(tmp
); break;
8500 case 1: gen_sxtb(tmp
); break;
8501 case 2: gen_uxth(tmp
); break;
8502 case 3: gen_uxtb(tmp
); break;
8504 store_reg(s
, rd
, tmp
);
8506 case 4: case 5: case 0xc: case 0xd:
8508 addr
= load_reg(s
, 13);
8509 if (insn
& (1 << 8))
8513 for (i
= 0; i
< 8; i
++) {
8514 if (insn
& (1 << i
))
8517 if ((insn
& (1 << 11)) == 0) {
8518 tcg_gen_addi_i32(addr
, addr
, -offset
);
8520 for (i
= 0; i
< 8; i
++) {
8521 if (insn
& (1 << i
)) {
8522 if (insn
& (1 << 11)) {
8524 tmp
= gen_ld32(addr
, IS_USER(s
));
8525 store_reg(s
, i
, tmp
);
8528 tmp
= load_reg(s
, i
);
8529 gen_st32(tmp
, addr
, IS_USER(s
));
8531 /* advance to the next address. */
8532 tcg_gen_addi_i32(addr
, addr
, 4);
8536 if (insn
& (1 << 8)) {
8537 if (insn
& (1 << 11)) {
8539 tmp
= gen_ld32(addr
, IS_USER(s
));
8540 /* don't set the pc until the rest of the instruction
8544 tmp
= load_reg(s
, 14);
8545 gen_st32(tmp
, addr
, IS_USER(s
));
8547 tcg_gen_addi_i32(addr
, addr
, 4);
8549 if ((insn
& (1 << 11)) == 0) {
8550 tcg_gen_addi_i32(addr
, addr
, -offset
);
8552 /* write back the new stack pointer */
8553 store_reg(s
, 13, addr
);
8554 /* set the new PC value */
8555 if ((insn
& 0x0900) == 0x0900)
8559 case 1: case 3: case 9: case 11: /* czb */
8561 tmp
= load_reg(s
, rm
);
8562 s
->condlabel
= gen_new_label();
8564 if (insn
& (1 << 11))
8565 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8567 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8569 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8570 val
= (uint32_t)s
->pc
+ 2;
8575 case 15: /* IT, nop-hint. */
8576 if ((insn
& 0xf) == 0) {
8577 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8581 s
->condexec_cond
= (insn
>> 4) & 0xe;
8582 s
->condexec_mask
= insn
& 0x1f;
8583 /* No actual code generated for this insn, just setup state. */
8586 case 0xe: /* bkpt */
8587 gen_set_condexec(s
);
8588 gen_set_pc_im(s
->pc
- 2);
8589 gen_exception(EXCP_BKPT
);
8590 s
->is_jmp
= DISAS_JUMP
;
8595 rn
= (insn
>> 3) & 0x7;
8597 tmp
= load_reg(s
, rn
);
8598 switch ((insn
>> 6) & 3) {
8599 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8600 case 1: gen_rev16(tmp
); break;
8601 case 3: gen_revsh(tmp
); break;
8602 default: goto illegal_op
;
8604 store_reg(s
, rd
, tmp
);
8612 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8615 addr
= tcg_const_i32(16);
8616 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8620 addr
= tcg_const_i32(17);
8621 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8625 if (insn
& (1 << 4))
8626 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8629 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8639 /* load/store multiple */
8640 rn
= (insn
>> 8) & 0x7;
8641 addr
= load_reg(s
, rn
);
8642 for (i
= 0; i
< 8; i
++) {
8643 if (insn
& (1 << i
)) {
8644 if (insn
& (1 << 11)) {
8646 tmp
= gen_ld32(addr
, IS_USER(s
));
8647 store_reg(s
, i
, tmp
);
8650 tmp
= load_reg(s
, i
);
8651 gen_st32(tmp
, addr
, IS_USER(s
));
8653 /* advance to the next address */
8654 tcg_gen_addi_i32(addr
, addr
, 4);
8657 /* Base register writeback. */
8658 if ((insn
& (1 << rn
)) == 0) {
8659 store_reg(s
, rn
, addr
);
8666 /* conditional branch or swi */
8667 cond
= (insn
>> 8) & 0xf;
8673 gen_set_condexec(s
);
8674 gen_set_pc_im(s
->pc
);
8675 s
->is_jmp
= DISAS_SWI
;
8678 /* generate a conditional jump to next instruction */
8679 s
->condlabel
= gen_new_label();
8680 gen_test_cc(cond
^ 1, s
->condlabel
);
8683 /* jump to the offset */
8684 val
= (uint32_t)s
->pc
+ 2;
8685 offset
= ((int32_t)insn
<< 24) >> 24;
8691 if (insn
& (1 << 11)) {
8692 if (disas_thumb2_insn(env
, s
, insn
))
8696 /* unconditional branch */
8697 val
= (uint32_t)s
->pc
;
8698 offset
= ((int32_t)insn
<< 21) >> 21;
8699 val
+= (offset
<< 1) + 2;
8704 if (disas_thumb2_insn(env
, s
, insn
))
8710 gen_set_condexec(s
);
8711 gen_set_pc_im(s
->pc
- 4);
8712 gen_exception(EXCP_UDEF
);
8713 s
->is_jmp
= DISAS_JUMP
;
8717 gen_set_condexec(s
);
8718 gen_set_pc_im(s
->pc
- 2);
8719 gen_exception(EXCP_UDEF
);
8720 s
->is_jmp
= DISAS_JUMP
;
8723 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8724 basic block 'tb'. If search_pc is TRUE, also generate PC
8725 information for each intermediate instruction. */
8726 static inline void gen_intermediate_code_internal(CPUState
*env
,
8727 TranslationBlock
*tb
,
8730 DisasContext dc1
, *dc
= &dc1
;
8732 uint16_t *gen_opc_end
;
8734 target_ulong pc_start
;
8735 uint32_t next_page_start
;
8739 /* generate intermediate code */
8746 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8748 dc
->is_jmp
= DISAS_NEXT
;
8750 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8752 dc
->thumb
= env
->thumb
;
8753 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8754 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8755 #if !defined(CONFIG_USER_ONLY)
8757 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8759 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8762 cpu_F0s
= tcg_temp_new_i32();
8763 cpu_F1s
= tcg_temp_new_i32();
8764 cpu_F0d
= tcg_temp_new_i64();
8765 cpu_F1d
= tcg_temp_new_i64();
8768 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8769 cpu_M0
= tcg_temp_new_i64();
8770 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8773 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8775 max_insns
= CF_COUNT_MASK
;
8778 /* Reset the conditional execution bits immediately. This avoids
8779 complications trying to do it at the end of the block. */
8780 if (env
->condexec_bits
)
8782 TCGv tmp
= new_tmp();
8783 tcg_gen_movi_i32(tmp
, 0);
8784 store_cpu_field(tmp
, condexec_bits
);
8787 #ifdef CONFIG_USER_ONLY
8788 /* Intercept jump to the magic kernel page. */
8789 if (dc
->pc
>= 0xffff0000) {
8790 /* We always get here via a jump, so know we are not in a
8791 conditional execution block. */
8792 gen_exception(EXCP_KERNEL_TRAP
);
8793 dc
->is_jmp
= DISAS_UPDATE
;
8797 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8798 /* We always get here via a jump, so know we are not in a
8799 conditional execution block. */
8800 gen_exception(EXCP_EXCEPTION_EXIT
);
8801 dc
->is_jmp
= DISAS_UPDATE
;
8806 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
8807 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8808 if (bp
->pc
== dc
->pc
) {
8809 gen_set_condexec(dc
);
8810 gen_set_pc_im(dc
->pc
);
8811 gen_exception(EXCP_DEBUG
);
8812 dc
->is_jmp
= DISAS_JUMP
;
8813 /* Advance PC so that clearing the breakpoint will
8814 invalidate this TB. */
8816 goto done_generating
;
8822 j
= gen_opc_ptr
- gen_opc_buf
;
8826 gen_opc_instr_start
[lj
++] = 0;
8828 gen_opc_pc
[lj
] = dc
->pc
;
8829 gen_opc_instr_start
[lj
] = 1;
8830 gen_opc_icount
[lj
] = num_insns
;
8833 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8837 disas_thumb_insn(env
, dc
);
8838 if (dc
->condexec_mask
) {
8839 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8840 | ((dc
->condexec_mask
>> 4) & 1);
8841 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8842 if (dc
->condexec_mask
== 0) {
8843 dc
->condexec_cond
= 0;
8847 disas_arm_insn(env
, dc
);
8850 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8854 if (dc
->condjmp
&& !dc
->is_jmp
) {
8855 gen_set_label(dc
->condlabel
);
8858 /* Translation stops when a conditional branch is encountered.
8859 * Otherwise the subsequent code could get translated several times.
8860 * Also stop translation when a page boundary is reached. This
8861 * ensures prefetch aborts occur at the right place. */
8863 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8864 !env
->singlestep_enabled
&&
8866 dc
->pc
< next_page_start
&&
8867 num_insns
< max_insns
);
8869 if (tb
->cflags
& CF_LAST_IO
) {
8871 /* FIXME: This can theoretically happen with self-modifying
8873 cpu_abort(env
, "IO on conditional branch instruction");
8878 /* At this stage dc->condjmp will only be set when the skipped
8879 instruction was a conditional branch or trap, and the PC has
8880 already been written. */
8881 if (unlikely(env
->singlestep_enabled
)) {
8882 /* Make sure the pc is updated, and raise a debug exception. */
8884 gen_set_condexec(dc
);
8885 if (dc
->is_jmp
== DISAS_SWI
) {
8886 gen_exception(EXCP_SWI
);
8888 gen_exception(EXCP_DEBUG
);
8890 gen_set_label(dc
->condlabel
);
8892 if (dc
->condjmp
|| !dc
->is_jmp
) {
8893 gen_set_pc_im(dc
->pc
);
8896 gen_set_condexec(dc
);
8897 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8898 gen_exception(EXCP_SWI
);
8900 /* FIXME: Single stepping a WFI insn will not halt
8902 gen_exception(EXCP_DEBUG
);
8905 /* While branches must always occur at the end of an IT block,
8906 there are a few other things that can cause us to terminate
8907 the TB in the middel of an IT block:
8908 - Exception generating instructions (bkpt, swi, undefined).
8910 - Hardware watchpoints.
8911 Hardware breakpoints have already been handled and skip this code.
8913 gen_set_condexec(dc
);
8914 switch(dc
->is_jmp
) {
8916 gen_goto_tb(dc
, 1, dc
->pc
);
8921 /* indicate that the hash table must be used to find the next TB */
8925 /* nothing more to generate */
8931 gen_exception(EXCP_SWI
);
8935 gen_set_label(dc
->condlabel
);
8936 gen_set_condexec(dc
);
8937 gen_goto_tb(dc
, 1, dc
->pc
);
8943 gen_icount_end(tb
, num_insns
);
8944 *gen_opc_ptr
= INDEX_op_end
;
8947 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8948 qemu_log("----------------\n");
8949 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8950 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8955 j
= gen_opc_ptr
- gen_opc_buf
;
8958 gen_opc_instr_start
[lj
++] = 0;
8960 tb
->size
= dc
->pc
- pc_start
;
8961 tb
->icount
= num_insns
;
8965 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8967 gen_intermediate_code_internal(env
, tb
, 0);
8970 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8972 gen_intermediate_code_internal(env
, tb
, 1);
8975 static const char *cpu_mode_names
[16] = {
8976 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8977 "???", "???", "???", "und", "???", "???", "???", "sys"
8980 void cpu_dump_state(CPUState
*env
, FILE *f
,
8981 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8991 /* ??? This assumes float64 and double have the same layout.
8992 Oh well, it's only debug dumps. */
9001 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9003 cpu_fprintf(f
, "\n");
9005 cpu_fprintf(f
, " ");
9007 psr
= cpsr_read(env
);
9008 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9010 psr
& (1 << 31) ? 'N' : '-',
9011 psr
& (1 << 30) ? 'Z' : '-',
9012 psr
& (1 << 29) ? 'C' : '-',
9013 psr
& (1 << 28) ? 'V' : '-',
9014 psr
& CPSR_T
? 'T' : 'A',
9015 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9018 for (i
= 0; i
< 16; i
++) {
9019 d
.d
= env
->vfp
.regs
[i
];
9023 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9024 i
* 2, (int)s0
.i
, s0
.s
,
9025 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9026 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9029 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9033 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9034 unsigned long searched_pc
, int pc_pos
, void *puc
)
9036 env
->regs
[15] = gen_opc_pc
[pc_pos
];