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_5 arm_feature(env, ARM_FEATURE_V5)
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext
{
50 /* Nonzero if this instruction has been conditionally skipped. */
52 /* The label that will be jumped to when the instruction is skipped. */
54 /* Thumb-2 condtional execution bits. */
57 struct TranslationBlock
*tb
;
58 int singlestep_enabled
;
60 #if !defined(CONFIG_USER_ONLY)
65 #if defined(CONFIG_USER_ONLY)
68 #define IS_USER(s) (s->user)
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
76 static TCGv_ptr cpu_env
;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
79 static TCGv_i32 cpu_R
[16];
80 /* CPSR flags, used for efficiency */
81 static TCGv_i32 cpu_CF
, cpu_VF
, cpu_NF
, cpu_ZF
;
83 /* FIXME: These should be removed. */
84 static TCGv cpu_F0s
, cpu_F1s
;
85 static TCGv_i64 cpu_F0d
, cpu_F1d
;
87 #include "gen-icount.h"
89 static const char *regnames
[] =
90 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
91 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
93 /* initialize TCG globals. */
94 void arm_translate_init(void)
98 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
100 for (i
= 0; i
< 16; i
++) {
101 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
102 offsetof(CPUState
, regs
[i
]),
106 cpu_CF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUState
, CF
), "CF");
107 cpu_VF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUState
, VF
), "VF");
108 cpu_NF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUState
, NF
), "NF");
109 cpu_ZF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUState
, ZF
), "ZF");
115 static int num_temps
;
117 /* Allocate a temporary variable. */
118 static TCGv_i32
new_tmp(void)
121 return tcg_temp_new_i32();
124 /* Release a temporary variable. */
125 static void dead_tmp(TCGv tmp
)
131 static inline TCGv
load_cpu_offset(int offset
)
133 TCGv tmp
= new_tmp();
134 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
138 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
140 static inline void store_cpu_offset(TCGv var
, int offset
)
142 tcg_gen_st_i32(var
, cpu_env
, offset
);
146 #define store_cpu_field(var, name) \
147 store_cpu_offset(var, offsetof(CPUState, name))
149 /* Set a variable to the value of a CPU register. */
150 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
154 /* normaly, since we updated PC, we need only to add one insn */
156 addr
= (long)s
->pc
+ 2;
158 addr
= (long)s
->pc
+ 4;
159 tcg_gen_movi_i32(var
, addr
);
161 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
165 /* Create a new temporary and set it to the value of a CPU register. */
166 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
168 TCGv tmp
= new_tmp();
169 load_reg_var(s
, tmp
, reg
);
173 /* Set a CPU register. The source must be a temporary and will be
175 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
178 tcg_gen_andi_i32(var
, var
, ~1);
179 s
->is_jmp
= DISAS_JUMP
;
181 tcg_gen_mov_i32(cpu_R
[reg
], var
);
185 /* Value extensions. */
186 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
187 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
188 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
189 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
191 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
192 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
195 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
196 /* Set NZCV flags from the high 4 bits of var. */
197 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
199 static void gen_exception(int excp
)
201 TCGv tmp
= new_tmp();
202 tcg_gen_movi_i32(tmp
, excp
);
203 gen_helper_exception(tmp
);
207 static void gen_smul_dual(TCGv a
, TCGv b
)
209 TCGv tmp1
= new_tmp();
210 TCGv tmp2
= new_tmp();
211 tcg_gen_ext16s_i32(tmp1
, a
);
212 tcg_gen_ext16s_i32(tmp2
, b
);
213 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
215 tcg_gen_sari_i32(a
, a
, 16);
216 tcg_gen_sari_i32(b
, b
, 16);
217 tcg_gen_mul_i32(b
, b
, a
);
218 tcg_gen_mov_i32(a
, tmp1
);
222 /* Byteswap each halfword. */
223 static void gen_rev16(TCGv var
)
225 TCGv tmp
= new_tmp();
226 tcg_gen_shri_i32(tmp
, var
, 8);
227 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
228 tcg_gen_shli_i32(var
, var
, 8);
229 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
230 tcg_gen_or_i32(var
, var
, tmp
);
234 /* Byteswap low halfword and sign extend. */
235 static void gen_revsh(TCGv var
)
237 TCGv tmp
= new_tmp();
238 tcg_gen_shri_i32(tmp
, var
, 8);
239 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
240 tcg_gen_shli_i32(var
, var
, 8);
241 tcg_gen_ext8s_i32(var
, var
);
242 tcg_gen_or_i32(var
, var
, tmp
);
246 /* Unsigned bitfield extract. */
247 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
250 tcg_gen_shri_i32(var
, var
, shift
);
251 tcg_gen_andi_i32(var
, var
, mask
);
254 /* Signed bitfield extract. */
255 static void gen_sbfx(TCGv var
, int shift
, int width
)
260 tcg_gen_sari_i32(var
, var
, shift
);
261 if (shift
+ width
< 32) {
262 signbit
= 1u << (width
- 1);
263 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
264 tcg_gen_xori_i32(var
, var
, signbit
);
265 tcg_gen_subi_i32(var
, var
, signbit
);
269 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
270 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
272 tcg_gen_andi_i32(val
, val
, mask
);
273 tcg_gen_shli_i32(val
, val
, shift
);
274 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
275 tcg_gen_or_i32(dest
, base
, val
);
278 /* Round the top 32 bits of a 64-bit value. */
279 static void gen_roundqd(TCGv a
, TCGv b
)
281 tcg_gen_shri_i32(a
, a
, 31);
282 tcg_gen_add_i32(a
, a
, b
);
285 /* FIXME: Most targets have native widening multiplication.
286 It would be good to use that instead of a full wide multiply. */
287 /* 32x32->64 multiply. Marks inputs as dead. */
288 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
290 TCGv_i64 tmp1
= tcg_temp_new_i64();
291 TCGv_i64 tmp2
= tcg_temp_new_i64();
293 tcg_gen_extu_i32_i64(tmp1
, a
);
295 tcg_gen_extu_i32_i64(tmp2
, b
);
297 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
301 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
303 TCGv_i64 tmp1
= tcg_temp_new_i64();
304 TCGv_i64 tmp2
= tcg_temp_new_i64();
306 tcg_gen_ext_i32_i64(tmp1
, a
);
308 tcg_gen_ext_i32_i64(tmp2
, b
);
310 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
314 /* Unsigned 32x32->64 multiply. */
315 static void gen_mull(TCGv a
, TCGv b
)
317 TCGv_i64 tmp1
= tcg_temp_new_i64();
318 TCGv_i64 tmp2
= tcg_temp_new_i64();
320 tcg_gen_extu_i32_i64(tmp1
, a
);
321 tcg_gen_extu_i32_i64(tmp2
, b
);
322 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
323 tcg_gen_trunc_i64_i32(a
, tmp1
);
324 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
325 tcg_gen_trunc_i64_i32(b
, tmp1
);
328 /* Signed 32x32->64 multiply. */
329 static void gen_imull(TCGv a
, TCGv b
)
331 TCGv_i64 tmp1
= tcg_temp_new_i64();
332 TCGv_i64 tmp2
= tcg_temp_new_i64();
334 tcg_gen_ext_i32_i64(tmp1
, a
);
335 tcg_gen_ext_i32_i64(tmp2
, b
);
336 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
337 tcg_gen_trunc_i64_i32(a
, tmp1
);
338 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
339 tcg_gen_trunc_i64_i32(b
, tmp1
);
342 /* Swap low and high halfwords. */
343 static void gen_swap_half(TCGv var
)
345 TCGv tmp
= new_tmp();
346 tcg_gen_shri_i32(tmp
, var
, 16);
347 tcg_gen_shli_i32(var
, var
, 16);
348 tcg_gen_or_i32(var
, var
, tmp
);
352 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
353 tmp = (t0 ^ t1) & 0x8000;
356 t0 = (t0 + t1) ^ tmp;
359 static void gen_add16(TCGv t0
, TCGv t1
)
361 TCGv tmp
= new_tmp();
362 tcg_gen_xor_i32(tmp
, t0
, t1
);
363 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
364 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
365 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
366 tcg_gen_add_i32(t0
, t0
, t1
);
367 tcg_gen_xor_i32(t0
, t0
, tmp
);
372 #define gen_set_CF(var) tcg_gen_mov_i32(cpu_CF, var)
374 /* Set CF to the top bit of var. */
375 static void gen_set_CF_bit31(TCGv var
)
377 tcg_gen_shri_i32(cpu_CF
, var
, 31);
380 /* Set N and Z flags from var. */
381 static inline void gen_logic_CC(TCGv var
)
383 tcg_gen_mov_i32(cpu_NF
, var
);
384 tcg_gen_mov_i32(cpu_ZF
, var
);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
390 tcg_gen_add_i32(dest
, t0
, t1
);
391 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
394 /* dest = T0 - T1 + CF - 1. */
395 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
397 tcg_gen_sub_i32(dest
, t0
, t1
);
398 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
399 tcg_gen_subi_i32(dest
, dest
, 1);
402 /* T0 &= ~T1. Clobbers T1. */
403 /* FIXME: Implement bic natively. */
404 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
406 TCGv tmp
= new_tmp();
407 tcg_gen_not_i32(tmp
, t1
);
408 tcg_gen_and_i32(dest
, t0
, tmp
);
412 /* FIXME: Implement this natively. */
413 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
415 static void shifter_out_im(TCGv var
, int shift
)
417 TCGv tmp
= new_tmp();
419 tcg_gen_andi_i32(tmp
, var
, 1);
421 tcg_gen_shri_i32(tmp
, var
, shift
);
423 tcg_gen_andi_i32(tmp
, tmp
, 1);
429 /* Shift by immediate. Includes special handling for shift == 0. */
430 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
436 shifter_out_im(var
, 32 - shift
);
437 tcg_gen_shli_i32(var
, var
, shift
);
443 tcg_gen_shri_i32(var
, var
, 31);
446 tcg_gen_movi_i32(var
, 0);
449 shifter_out_im(var
, shift
- 1);
450 tcg_gen_shri_i32(var
, var
, shift
);
457 shifter_out_im(var
, shift
- 1);
460 tcg_gen_sari_i32(var
, var
, shift
);
462 case 3: /* ROR/RRX */
465 shifter_out_im(var
, shift
- 1);
466 tcg_gen_rotri_i32(var
, var
, shift
); break;
468 TCGv tmp
= new_tmp();
469 tcg_gen_mov_i32(tmp
, cpu_CF
);
471 shifter_out_im(var
, 0);
472 tcg_gen_shri_i32(var
, var
, 1);
473 tcg_gen_shli_i32(tmp
, tmp
, 31);
474 tcg_gen_or_i32(var
, var
, tmp
);
480 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
481 TCGv shift
, int flags
)
485 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
486 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
487 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
488 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
492 case 0: gen_helper_shl(var
, var
, shift
); break;
493 case 1: gen_helper_shr(var
, var
, shift
); break;
494 case 2: gen_helper_sar(var
, var
, shift
); break;
495 case 3: gen_helper_ror(var
, var
, shift
); break;
501 #define PAS_OP(pfx) \
503 case 0: gen_pas_helper(glue(pfx,add16)); break; \
504 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
505 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
506 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
507 case 4: gen_pas_helper(glue(pfx,add8)); break; \
508 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
510 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
515 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
517 tmp
= tcg_temp_new_ptr();
518 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
522 tmp
= tcg_temp_new_ptr();
523 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
526 #undef gen_pas_helper
527 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
540 #undef gen_pas_helper
545 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
546 #define PAS_OP(pfx) \
548 case 0: gen_pas_helper(glue(pfx,add8)); break; \
549 case 1: gen_pas_helper(glue(pfx,add16)); break; \
550 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
551 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
552 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
553 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
555 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
560 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
562 tmp
= tcg_temp_new_ptr();
563 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
567 tmp
= tcg_temp_new_ptr();
568 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
571 #undef gen_pas_helper
572 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
585 #undef gen_pas_helper
590 static void gen_test_cc(int cc
, int label
)
597 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
600 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_ZF
, 0, label
);
603 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_CF
, 0, label
);
606 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, label
);
609 tcg_gen_brcondi_i32(TCG_COND_LT
, cpu_NF
, 0, label
);
612 tcg_gen_brcondi_i32(TCG_COND_GE
, cpu_NF
, 0, label
);
615 tcg_gen_brcondi_i32(TCG_COND_LT
, cpu_VF
, 0, label
);
618 tcg_gen_brcondi_i32(TCG_COND_GE
, cpu_VF
, 0, label
);
620 case 8: /* hi: C && !Z */
621 inv
= gen_new_label();
622 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, inv
);
623 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_ZF
, 0, label
);
626 case 9: /* ls: !C || Z */
627 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, label
);
628 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
630 case 10: /* ge: N == V -> N ^ V == 0 */
632 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
633 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
636 case 11: /* lt: N != V -> N ^ V != 0 */
638 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
639 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
642 case 12: /* gt: !Z && N == V */
643 inv
= gen_new_label();
644 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, inv
);
646 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
647 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
651 case 13: /* le: Z || N != V */
652 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
654 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
655 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
659 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
664 static const uint8_t table_logic_cc
[16] = {
683 /* Set PC and Thumb state from an immediate address. */
684 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
688 s
->is_jmp
= DISAS_UPDATE
;
689 if (s
->thumb
!= (addr
& 1)) {
691 tcg_gen_movi_i32(tmp
, addr
& 1);
692 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
695 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
698 /* Set PC and Thumb state from var. var is marked as dead. */
699 static inline void gen_bx(DisasContext
*s
, TCGv var
)
701 s
->is_jmp
= DISAS_UPDATE
;
702 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
703 tcg_gen_andi_i32(var
, var
, 1);
704 store_cpu_field(var
, thumb
);
707 /* Variant of store_reg which uses branch&exchange logic when storing
708 to r15 in ARM architecture v7 and above. The source must be a temporary
709 and will be marked as dead. */
710 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
713 if (reg
== 15 && ENABLE_ARCH_7
) {
716 store_reg(s
, reg
, var
);
720 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
722 TCGv tmp
= new_tmp();
723 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
726 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
728 TCGv tmp
= new_tmp();
729 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
732 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
734 TCGv tmp
= new_tmp();
735 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
738 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
740 TCGv tmp
= new_tmp();
741 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
744 static inline TCGv
gen_ld32(TCGv addr
, int index
)
746 TCGv tmp
= new_tmp();
747 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
750 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
752 tcg_gen_qemu_st8(val
, addr
, index
);
755 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
757 tcg_gen_qemu_st16(val
, addr
, index
);
760 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
762 tcg_gen_qemu_st32(val
, addr
, index
);
766 static inline void gen_set_pc_im(uint32_t val
)
768 tcg_gen_movi_i32(cpu_R
[15], val
);
771 /* Force a TB lookup after an instruction that changes the CPU state. */
772 static inline void gen_lookup_tb(DisasContext
*s
)
774 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
775 s
->is_jmp
= DISAS_UPDATE
;
778 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
781 int val
, rm
, shift
, shiftop
;
784 if (!(insn
& (1 << 25))) {
787 if (!(insn
& (1 << 23)))
790 tcg_gen_addi_i32(var
, var
, val
);
794 shift
= (insn
>> 7) & 0x1f;
795 shiftop
= (insn
>> 5) & 3;
796 offset
= load_reg(s
, rm
);
797 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
798 if (!(insn
& (1 << 23)))
799 tcg_gen_sub_i32(var
, var
, offset
);
801 tcg_gen_add_i32(var
, var
, offset
);
806 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
812 if (insn
& (1 << 22)) {
814 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
815 if (!(insn
& (1 << 23)))
819 tcg_gen_addi_i32(var
, var
, val
);
823 tcg_gen_addi_i32(var
, var
, extra
);
825 offset
= load_reg(s
, rm
);
826 if (!(insn
& (1 << 23)))
827 tcg_gen_sub_i32(var
, var
, offset
);
829 tcg_gen_add_i32(var
, var
, offset
);
834 #define VFP_OP2(name) \
835 static inline void gen_vfp_##name(int dp) \
838 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
840 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
850 static inline void gen_vfp_abs(int dp
)
853 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
855 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
858 static inline void gen_vfp_neg(int dp
)
861 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
863 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
866 static inline void gen_vfp_sqrt(int dp
)
869 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
871 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
874 static inline void gen_vfp_cmp(int dp
)
877 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
879 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
882 static inline void gen_vfp_cmpe(int dp
)
885 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
887 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
890 static inline void gen_vfp_F1_ld0(int dp
)
893 tcg_gen_movi_i64(cpu_F1d
, 0);
895 tcg_gen_movi_i32(cpu_F1s
, 0);
898 static inline void gen_vfp_uito(int dp
)
901 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
903 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
906 static inline void gen_vfp_sito(int dp
)
909 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
911 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
914 static inline void gen_vfp_toui(int dp
)
917 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
919 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
922 static inline void gen_vfp_touiz(int dp
)
925 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
927 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
930 static inline void gen_vfp_tosi(int dp
)
933 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
935 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
938 static inline void gen_vfp_tosiz(int dp
)
941 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
943 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
946 #define VFP_GEN_FIX(name) \
947 static inline void gen_vfp_##name(int dp, int shift) \
950 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
952 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
964 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv addr
)
967 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
969 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
972 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv addr
)
975 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
977 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
981 vfp_reg_offset (int dp
, int reg
)
984 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
986 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
987 + offsetof(CPU_DoubleU
, l
.upper
);
989 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
990 + offsetof(CPU_DoubleU
, l
.lower
);
994 /* Return the offset of a 32-bit piece of a NEON register.
995 zero is the least significant end of the register. */
997 neon_reg_offset (int reg
, int n
)
1001 return vfp_reg_offset(0, sreg
);
1004 static TCGv
neon_load_reg(int reg
, int pass
)
1006 TCGv tmp
= new_tmp();
1007 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1011 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1013 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1017 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1019 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1022 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1024 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1027 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1028 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1029 #define tcg_gen_st_f32 tcg_gen_st_i32
1030 #define tcg_gen_st_f64 tcg_gen_st_i64
1032 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1035 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1037 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1040 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1043 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1045 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1048 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1051 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1053 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1056 #define ARM_CP_RW_BIT (1 << 20)
1058 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1060 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1063 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1065 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1068 static inline TCGv
iwmmxt_load_creg(int reg
)
1070 TCGv var
= new_tmp();
1071 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1075 static inline void iwmmxt_store_creg(int reg
, TCGv var
)
1077 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1080 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1082 iwmmxt_store_reg(cpu_M0
, rn
);
1085 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1087 iwmmxt_load_reg(cpu_M0
, rn
);
1090 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1092 iwmmxt_load_reg(cpu_V1
, rn
);
1093 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1096 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1098 iwmmxt_load_reg(cpu_V1
, rn
);
1099 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1102 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1104 iwmmxt_load_reg(cpu_V1
, rn
);
1105 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1108 #define IWMMXT_OP(name) \
1109 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1111 iwmmxt_load_reg(cpu_V1, rn); \
1112 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1115 #define IWMMXT_OP_ENV(name) \
1116 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1118 iwmmxt_load_reg(cpu_V1, rn); \
1119 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1122 #define IWMMXT_OP_ENV_SIZE(name) \
1123 IWMMXT_OP_ENV(name##b) \
1124 IWMMXT_OP_ENV(name##w) \
1125 IWMMXT_OP_ENV(name##l)
1127 #define IWMMXT_OP_ENV1(name) \
1128 static inline void gen_op_iwmmxt_##name##_M0(void) \
1130 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1144 IWMMXT_OP_ENV_SIZE(unpackl
)
1145 IWMMXT_OP_ENV_SIZE(unpackh
)
1147 IWMMXT_OP_ENV1(unpacklub
)
1148 IWMMXT_OP_ENV1(unpackluw
)
1149 IWMMXT_OP_ENV1(unpacklul
)
1150 IWMMXT_OP_ENV1(unpackhub
)
1151 IWMMXT_OP_ENV1(unpackhuw
)
1152 IWMMXT_OP_ENV1(unpackhul
)
1153 IWMMXT_OP_ENV1(unpacklsb
)
1154 IWMMXT_OP_ENV1(unpacklsw
)
1155 IWMMXT_OP_ENV1(unpacklsl
)
1156 IWMMXT_OP_ENV1(unpackhsb
)
1157 IWMMXT_OP_ENV1(unpackhsw
)
1158 IWMMXT_OP_ENV1(unpackhsl
)
1160 IWMMXT_OP_ENV_SIZE(cmpeq
)
1161 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1162 IWMMXT_OP_ENV_SIZE(cmpgts
)
1164 IWMMXT_OP_ENV_SIZE(mins
)
1165 IWMMXT_OP_ENV_SIZE(minu
)
1166 IWMMXT_OP_ENV_SIZE(maxs
)
1167 IWMMXT_OP_ENV_SIZE(maxu
)
1169 IWMMXT_OP_ENV_SIZE(subn
)
1170 IWMMXT_OP_ENV_SIZE(addn
)
1171 IWMMXT_OP_ENV_SIZE(subu
)
1172 IWMMXT_OP_ENV_SIZE(addu
)
1173 IWMMXT_OP_ENV_SIZE(subs
)
1174 IWMMXT_OP_ENV_SIZE(adds
)
1176 IWMMXT_OP_ENV(avgb0
)
1177 IWMMXT_OP_ENV(avgb1
)
1178 IWMMXT_OP_ENV(avgw0
)
1179 IWMMXT_OP_ENV(avgw1
)
1183 IWMMXT_OP_ENV(packuw
)
1184 IWMMXT_OP_ENV(packul
)
1185 IWMMXT_OP_ENV(packuq
)
1186 IWMMXT_OP_ENV(packsw
)
1187 IWMMXT_OP_ENV(packsl
)
1188 IWMMXT_OP_ENV(packsq
)
1190 static void gen_op_iwmmxt_set_mup(void)
1193 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1194 tcg_gen_ori_i32(tmp
, tmp
, 2);
1195 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1198 static void gen_op_iwmmxt_set_cup(void)
1201 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1202 tcg_gen_ori_i32(tmp
, tmp
, 1);
1203 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1206 static void gen_op_iwmmxt_setpsr_nz(void)
1208 TCGv tmp
= new_tmp();
1209 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1210 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1213 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1215 iwmmxt_load_reg(cpu_V1
, rn
);
1216 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1217 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1220 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
, TCGv dest
)
1226 rd
= (insn
>> 16) & 0xf;
1227 tmp
= load_reg(s
, rd
);
1229 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1230 if (insn
& (1 << 24)) {
1232 if (insn
& (1 << 23))
1233 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1235 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1236 tcg_gen_mov_i32(dest
, tmp
);
1237 if (insn
& (1 << 21))
1238 store_reg(s
, rd
, tmp
);
1241 } else if (insn
& (1 << 21)) {
1243 tcg_gen_mov_i32(dest
, tmp
);
1244 if (insn
& (1 << 23))
1245 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1247 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1248 store_reg(s
, rd
, tmp
);
1249 } else if (!(insn
& (1 << 23)))
1254 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv dest
)
1256 int rd
= (insn
>> 0) & 0xf;
1259 if (insn
& (1 << 8)) {
1260 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1263 tmp
= iwmmxt_load_creg(rd
);
1267 iwmmxt_load_reg(cpu_V0
, rd
);
1268 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1270 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1271 tcg_gen_mov_i32(dest
, tmp
);
1276 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1277 (ie. an undefined instruction). */
1278 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1281 int rdhi
, rdlo
, rd0
, rd1
, i
;
1283 TCGv tmp
, tmp2
, tmp3
;
1285 if ((insn
& 0x0e000e00) == 0x0c000000) {
1286 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1288 rdlo
= (insn
>> 12) & 0xf;
1289 rdhi
= (insn
>> 16) & 0xf;
1290 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1291 iwmmxt_load_reg(cpu_V0
, wrd
);
1292 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1293 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1294 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1295 } else { /* TMCRR */
1296 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1297 iwmmxt_store_reg(cpu_V0
, wrd
);
1298 gen_op_iwmmxt_set_mup();
1303 wrd
= (insn
>> 12) & 0xf;
1305 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1309 if (insn
& ARM_CP_RW_BIT
) {
1310 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1312 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1313 iwmmxt_store_creg(wrd
, tmp
);
1316 if (insn
& (1 << 8)) {
1317 if (insn
& (1 << 22)) { /* WLDRD */
1318 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1320 } else { /* WLDRW wRd */
1321 tmp
= gen_ld32(addr
, IS_USER(s
));
1324 if (insn
& (1 << 22)) { /* WLDRH */
1325 tmp
= gen_ld16u(addr
, IS_USER(s
));
1326 } else { /* WLDRB */
1327 tmp
= gen_ld8u(addr
, IS_USER(s
));
1331 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1334 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1337 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1338 tmp
= iwmmxt_load_creg(wrd
);
1339 gen_st32(tmp
, addr
, IS_USER(s
));
1341 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1343 if (insn
& (1 << 8)) {
1344 if (insn
& (1 << 22)) { /* WSTRD */
1346 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1347 } else { /* WSTRW wRd */
1348 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1349 gen_st32(tmp
, addr
, IS_USER(s
));
1352 if (insn
& (1 << 22)) { /* WSTRH */
1353 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1354 gen_st16(tmp
, addr
, IS_USER(s
));
1355 } else { /* WSTRB */
1356 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1357 gen_st8(tmp
, addr
, IS_USER(s
));
1365 if ((insn
& 0x0f000000) != 0x0e000000)
1368 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1369 case 0x000: /* WOR */
1370 wrd
= (insn
>> 12) & 0xf;
1371 rd0
= (insn
>> 0) & 0xf;
1372 rd1
= (insn
>> 16) & 0xf;
1373 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1374 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1375 gen_op_iwmmxt_setpsr_nz();
1376 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1377 gen_op_iwmmxt_set_mup();
1378 gen_op_iwmmxt_set_cup();
1380 case 0x011: /* TMCR */
1383 rd
= (insn
>> 12) & 0xf;
1384 wrd
= (insn
>> 16) & 0xf;
1386 case ARM_IWMMXT_wCID
:
1387 case ARM_IWMMXT_wCASF
:
1389 case ARM_IWMMXT_wCon
:
1390 gen_op_iwmmxt_set_cup();
1392 case ARM_IWMMXT_wCSSF
:
1393 tmp
= iwmmxt_load_creg(wrd
);
1394 tmp2
= load_reg(s
, rd
);
1395 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
1397 iwmmxt_store_creg(wrd
, tmp
);
1399 case ARM_IWMMXT_wCGR0
:
1400 case ARM_IWMMXT_wCGR1
:
1401 case ARM_IWMMXT_wCGR2
:
1402 case ARM_IWMMXT_wCGR3
:
1403 gen_op_iwmmxt_set_cup();
1404 tmp
= load_reg(s
, rd
);
1405 iwmmxt_store_creg(wrd
, tmp
);
1411 case 0x100: /* WXOR */
1412 wrd
= (insn
>> 12) & 0xf;
1413 rd0
= (insn
>> 0) & 0xf;
1414 rd1
= (insn
>> 16) & 0xf;
1415 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1416 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1417 gen_op_iwmmxt_setpsr_nz();
1418 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1419 gen_op_iwmmxt_set_mup();
1420 gen_op_iwmmxt_set_cup();
1422 case 0x111: /* TMRC */
1425 rd
= (insn
>> 12) & 0xf;
1426 wrd
= (insn
>> 16) & 0xf;
1427 tmp
= iwmmxt_load_creg(wrd
);
1428 store_reg(s
, rd
, tmp
);
1430 case 0x300: /* WANDN */
1431 wrd
= (insn
>> 12) & 0xf;
1432 rd0
= (insn
>> 0) & 0xf;
1433 rd1
= (insn
>> 16) & 0xf;
1434 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1435 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1436 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1437 gen_op_iwmmxt_setpsr_nz();
1438 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1439 gen_op_iwmmxt_set_mup();
1440 gen_op_iwmmxt_set_cup();
1442 case 0x200: /* WAND */
1443 wrd
= (insn
>> 12) & 0xf;
1444 rd0
= (insn
>> 0) & 0xf;
1445 rd1
= (insn
>> 16) & 0xf;
1446 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1447 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1448 gen_op_iwmmxt_setpsr_nz();
1449 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1450 gen_op_iwmmxt_set_mup();
1451 gen_op_iwmmxt_set_cup();
1453 case 0x810: case 0xa10: /* WMADD */
1454 wrd
= (insn
>> 12) & 0xf;
1455 rd0
= (insn
>> 0) & 0xf;
1456 rd1
= (insn
>> 16) & 0xf;
1457 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1458 if (insn
& (1 << 21))
1459 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1461 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1462 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1463 gen_op_iwmmxt_set_mup();
1465 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1466 wrd
= (insn
>> 12) & 0xf;
1467 rd0
= (insn
>> 16) & 0xf;
1468 rd1
= (insn
>> 0) & 0xf;
1469 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1470 switch ((insn
>> 22) & 3) {
1472 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1475 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1478 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1483 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1484 gen_op_iwmmxt_set_mup();
1485 gen_op_iwmmxt_set_cup();
1487 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1488 wrd
= (insn
>> 12) & 0xf;
1489 rd0
= (insn
>> 16) & 0xf;
1490 rd1
= (insn
>> 0) & 0xf;
1491 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1492 switch ((insn
>> 22) & 3) {
1494 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1497 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1500 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1505 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1506 gen_op_iwmmxt_set_mup();
1507 gen_op_iwmmxt_set_cup();
1509 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1510 wrd
= (insn
>> 12) & 0xf;
1511 rd0
= (insn
>> 16) & 0xf;
1512 rd1
= (insn
>> 0) & 0xf;
1513 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1514 if (insn
& (1 << 22))
1515 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1517 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1518 if (!(insn
& (1 << 20)))
1519 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1520 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1521 gen_op_iwmmxt_set_mup();
1523 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1524 wrd
= (insn
>> 12) & 0xf;
1525 rd0
= (insn
>> 16) & 0xf;
1526 rd1
= (insn
>> 0) & 0xf;
1527 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1528 if (insn
& (1 << 21)) {
1529 if (insn
& (1 << 20))
1530 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1532 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1534 if (insn
& (1 << 20))
1535 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1537 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1539 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1540 gen_op_iwmmxt_set_mup();
1542 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1543 wrd
= (insn
>> 12) & 0xf;
1544 rd0
= (insn
>> 16) & 0xf;
1545 rd1
= (insn
>> 0) & 0xf;
1546 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1547 if (insn
& (1 << 21))
1548 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1550 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1551 if (!(insn
& (1 << 20))) {
1552 iwmmxt_load_reg(cpu_V1
, wrd
);
1553 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1555 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1556 gen_op_iwmmxt_set_mup();
1558 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1559 wrd
= (insn
>> 12) & 0xf;
1560 rd0
= (insn
>> 16) & 0xf;
1561 rd1
= (insn
>> 0) & 0xf;
1562 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1563 switch ((insn
>> 22) & 3) {
1565 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1568 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1571 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1576 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1577 gen_op_iwmmxt_set_mup();
1578 gen_op_iwmmxt_set_cup();
1580 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1581 wrd
= (insn
>> 12) & 0xf;
1582 rd0
= (insn
>> 16) & 0xf;
1583 rd1
= (insn
>> 0) & 0xf;
1584 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1585 if (insn
& (1 << 22)) {
1586 if (insn
& (1 << 20))
1587 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1589 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1591 if (insn
& (1 << 20))
1592 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1594 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1596 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1597 gen_op_iwmmxt_set_mup();
1598 gen_op_iwmmxt_set_cup();
1600 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1601 wrd
= (insn
>> 12) & 0xf;
1602 rd0
= (insn
>> 16) & 0xf;
1603 rd1
= (insn
>> 0) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1605 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1606 tcg_gen_andi_i32(tmp
, tmp
, 7);
1607 iwmmxt_load_reg(cpu_V1
, rd1
);
1608 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1610 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1611 gen_op_iwmmxt_set_mup();
1613 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1614 if (((insn
>> 6) & 3) == 3)
1616 rd
= (insn
>> 12) & 0xf;
1617 wrd
= (insn
>> 16) & 0xf;
1618 tmp
= load_reg(s
, rd
);
1619 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1620 switch ((insn
>> 6) & 3) {
1622 tmp2
= tcg_const_i32(0xff);
1623 tmp3
= tcg_const_i32((insn
& 7) << 3);
1626 tmp2
= tcg_const_i32(0xffff);
1627 tmp3
= tcg_const_i32((insn
& 3) << 4);
1630 tmp2
= tcg_const_i32(0xffffffff);
1631 tmp3
= tcg_const_i32((insn
& 1) << 5);
1637 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1638 tcg_temp_free(tmp3
);
1639 tcg_temp_free(tmp2
);
1641 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1642 gen_op_iwmmxt_set_mup();
1644 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1645 rd
= (insn
>> 12) & 0xf;
1646 wrd
= (insn
>> 16) & 0xf;
1647 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1649 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1651 switch ((insn
>> 22) & 3) {
1653 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1654 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1656 tcg_gen_ext8s_i32(tmp
, tmp
);
1658 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1662 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1663 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1665 tcg_gen_ext16s_i32(tmp
, tmp
);
1667 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1671 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1672 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1675 store_reg(s
, rd
, tmp
);
1677 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1678 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1680 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1681 switch ((insn
>> 22) & 3) {
1683 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1686 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1689 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1692 tcg_gen_shli_i32(tmp
, tmp
, 28);
1696 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1697 if (((insn
>> 6) & 3) == 3)
1699 rd
= (insn
>> 12) & 0xf;
1700 wrd
= (insn
>> 16) & 0xf;
1701 tmp
= load_reg(s
, rd
);
1702 switch ((insn
>> 6) & 3) {
1704 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1707 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1710 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1714 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1715 gen_op_iwmmxt_set_mup();
1717 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1718 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1720 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1722 tcg_gen_mov_i32(tmp2
, tmp
);
1723 switch ((insn
>> 22) & 3) {
1725 for (i
= 0; i
< 7; i
++) {
1726 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1727 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1731 for (i
= 0; i
< 3; i
++) {
1732 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1733 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1737 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1738 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1745 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1746 wrd
= (insn
>> 12) & 0xf;
1747 rd0
= (insn
>> 16) & 0xf;
1748 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1749 switch ((insn
>> 22) & 3) {
1751 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1754 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1757 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1762 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1763 gen_op_iwmmxt_set_mup();
1765 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1766 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1768 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1770 tcg_gen_mov_i32(tmp2
, tmp
);
1771 switch ((insn
>> 22) & 3) {
1773 for (i
= 0; i
< 7; i
++) {
1774 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1775 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1779 for (i
= 0; i
< 3; i
++) {
1780 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1781 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1785 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1786 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1793 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1794 rd
= (insn
>> 12) & 0xf;
1795 rd0
= (insn
>> 16) & 0xf;
1796 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1798 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1800 switch ((insn
>> 22) & 3) {
1802 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1805 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1808 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1811 store_reg(s
, rd
, tmp
);
1813 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1814 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1815 wrd
= (insn
>> 12) & 0xf;
1816 rd0
= (insn
>> 16) & 0xf;
1817 rd1
= (insn
>> 0) & 0xf;
1818 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1819 switch ((insn
>> 22) & 3) {
1821 if (insn
& (1 << 21))
1822 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1824 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1827 if (insn
& (1 << 21))
1828 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1830 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1833 if (insn
& (1 << 21))
1834 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1836 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1841 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1842 gen_op_iwmmxt_set_mup();
1843 gen_op_iwmmxt_set_cup();
1845 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1846 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1847 wrd
= (insn
>> 12) & 0xf;
1848 rd0
= (insn
>> 16) & 0xf;
1849 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1850 switch ((insn
>> 22) & 3) {
1852 if (insn
& (1 << 21))
1853 gen_op_iwmmxt_unpacklsb_M0();
1855 gen_op_iwmmxt_unpacklub_M0();
1858 if (insn
& (1 << 21))
1859 gen_op_iwmmxt_unpacklsw_M0();
1861 gen_op_iwmmxt_unpackluw_M0();
1864 if (insn
& (1 << 21))
1865 gen_op_iwmmxt_unpacklsl_M0();
1867 gen_op_iwmmxt_unpacklul_M0();
1872 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1873 gen_op_iwmmxt_set_mup();
1874 gen_op_iwmmxt_set_cup();
1876 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1877 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1878 wrd
= (insn
>> 12) & 0xf;
1879 rd0
= (insn
>> 16) & 0xf;
1880 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1881 switch ((insn
>> 22) & 3) {
1883 if (insn
& (1 << 21))
1884 gen_op_iwmmxt_unpackhsb_M0();
1886 gen_op_iwmmxt_unpackhub_M0();
1889 if (insn
& (1 << 21))
1890 gen_op_iwmmxt_unpackhsw_M0();
1892 gen_op_iwmmxt_unpackhuw_M0();
1895 if (insn
& (1 << 21))
1896 gen_op_iwmmxt_unpackhsl_M0();
1898 gen_op_iwmmxt_unpackhul_M0();
1903 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1904 gen_op_iwmmxt_set_mup();
1905 gen_op_iwmmxt_set_cup();
1907 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1908 case 0x214: case 0x614: case 0xa14: case 0xe14:
1909 if (((insn
>> 22) & 3) == 0)
1911 wrd
= (insn
>> 12) & 0xf;
1912 rd0
= (insn
>> 16) & 0xf;
1913 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1915 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1919 switch ((insn
>> 22) & 3) {
1921 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1924 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1927 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1931 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1932 gen_op_iwmmxt_set_mup();
1933 gen_op_iwmmxt_set_cup();
1935 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1936 case 0x014: case 0x414: case 0x814: case 0xc14:
1937 if (((insn
>> 22) & 3) == 0)
1939 wrd
= (insn
>> 12) & 0xf;
1940 rd0
= (insn
>> 16) & 0xf;
1941 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1943 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1947 switch ((insn
>> 22) & 3) {
1949 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1952 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1955 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1959 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1960 gen_op_iwmmxt_set_mup();
1961 gen_op_iwmmxt_set_cup();
1963 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
1964 case 0x114: case 0x514: case 0x914: case 0xd14:
1965 if (((insn
>> 22) & 3) == 0)
1967 wrd
= (insn
>> 12) & 0xf;
1968 rd0
= (insn
>> 16) & 0xf;
1969 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1971 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
1975 switch ((insn
>> 22) & 3) {
1977 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1980 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1983 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
1987 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1988 gen_op_iwmmxt_set_mup();
1989 gen_op_iwmmxt_set_cup();
1991 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
1992 case 0x314: case 0x714: case 0xb14: case 0xf14:
1993 if (((insn
>> 22) & 3) == 0)
1995 wrd
= (insn
>> 12) & 0xf;
1996 rd0
= (insn
>> 16) & 0xf;
1997 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1999 switch ((insn
>> 22) & 3) {
2001 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2005 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2008 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2012 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2015 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2019 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2023 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2024 gen_op_iwmmxt_set_mup();
2025 gen_op_iwmmxt_set_cup();
2027 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2028 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2029 wrd
= (insn
>> 12) & 0xf;
2030 rd0
= (insn
>> 16) & 0xf;
2031 rd1
= (insn
>> 0) & 0xf;
2032 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2033 switch ((insn
>> 22) & 3) {
2035 if (insn
& (1 << 21))
2036 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2038 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2041 if (insn
& (1 << 21))
2042 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2044 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2047 if (insn
& (1 << 21))
2048 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2050 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2055 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2056 gen_op_iwmmxt_set_mup();
2058 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2059 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2060 wrd
= (insn
>> 12) & 0xf;
2061 rd0
= (insn
>> 16) & 0xf;
2062 rd1
= (insn
>> 0) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2064 switch ((insn
>> 22) & 3) {
2066 if (insn
& (1 << 21))
2067 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2069 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2072 if (insn
& (1 << 21))
2073 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2075 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2078 if (insn
& (1 << 21))
2079 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2081 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2086 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2087 gen_op_iwmmxt_set_mup();
2089 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2090 case 0x402: case 0x502: case 0x602: case 0x702:
2091 wrd
= (insn
>> 12) & 0xf;
2092 rd0
= (insn
>> 16) & 0xf;
2093 rd1
= (insn
>> 0) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2095 tmp
= tcg_const_i32((insn
>> 20) & 3);
2096 iwmmxt_load_reg(cpu_V1
, rd1
);
2097 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2099 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2100 gen_op_iwmmxt_set_mup();
2102 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2103 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2104 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2105 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2106 wrd
= (insn
>> 12) & 0xf;
2107 rd0
= (insn
>> 16) & 0xf;
2108 rd1
= (insn
>> 0) & 0xf;
2109 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2110 switch ((insn
>> 20) & 0xf) {
2112 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2115 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2118 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2121 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2124 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2127 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2130 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2133 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2136 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2141 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2142 gen_op_iwmmxt_set_mup();
2143 gen_op_iwmmxt_set_cup();
2145 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2146 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2147 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2148 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2149 wrd
= (insn
>> 12) & 0xf;
2150 rd0
= (insn
>> 16) & 0xf;
2151 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2152 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2153 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2155 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2156 gen_op_iwmmxt_set_mup();
2157 gen_op_iwmmxt_set_cup();
2159 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2160 case 0x418: case 0x518: case 0x618: case 0x718:
2161 case 0x818: case 0x918: case 0xa18: case 0xb18:
2162 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2163 wrd
= (insn
>> 12) & 0xf;
2164 rd0
= (insn
>> 16) & 0xf;
2165 rd1
= (insn
>> 0) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2167 switch ((insn
>> 20) & 0xf) {
2169 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2172 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2175 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2178 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2181 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2184 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2187 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2190 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2193 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2198 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2199 gen_op_iwmmxt_set_mup();
2200 gen_op_iwmmxt_set_cup();
2202 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2203 case 0x408: case 0x508: case 0x608: case 0x708:
2204 case 0x808: case 0x908: case 0xa08: case 0xb08:
2205 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2206 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2208 wrd
= (insn
>> 12) & 0xf;
2209 rd0
= (insn
>> 16) & 0xf;
2210 rd1
= (insn
>> 0) & 0xf;
2211 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2212 switch ((insn
>> 22) & 3) {
2214 if (insn
& (1 << 21))
2215 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2217 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2220 if (insn
& (1 << 21))
2221 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2223 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2226 if (insn
& (1 << 21))
2227 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2229 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2232 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2233 gen_op_iwmmxt_set_mup();
2234 gen_op_iwmmxt_set_cup();
2236 case 0x201: case 0x203: case 0x205: case 0x207:
2237 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2238 case 0x211: case 0x213: case 0x215: case 0x217:
2239 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2240 wrd
= (insn
>> 5) & 0xf;
2241 rd0
= (insn
>> 12) & 0xf;
2242 rd1
= (insn
>> 0) & 0xf;
2243 if (rd0
== 0xf || rd1
== 0xf)
2245 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2246 tmp
= load_reg(s
, rd0
);
2247 tmp2
= load_reg(s
, rd1
);
2248 switch ((insn
>> 16) & 0xf) {
2249 case 0x0: /* TMIA */
2250 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2252 case 0x8: /* TMIAPH */
2253 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2255 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2256 if (insn
& (1 << 16))
2257 tcg_gen_shri_i32(tmp
, tmp
, 16);
2258 if (insn
& (1 << 17))
2259 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2260 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2269 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2270 gen_op_iwmmxt_set_mup();
2279 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2280 (ie. an undefined instruction). */
2281 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2283 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2286 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2287 /* Multiply with Internal Accumulate Format */
2288 rd0
= (insn
>> 12) & 0xf;
2290 acc
= (insn
>> 5) & 7;
2295 tmp
= load_reg(s
, rd0
);
2296 tmp2
= load_reg(s
, rd1
);
2297 switch ((insn
>> 16) & 0xf) {
2299 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2301 case 0x8: /* MIAPH */
2302 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2304 case 0xc: /* MIABB */
2305 case 0xd: /* MIABT */
2306 case 0xe: /* MIATB */
2307 case 0xf: /* MIATT */
2308 if (insn
& (1 << 16))
2309 tcg_gen_shri_i32(tmp
, tmp
, 16);
2310 if (insn
& (1 << 17))
2311 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2312 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2320 gen_op_iwmmxt_movq_wRn_M0(acc
);
2324 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2325 /* Internal Accumulator Access Format */
2326 rdhi
= (insn
>> 16) & 0xf;
2327 rdlo
= (insn
>> 12) & 0xf;
2333 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2334 iwmmxt_load_reg(cpu_V0
, acc
);
2335 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2336 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2337 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2338 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2340 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2341 iwmmxt_store_reg(cpu_V0
, acc
);
2349 /* Disassemble system coprocessor instruction. Return nonzero if
2350 instruction is not defined. */
2351 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2354 uint32_t rd
= (insn
>> 12) & 0xf;
2355 uint32_t cp
= (insn
>> 8) & 0xf;
2360 if (insn
& ARM_CP_RW_BIT
) {
2361 if (!env
->cp
[cp
].cp_read
)
2363 gen_set_pc_im(s
->pc
);
2365 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2366 store_reg(s
, rd
, tmp
);
2368 if (!env
->cp
[cp
].cp_write
)
2370 gen_set_pc_im(s
->pc
);
2371 tmp
= load_reg(s
, rd
);
2372 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2378 static int cp15_user_ok(uint32_t insn
)
2380 int cpn
= (insn
>> 16) & 0xf;
2381 int cpm
= insn
& 0xf;
2382 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2384 if (cpn
== 13 && cpm
== 0) {
2386 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2390 /* ISB, DSB, DMB. */
2391 if ((cpm
== 5 && op
== 4)
2392 || (cpm
== 10 && (op
== 4 || op
== 5)))
2398 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2399 instruction is not defined. */
2400 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2405 /* M profile cores use memory mapped registers instead of cp15. */
2406 if (arm_feature(env
, ARM_FEATURE_M
) ||
2407 !arm_feature(env
, ARM_FEATURE_CP15
)) {
2411 if ((insn
& (1 << 25)) == 0) {
2412 if (insn
& (1 << 20)) {
2416 /* mcrr. Used for block cache operations, so implement as no-op. */
2419 if ((insn
& (1 << 4)) == 0) {
2423 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2426 if ((insn
& 0x0fff0fff) == 0x0e070f90
2427 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2428 /* Wait for interrupt. */
2429 gen_set_pc_im(s
->pc
);
2430 s
->is_jmp
= DISAS_WFI
;
2433 rd
= (insn
>> 12) & 0xf;
2434 if (insn
& ARM_CP_RW_BIT
) {
2436 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2437 /* If the destination register is r15 then sets condition codes. */
2439 store_reg(s
, rd
, tmp
);
2443 tmp
= load_reg(s
, rd
);
2444 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2446 /* Normally we would always end the TB here, but Linux
2447 * arch/arm/mach-pxa/sleep.S expects two instructions following
2448 * an MMU enable to execute from cache. Imitate this behaviour. */
2449 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2450 (insn
& 0x0fff0fff) != 0x0e010f10)
2456 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2457 #define VFP_SREG(insn, bigbit, smallbit) \
2458 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2459 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2460 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2461 reg = (((insn) >> (bigbit)) & 0x0f) \
2462 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2464 if (insn & (1 << (smallbit))) \
2466 reg = ((insn) >> (bigbit)) & 0x0f; \
2469 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2470 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2471 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2472 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2473 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2474 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2476 /* Move between integer and VFP cores. */
2477 static TCGv
gen_vfp_mrs(void)
2479 TCGv tmp
= new_tmp();
2480 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2484 static void gen_vfp_msr(TCGv tmp
)
2486 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2491 vfp_enabled(CPUState
* env
)
2493 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2496 static void gen_neon_dup_u8(TCGv var
, int shift
)
2498 TCGv tmp
= new_tmp();
2500 tcg_gen_shri_i32(var
, var
, shift
);
2501 tcg_gen_ext8u_i32(var
, var
);
2502 tcg_gen_shli_i32(tmp
, var
, 8);
2503 tcg_gen_or_i32(var
, var
, tmp
);
2504 tcg_gen_shli_i32(tmp
, var
, 16);
2505 tcg_gen_or_i32(var
, var
, tmp
);
2509 static void gen_neon_dup_low16(TCGv var
)
2511 TCGv tmp
= new_tmp();
2512 tcg_gen_ext16u_i32(var
, var
);
2513 tcg_gen_shli_i32(tmp
, var
, 16);
2514 tcg_gen_or_i32(var
, var
, tmp
);
2518 static void gen_neon_dup_high16(TCGv var
)
2520 TCGv tmp
= new_tmp();
2521 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2522 tcg_gen_shri_i32(tmp
, var
, 16);
2523 tcg_gen_or_i32(var
, var
, tmp
);
2527 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2528 (ie. an undefined instruction). */
2529 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2531 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2537 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2540 if (!vfp_enabled(env
)) {
2541 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2542 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2544 rn
= (insn
>> 16) & 0xf;
2545 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2546 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2549 dp
= ((insn
& 0xf00) == 0xb00);
2550 switch ((insn
>> 24) & 0xf) {
2552 if (insn
& (1 << 4)) {
2553 /* single register transfer */
2554 rd
= (insn
>> 12) & 0xf;
2559 VFP_DREG_N(rn
, insn
);
2562 if (insn
& 0x00c00060
2563 && !arm_feature(env
, ARM_FEATURE_NEON
))
2566 pass
= (insn
>> 21) & 1;
2567 if (insn
& (1 << 22)) {
2569 offset
= ((insn
>> 5) & 3) * 8;
2570 } else if (insn
& (1 << 5)) {
2572 offset
= (insn
& (1 << 6)) ? 16 : 0;
2577 if (insn
& ARM_CP_RW_BIT
) {
2579 tmp
= neon_load_reg(rn
, pass
);
2583 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2584 if (insn
& (1 << 23))
2590 if (insn
& (1 << 23)) {
2592 tcg_gen_shri_i32(tmp
, tmp
, 16);
2598 tcg_gen_sari_i32(tmp
, tmp
, 16);
2607 store_reg(s
, rd
, tmp
);
2610 tmp
= load_reg(s
, rd
);
2611 if (insn
& (1 << 23)) {
2614 gen_neon_dup_u8(tmp
, 0);
2615 } else if (size
== 1) {
2616 gen_neon_dup_low16(tmp
);
2618 for (n
= 0; n
<= pass
* 2; n
++) {
2620 tcg_gen_mov_i32(tmp2
, tmp
);
2621 neon_store_reg(rn
, n
, tmp2
);
2623 neon_store_reg(rn
, n
, tmp
);
2628 tmp2
= neon_load_reg(rn
, pass
);
2629 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2633 tmp2
= neon_load_reg(rn
, pass
);
2634 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2640 neon_store_reg(rn
, pass
, tmp
);
2644 if ((insn
& 0x6f) != 0x00)
2646 rn
= VFP_SREG_N(insn
);
2647 if (insn
& ARM_CP_RW_BIT
) {
2649 if (insn
& (1 << 21)) {
2650 /* system register */
2655 /* VFP2 allows access to FSID from userspace.
2656 VFP3 restricts all id registers to privileged
2659 && arm_feature(env
, ARM_FEATURE_VFP3
))
2661 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2666 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2668 case ARM_VFP_FPINST
:
2669 case ARM_VFP_FPINST2
:
2670 /* Not present in VFP3. */
2672 || arm_feature(env
, ARM_FEATURE_VFP3
))
2674 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2678 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2679 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2682 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2688 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2690 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2696 gen_mov_F0_vreg(0, rn
);
2697 tmp
= gen_vfp_mrs();
2700 /* Set the 4 flag bits in the CPSR. */
2704 store_reg(s
, rd
, tmp
);
2708 tmp
= load_reg(s
, rd
);
2709 if (insn
& (1 << 21)) {
2711 /* system register */
2716 /* Writes are ignored. */
2719 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2726 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2729 case ARM_VFP_FPINST
:
2730 case ARM_VFP_FPINST2
:
2731 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2738 gen_mov_vreg_F0(0, rn
);
2743 /* data processing */
2744 /* The opcode is in bits 23, 21, 20 and 6. */
2745 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2749 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2751 /* rn is register number */
2752 VFP_DREG_N(rn
, insn
);
2755 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2756 /* Integer or single precision destination. */
2757 rd
= VFP_SREG_D(insn
);
2759 VFP_DREG_D(rd
, insn
);
2762 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2763 /* Integer source. */
2764 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2766 VFP_DREG_M(rm
, insn
);
2769 rn
= VFP_SREG_N(insn
);
2770 if (op
== 15 && rn
== 15) {
2771 /* Double precision destination. */
2772 VFP_DREG_D(rd
, insn
);
2774 rd
= VFP_SREG_D(insn
);
2776 rm
= VFP_SREG_M(insn
);
2779 veclen
= env
->vfp
.vec_len
;
2780 if (op
== 15 && rn
> 3)
2783 /* Shut up compiler warnings. */
2794 /* Figure out what type of vector operation this is. */
2795 if ((rd
& bank_mask
) == 0) {
2800 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2802 delta_d
= env
->vfp
.vec_stride
+ 1;
2804 if ((rm
& bank_mask
) == 0) {
2805 /* mixed scalar/vector */
2814 /* Load the initial operands. */
2819 /* Integer source */
2820 gen_mov_F0_vreg(0, rm
);
2825 gen_mov_F0_vreg(dp
, rd
);
2826 gen_mov_F1_vreg(dp
, rm
);
2830 /* Compare with zero */
2831 gen_mov_F0_vreg(dp
, rd
);
2842 /* Source and destination the same. */
2843 gen_mov_F0_vreg(dp
, rd
);
2846 /* One source operand. */
2847 gen_mov_F0_vreg(dp
, rm
);
2851 /* Two source operands. */
2852 gen_mov_F0_vreg(dp
, rn
);
2853 gen_mov_F1_vreg(dp
, rm
);
2857 /* Perform the calculation. */
2859 case 0: /* mac: fd + (fn * fm) */
2861 gen_mov_F1_vreg(dp
, rd
);
2864 case 1: /* nmac: fd - (fn * fm) */
2867 gen_mov_F1_vreg(dp
, rd
);
2870 case 2: /* msc: -fd + (fn * fm) */
2872 gen_mov_F1_vreg(dp
, rd
);
2875 case 3: /* nmsc: -fd - (fn * fm) */
2878 gen_mov_F1_vreg(dp
, rd
);
2881 case 4: /* mul: fn * fm */
2884 case 5: /* nmul: -(fn * fm) */
2888 case 6: /* add: fn + fm */
2891 case 7: /* sub: fn - fm */
2894 case 8: /* div: fn / fm */
2897 case 14: /* fconst */
2898 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2901 n
= (insn
<< 12) & 0x80000000;
2902 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2909 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
2916 tcg_gen_movi_i32(cpu_F0s
, n
);
2919 case 15: /* extension space */
2942 case 11: /* cmpez */
2946 case 15: /* single<->double conversion */
2948 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
2950 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
2952 case 16: /* fuito */
2955 case 17: /* fsito */
2958 case 20: /* fshto */
2959 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2961 gen_vfp_shto(dp
, 16 - rm
);
2963 case 21: /* fslto */
2964 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2966 gen_vfp_slto(dp
, 32 - rm
);
2968 case 22: /* fuhto */
2969 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2971 gen_vfp_uhto(dp
, 16 - rm
);
2973 case 23: /* fulto */
2974 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2976 gen_vfp_ulto(dp
, 32 - rm
);
2978 case 24: /* ftoui */
2981 case 25: /* ftouiz */
2984 case 26: /* ftosi */
2987 case 27: /* ftosiz */
2990 case 28: /* ftosh */
2991 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2993 gen_vfp_tosh(dp
, 16 - rm
);
2995 case 29: /* ftosl */
2996 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2998 gen_vfp_tosl(dp
, 32 - rm
);
3000 case 30: /* ftouh */
3001 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3003 gen_vfp_touh(dp
, 16 - rm
);
3005 case 31: /* ftoul */
3006 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3008 gen_vfp_toul(dp
, 32 - rm
);
3010 default: /* undefined */
3011 printf ("rn:%d\n", rn
);
3015 default: /* undefined */
3016 printf ("op:%d\n", op
);
3020 /* Write back the result. */
3021 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3022 ; /* Comparison, do nothing. */
3023 else if (op
== 15 && rn
> 17)
3024 /* Integer result. */
3025 gen_mov_vreg_F0(0, rd
);
3026 else if (op
== 15 && rn
== 15)
3028 gen_mov_vreg_F0(!dp
, rd
);
3030 gen_mov_vreg_F0(dp
, rd
);
3032 /* break out of the loop if we have finished */
3036 if (op
== 15 && delta_m
== 0) {
3037 /* single source one-many */
3039 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3041 gen_mov_vreg_F0(dp
, rd
);
3045 /* Setup the next operands. */
3047 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3051 /* One source operand. */
3052 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3054 gen_mov_F0_vreg(dp
, rm
);
3056 /* Two source operands. */
3057 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3059 gen_mov_F0_vreg(dp
, rn
);
3061 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3063 gen_mov_F1_vreg(dp
, rm
);
3071 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3072 /* two-register transfer */
3073 rn
= (insn
>> 16) & 0xf;
3074 rd
= (insn
>> 12) & 0xf;
3076 VFP_DREG_M(rm
, insn
);
3078 rm
= VFP_SREG_M(insn
);
3081 if (insn
& ARM_CP_RW_BIT
) {
3084 gen_mov_F0_vreg(0, rm
* 2);
3085 tmp
= gen_vfp_mrs();
3086 store_reg(s
, rd
, tmp
);
3087 gen_mov_F0_vreg(0, rm
* 2 + 1);
3088 tmp
= gen_vfp_mrs();
3089 store_reg(s
, rn
, tmp
);
3091 gen_mov_F0_vreg(0, rm
);
3092 tmp
= gen_vfp_mrs();
3093 store_reg(s
, rn
, tmp
);
3094 gen_mov_F0_vreg(0, rm
+ 1);
3095 tmp
= gen_vfp_mrs();
3096 store_reg(s
, rd
, tmp
);
3101 tmp
= load_reg(s
, rd
);
3103 gen_mov_vreg_F0(0, rm
* 2);
3104 tmp
= load_reg(s
, rn
);
3106 gen_mov_vreg_F0(0, rm
* 2 + 1);
3108 tmp
= load_reg(s
, rn
);
3110 gen_mov_vreg_F0(0, rm
);
3111 tmp
= load_reg(s
, rd
);
3113 gen_mov_vreg_F0(0, rm
+ 1);
3118 rn
= (insn
>> 16) & 0xf;
3120 VFP_DREG_D(rd
, insn
);
3122 rd
= VFP_SREG_D(insn
);
3123 if (s
->thumb
&& rn
== 15) {
3125 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3127 addr
= load_reg(s
, rn
);
3129 if ((insn
& 0x01200000) == 0x01000000) {
3130 /* Single load/store */
3131 offset
= (insn
& 0xff) << 2;
3132 if ((insn
& (1 << 23)) == 0)
3134 tcg_gen_addi_i32(addr
, addr
, offset
);
3135 if (insn
& (1 << 20)) {
3136 gen_vfp_ld(s
, dp
, addr
);
3137 gen_mov_vreg_F0(dp
, rd
);
3139 gen_mov_F0_vreg(dp
, rd
);
3140 gen_vfp_st(s
, dp
, addr
);
3144 /* load/store multiple */
3146 n
= (insn
>> 1) & 0x7f;
3150 if (insn
& (1 << 24)) /* pre-decrement */
3151 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3157 for (i
= 0; i
< n
; i
++) {
3158 if (insn
& ARM_CP_RW_BIT
) {
3160 gen_vfp_ld(s
, dp
, addr
);
3161 gen_mov_vreg_F0(dp
, rd
+ i
);
3164 gen_mov_F0_vreg(dp
, rd
+ i
);
3165 gen_vfp_st(s
, dp
, addr
);
3167 tcg_gen_addi_i32(addr
, addr
, offset
);
3169 if (insn
& (1 << 21)) {
3171 if (insn
& (1 << 24))
3172 offset
= -offset
* n
;
3173 else if (dp
&& (insn
& 1))
3179 tcg_gen_addi_i32(addr
, addr
, offset
);
3180 store_reg(s
, rn
, addr
);
3188 /* Should never happen. */
3194 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3196 TranslationBlock
*tb
;
3199 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3201 gen_set_pc_im(dest
);
3202 tcg_gen_exit_tb((intptr_t)tb
+ n
);
3204 gen_set_pc_im(dest
);
3209 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3211 if (unlikely(s
->singlestep_enabled
)) {
3212 /* An indirect jump so that we still trigger the debug exception. */
3217 gen_goto_tb(s
, 0, dest
);
3218 s
->is_jmp
= DISAS_TB_JUMP
;
3222 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3225 tcg_gen_sari_i32(t0
, t0
, 16);
3229 tcg_gen_sari_i32(t1
, t1
, 16);
3232 tcg_gen_mul_i32(t0
, t0
, t1
);
3235 /* Return the mask of PSR bits set by a MSR instruction. */
3236 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3240 if (flags
& (1 << 0))
3242 if (flags
& (1 << 1))
3244 if (flags
& (1 << 2))
3246 if (flags
& (1 << 3))
3249 /* Mask out undefined bits. */
3250 mask
&= ~CPSR_RESERVED
;
3251 if (!arm_feature(env
, ARM_FEATURE_V6
))
3252 mask
&= ~(CPSR_E
| CPSR_GE
);
3253 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3255 /* Mask out execution state bits. */
3258 /* Mask out privileged bits. */
3264 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3265 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3269 /* ??? This is also undefined in system mode. */
3273 tmp
= load_cpu_field(spsr
);
3274 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3275 tcg_gen_andi_i32(t0
, t0
, mask
);
3276 tcg_gen_or_i32(tmp
, tmp
, t0
);
3277 store_cpu_field(tmp
, spsr
);
3279 gen_set_cpsr(t0
, mask
);
3286 /* Returns nonzero if access to the PSR is not permitted. */
3287 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3291 tcg_gen_movi_i32(tmp
, val
);
3292 return gen_set_psr(s
, mask
, spsr
, tmp
);
3295 /* Generate an old-style exception return. Marks pc as dead. */
3296 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3299 store_reg(s
, 15, pc
);
3300 tmp
= load_cpu_field(spsr
);
3301 gen_set_cpsr(tmp
, 0xffffffff);
3303 s
->is_jmp
= DISAS_UPDATE
;
3306 /* Generate a v6 exception return. Marks both values as dead. */
3307 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3309 gen_set_cpsr(cpsr
, 0xffffffff);
3311 store_reg(s
, 15, pc
);
3312 s
->is_jmp
= DISAS_UPDATE
;
3316 gen_set_condexec (DisasContext
*s
)
3318 if (s
->condexec_mask
) {
3319 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3320 TCGv tmp
= new_tmp();
3321 tcg_gen_movi_i32(tmp
, val
);
3322 store_cpu_field(tmp
, condexec_bits
);
3326 static void gen_nop_hint(DisasContext
*s
, int val
)
3330 gen_set_pc_im(s
->pc
);
3331 s
->is_jmp
= DISAS_WFI
;
3335 /* TODO: Implement SEV and WFE. May help SMP performance. */
3341 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3343 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3346 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3347 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3348 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3354 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3357 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3358 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3359 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3364 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3365 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3366 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3367 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3368 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3370 /* FIXME: This is wrong. They set the wrong overflow bit. */
3371 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3372 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3373 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3374 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3376 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3377 switch ((size << 1) | u) { \
3379 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3382 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3385 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3388 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3391 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3394 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3396 default: return 1; \
3399 #define GEN_NEON_INTEGER_OP(name) do { \
3400 switch ((size << 1) | u) { \
3402 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3405 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3408 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3411 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3414 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3417 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3419 default: return 1; \
3422 static TCGv
neon_load_scratch(int scratch
)
3424 TCGv tmp
= new_tmp();
3425 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3429 static void neon_store_scratch(int scratch
, TCGv var
)
3431 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3435 static inline TCGv
neon_get_scalar(int size
, int reg
)
3439 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3441 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3443 gen_neon_dup_low16(tmp
);
3445 gen_neon_dup_high16(tmp
);
3451 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3459 tcg_gen_andi_i32(rd
, t0
, 0xff);
3460 tcg_gen_shri_i32(tmp
, t0
, 8);
3461 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3462 tcg_gen_or_i32(rd
, rd
, tmp
);
3463 tcg_gen_shli_i32(tmp
, t1
, 16);
3464 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3465 tcg_gen_or_i32(rd
, rd
, tmp
);
3466 tcg_gen_shli_i32(tmp
, t1
, 8);
3467 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3468 tcg_gen_or_i32(rd
, rd
, tmp
);
3470 tcg_gen_shri_i32(rm
, t0
, 8);
3471 tcg_gen_andi_i32(rm
, rm
, 0xff);
3472 tcg_gen_shri_i32(tmp
, t0
, 16);
3473 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3474 tcg_gen_or_i32(rm
, rm
, tmp
);
3475 tcg_gen_shli_i32(tmp
, t1
, 8);
3476 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3477 tcg_gen_or_i32(rm
, rm
, tmp
);
3478 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3479 tcg_gen_or_i32(t1
, rm
, tmp
);
3480 tcg_gen_mov_i32(t0
, rd
);
3487 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3495 tcg_gen_andi_i32(rd
, t0
, 0xff);
3496 tcg_gen_shli_i32(tmp
, t1
, 8);
3497 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3498 tcg_gen_or_i32(rd
, rd
, tmp
);
3499 tcg_gen_shli_i32(tmp
, t0
, 16);
3500 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3501 tcg_gen_or_i32(rd
, rd
, tmp
);
3502 tcg_gen_shli_i32(tmp
, t1
, 24);
3503 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3504 tcg_gen_or_i32(rd
, rd
, tmp
);
3506 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3507 tcg_gen_shri_i32(tmp
, t0
, 8);
3508 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3509 tcg_gen_or_i32(rm
, rm
, tmp
);
3510 tcg_gen_shri_i32(tmp
, t1
, 8);
3511 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3512 tcg_gen_or_i32(rm
, rm
, tmp
);
3513 tcg_gen_shri_i32(tmp
, t0
, 16);
3514 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3515 tcg_gen_or_i32(t1
, rm
, tmp
);
3516 tcg_gen_mov_i32(t0
, rd
);
3523 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3530 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3531 tcg_gen_shli_i32(tmp2
, t1
, 16);
3532 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3533 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3534 tcg_gen_shri_i32(tmp2
, t0
, 16);
3535 tcg_gen_or_i32(t1
, t1
, tmp2
);
3536 tcg_gen_mov_i32(t0
, tmp
);
3542 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3547 for (n
= 0; n
< q
+ 1; n
+= 2) {
3548 t0
= neon_load_reg(reg
, n
);
3549 t1
= neon_load_reg(reg
, n
+ 1);
3551 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3552 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3553 case 2: /* no-op */; break;
3556 neon_store_scratch(tmp
+ n
, t0
);
3557 neon_store_scratch(tmp
+ n
+ 1, t1
);
3561 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3568 tcg_gen_shli_i32(rd
, t0
, 8);
3569 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3570 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3571 tcg_gen_or_i32(rd
, rd
, tmp
);
3573 tcg_gen_shri_i32(t1
, t1
, 8);
3574 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3575 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3576 tcg_gen_or_i32(t1
, t1
, tmp
);
3577 tcg_gen_mov_i32(t0
, rd
);
3583 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3590 tcg_gen_shli_i32(rd
, t0
, 16);
3591 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3592 tcg_gen_or_i32(rd
, rd
, tmp
);
3593 tcg_gen_shri_i32(t1
, t1
, 16);
3594 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3595 tcg_gen_or_i32(t1
, t1
, tmp
);
3596 tcg_gen_mov_i32(t0
, rd
);
3607 } neon_ls_element_type
[11] = {
3621 /* Translate a NEON load/store element instruction. Return nonzero if the
3622 instruction is invalid. */
3623 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3640 if (!vfp_enabled(env
))
3642 VFP_DREG_D(rd
, insn
);
3643 rn
= (insn
>> 16) & 0xf;
3645 load
= (insn
& (1 << 21)) != 0;
3647 if ((insn
& (1 << 23)) == 0) {
3648 /* Load store all elements. */
3649 op
= (insn
>> 8) & 0xf;
3650 size
= (insn
>> 6) & 3;
3651 if (op
> 10 || size
== 3)
3653 nregs
= neon_ls_element_type
[op
].nregs
;
3654 interleave
= neon_ls_element_type
[op
].interleave
;
3655 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3656 stride
= (1 << size
) * interleave
;
3657 for (reg
= 0; reg
< nregs
; reg
++) {
3658 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3659 tcg_gen_add_i32(addr
, cpu_R
[rn
], (1 << size
) * reg
);
3660 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3661 tcg_gen_add_i32(addr
, cpu_R
[rn
], 1 << size
);
3663 for (pass
= 0; pass
< 2; pass
++) {
3666 tmp
= gen_ld32(addr
, IS_USER(s
));
3667 neon_store_reg(rd
, pass
, tmp
);
3669 tmp
= neon_load_reg(rd
, pass
);
3670 gen_st32(tmp
, addr
, IS_USER(s
));
3672 tcg_gen_addi_i32(addr
, addr
, stride
);
3673 } else if (size
== 1) {
3675 tmp
= gen_ld16u(addr
, IS_USER(s
));
3676 tcg_gen_addi_i32(addr
, addr
, stride
);
3677 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3678 tcg_gen_addi_i32(addr
, addr
, stride
);
3679 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3681 neon_store_reg(rd
, pass
, tmp
);
3683 tmp
= neon_load_reg(rd
, pass
);
3685 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3686 gen_st16(tmp
, addr
, IS_USER(s
));
3687 tcg_gen_addi_i32(addr
, addr
, stride
);
3688 gen_st16(tmp2
, addr
, IS_USER(s
));
3689 tcg_gen_addi_i32(addr
, addr
, stride
);
3691 } else /* size == 0 */ {
3694 for (n
= 0; n
< 4; n
++) {
3695 tmp
= gen_ld8u(addr
, IS_USER(s
));
3696 tcg_gen_addi_i32(addr
, addr
, stride
);
3700 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3704 neon_store_reg(rd
, pass
, tmp2
);
3706 tmp2
= neon_load_reg(rd
, pass
);
3707 for (n
= 0; n
< 4; n
++) {
3710 tcg_gen_mov_i32(tmp
, tmp2
);
3712 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3714 gen_st8(tmp
, addr
, IS_USER(s
));
3715 tcg_gen_addi_i32(addr
, addr
, stride
);
3721 rd
+= neon_ls_element_type
[op
].spacing
;
3725 size
= (insn
>> 10) & 3;
3727 /* Load single element to all lanes. */
3730 size
= (insn
>> 6) & 3;
3731 nregs
= ((insn
>> 8) & 3) + 1;
3732 stride
= (insn
& (1 << 5)) ? 2 : 1;
3733 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3734 for (reg
= 0; reg
< nregs
; reg
++) {
3737 tmp
= gen_ld8u(addr
, IS_USER(s
));
3738 gen_neon_dup_u8(tmp
, 0);
3741 tmp
= gen_ld16u(addr
, IS_USER(s
));
3742 gen_neon_dup_low16(tmp
);
3745 tmp
= gen_ld32(addr
, IS_USER(s
));
3749 default: /* Avoid compiler warnings. */
3752 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3754 tcg_gen_mov_i32(tmp2
, tmp
);
3755 neon_store_reg(rd
, 0, tmp2
);
3756 neon_store_reg(rd
, 1, tmp
);
3759 stride
= (1 << size
) * nregs
;
3761 /* Single element. */
3762 pass
= (insn
>> 7) & 1;
3765 shift
= ((insn
>> 5) & 3) * 8;
3769 shift
= ((insn
>> 6) & 1) * 16;
3770 stride
= (insn
& (1 << 5)) ? 2 : 1;
3774 stride
= (insn
& (1 << 6)) ? 2 : 1;
3779 nregs
= ((insn
>> 8) & 3) + 1;
3780 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3781 for (reg
= 0; reg
< nregs
; reg
++) {
3785 tmp
= gen_ld8u(addr
, IS_USER(s
));
3788 tmp
= gen_ld16u(addr
, IS_USER(s
));
3791 tmp
= gen_ld32(addr
, IS_USER(s
));
3793 default: /* Avoid compiler warnings. */
3797 tmp2
= neon_load_reg(rd
, pass
);
3798 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3801 neon_store_reg(rd
, pass
, tmp
);
3802 } else { /* Store */
3803 tmp
= neon_load_reg(rd
, pass
);
3805 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3808 gen_st8(tmp
, addr
, IS_USER(s
));
3811 gen_st16(tmp
, addr
, IS_USER(s
));
3814 gen_st32(tmp
, addr
, IS_USER(s
));
3819 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3821 stride
= nregs
* (1 << size
);
3828 base
= load_reg(s
, rn
);
3830 tcg_gen_addi_i32(base
, base
, stride
);
3833 index
= load_reg(s
, rm
);
3834 tcg_gen_add_i32(base
, base
, index
);
3837 store_reg(s
, rn
, base
);
3842 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3843 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3845 tcg_gen_and_i32(t
, t
, c
);
3846 tcg_gen_bic_i32(f
, f
, c
);
3847 tcg_gen_or_i32(dest
, t
, f
);
3850 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3853 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3854 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3855 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3860 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3863 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3864 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3865 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3870 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3873 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3874 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3875 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3880 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3886 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3887 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3892 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3893 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3900 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3901 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3906 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3907 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3914 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3918 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3919 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3920 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3925 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3926 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3927 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3934 static inline void gen_neon_addl(int size
)
3937 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3938 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3939 case 2: tcg_gen_add_i64(CPU_V001
); break;
3944 static inline void gen_neon_subl(int size
)
3947 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
3948 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
3949 case 2: tcg_gen_sub_i64(CPU_V001
); break;
3954 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
3957 case 0: gen_helper_neon_negl_u16(var
, var
); break;
3958 case 1: gen_helper_neon_negl_u32(var
, var
); break;
3959 case 2: gen_helper_neon_negl_u64(var
, var
); break;
3964 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
3967 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
3968 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
3973 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
3977 switch ((size
<< 1) | u
) {
3978 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
3979 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
3980 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
3981 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
3983 tmp
= gen_muls_i64_i32(a
, b
);
3984 tcg_gen_mov_i64(dest
, tmp
);
3987 tmp
= gen_mulu_i64_i32(a
, b
);
3988 tcg_gen_mov_i64(dest
, tmp
);
3994 /* Translate a NEON data processing instruction. Return nonzero if the
3995 instruction is invalid.
3996 We process data in a mixture of 32-bit and 64-bit chunks.
3997 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
3999 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4017 if (!vfp_enabled(env
))
4019 q
= (insn
& (1 << 6)) != 0;
4020 u
= (insn
>> 24) & 1;
4021 VFP_DREG_D(rd
, insn
);
4022 VFP_DREG_N(rn
, insn
);
4023 VFP_DREG_M(rm
, insn
);
4024 size
= (insn
>> 20) & 3;
4025 if ((insn
& (1 << 23)) == 0) {
4026 /* Three register same length. */
4027 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4028 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4029 || op
== 10 || op
== 11 || op
== 16)) {
4030 /* 64-bit element instructions. */
4031 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4032 neon_load_reg64(cpu_V0
, rn
+ pass
);
4033 neon_load_reg64(cpu_V1
, rm
+ pass
);
4037 gen_helper_neon_add_saturate_u64(CPU_V001
);
4039 gen_helper_neon_add_saturate_s64(CPU_V001
);
4044 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4046 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4051 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4053 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4058 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4061 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4065 case 10: /* VRSHL */
4067 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4069 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4072 case 11: /* VQRSHL */
4074 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4077 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4083 tcg_gen_sub_i64(CPU_V001
);
4085 tcg_gen_add_i64(CPU_V001
);
4091 neon_store_reg64(cpu_V0
, rd
+ pass
);
4098 case 10: /* VRSHL */
4099 case 11: /* VQRSHL */
4102 /* Shift instruction operands are reversed. */
4109 case 20: /* VPMAX */
4110 case 21: /* VPMIN */
4111 case 23: /* VPADD */
4114 case 26: /* VPADD (float) */
4115 pairwise
= (u
&& size
< 2);
4117 case 30: /* VPMIN/VPMAX (float) */
4125 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4134 tmp
= neon_load_reg(rn
, n
);
4135 tmp2
= neon_load_reg(rn
, n
+ 1);
4137 tmp
= neon_load_reg(rm
, n
);
4138 tmp2
= neon_load_reg(rm
, n
+ 1);
4142 tmp
= neon_load_reg(rn
, pass
);
4143 tmp2
= neon_load_reg(rm
, pass
);
4147 GEN_NEON_INTEGER_OP(hadd
);
4150 GEN_NEON_INTEGER_OP_ENV(qadd
);
4152 case 2: /* VRHADD */
4153 GEN_NEON_INTEGER_OP(rhadd
);
4155 case 3: /* Logic ops. */
4156 switch ((u
<< 2) | size
) {
4158 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4161 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4164 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4167 tcg_gen_not_i32(tmp2
, tmp2
);
4168 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4171 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4174 tmp3
= neon_load_reg(rd
, pass
);
4175 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4179 tmp3
= neon_load_reg(rd
, pass
);
4180 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4184 tmp3
= neon_load_reg(rd
, pass
);
4185 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4191 GEN_NEON_INTEGER_OP(hsub
);
4194 GEN_NEON_INTEGER_OP_ENV(qsub
);
4197 GEN_NEON_INTEGER_OP(cgt
);
4200 GEN_NEON_INTEGER_OP(cge
);
4203 GEN_NEON_INTEGER_OP(shl
);
4206 GEN_NEON_INTEGER_OP_ENV(qshl
);
4208 case 10: /* VRSHL */
4209 GEN_NEON_INTEGER_OP(rshl
);
4211 case 11: /* VQRSHL */
4212 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4215 GEN_NEON_INTEGER_OP(max
);
4218 GEN_NEON_INTEGER_OP(min
);
4221 GEN_NEON_INTEGER_OP(abd
);
4224 GEN_NEON_INTEGER_OP(abd
);
4226 tmp2
= neon_load_reg(rd
, pass
);
4227 gen_neon_add(size
, tmp
, tmp2
);
4230 if (!u
) { /* VADD */
4231 if (gen_neon_add(size
, tmp
, tmp2
))
4235 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4236 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4237 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4243 if (!u
) { /* VTST */
4245 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4246 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4247 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4252 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4253 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4254 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4259 case 18: /* Multiply. */
4261 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4262 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4263 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4267 tmp2
= neon_load_reg(rd
, pass
);
4269 gen_neon_rsb(size
, tmp
, tmp2
);
4271 gen_neon_add(size
, tmp
, tmp2
);
4275 if (u
) { /* polynomial */
4276 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4277 } else { /* Integer */
4279 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4280 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4281 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4286 case 20: /* VPMAX */
4287 GEN_NEON_INTEGER_OP(pmax
);
4289 case 21: /* VPMIN */
4290 GEN_NEON_INTEGER_OP(pmin
);
4292 case 22: /* Hultiply high. */
4293 if (!u
) { /* VQDMULH */
4295 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4296 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4299 } else { /* VQRDHMUL */
4301 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4302 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4307 case 23: /* VPADD */
4311 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4312 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4313 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4317 case 26: /* Floating point arithnetic. */
4318 switch ((u
<< 2) | size
) {
4320 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4323 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4326 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4329 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4335 case 27: /* Float multiply. */
4336 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4339 tmp2
= neon_load_reg(rd
, pass
);
4341 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4343 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4347 case 28: /* Float compare. */
4349 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4352 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4354 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4357 case 29: /* Float compare absolute. */
4361 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4363 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4365 case 30: /* Float min/max. */
4367 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4369 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4373 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4375 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4382 /* Save the result. For elementwise operations we can put it
4383 straight into the destination register. For pairwise operations
4384 we have to be careful to avoid clobbering the source operands. */
4385 if (pairwise
&& rd
== rm
) {
4386 neon_store_scratch(pass
, tmp
);
4388 neon_store_reg(rd
, pass
, tmp
);
4392 if (pairwise
&& rd
== rm
) {
4393 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4394 tmp
= neon_load_scratch(pass
);
4395 neon_store_reg(rd
, pass
, tmp
);
4398 /* End of 3 register same size operations. */
4399 } else if (insn
& (1 << 4)) {
4400 if ((insn
& 0x00380080) != 0) {
4401 /* Two registers and shift. */
4402 op
= (insn
>> 8) & 0xf;
4403 if (insn
& (1 << 7)) {
4408 while ((insn
& (1 << (size
+ 19))) == 0)
4411 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4412 /* To avoid excessive dumplication of ops we implement shift
4413 by immediate using the variable shift operations. */
4415 /* Shift by immediate:
4416 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4417 /* Right shifts are encoded as N - shift, where N is the
4418 element size in bits. */
4420 shift
= shift
- (1 << (size
+ 3));
4428 imm
= (uint8_t) shift
;
4433 imm
= (uint16_t) shift
;
4444 for (pass
= 0; pass
< count
; pass
++) {
4446 neon_load_reg64(cpu_V0
, rm
+ pass
);
4447 tcg_gen_movi_i64(cpu_V1
, imm
);
4452 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4454 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4459 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4461 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4466 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4468 case 5: /* VSHL, VSLI */
4469 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4473 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4475 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4477 case 7: /* VQSHLU */
4478 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4481 if (op
== 1 || op
== 3) {
4483 neon_load_reg64(cpu_V0
, rd
+ pass
);
4484 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4485 } else if (op
== 4 || (op
== 5 && u
)) {
4487 cpu_abort(env
, "VS[LR]I.64 not implemented");
4489 neon_store_reg64(cpu_V0
, rd
+ pass
);
4490 } else { /* size < 3 */
4491 /* Operands in T0 and T1. */
4492 tmp
= neon_load_reg(rm
, pass
);
4494 tcg_gen_movi_i32(tmp2
, imm
);
4498 GEN_NEON_INTEGER_OP(shl
);
4502 GEN_NEON_INTEGER_OP(rshl
);
4507 GEN_NEON_INTEGER_OP(shl
);
4509 case 5: /* VSHL, VSLI */
4511 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4512 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4513 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4518 GEN_NEON_INTEGER_OP_ENV(qshl
);
4520 case 7: /* VQSHLU */
4522 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4523 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4524 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4531 if (op
== 1 || op
== 3) {
4533 tmp2
= neon_load_reg(rd
, pass
);
4534 gen_neon_add(size
, tmp2
, tmp
);
4536 } else if (op
== 4 || (op
== 5 && u
)) {
4541 imm
= 0xff >> -shift
;
4543 imm
= (uint8_t)(0xff << shift
);
4549 imm
= 0xffff >> -shift
;
4551 imm
= (uint16_t)(0xffff << shift
);
4556 imm
= 0xffffffffu
>> -shift
;
4558 imm
= 0xffffffffu
<< shift
;
4563 tmp2
= neon_load_reg(rd
, pass
);
4564 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4565 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4566 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4569 neon_store_reg(rd
, pass
, tmp
);
4572 } else if (op
< 10) {
4573 /* Shift by immediate and narrow:
4574 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4575 shift
= shift
- (1 << (size
+ 3));
4579 imm
= (uint16_t)shift
;
4581 tmp2
= tcg_const_i32(imm
);
4582 TCGV_UNUSED_I64(tmp64
);
4585 imm
= (uint32_t)shift
;
4586 tmp2
= tcg_const_i32(imm
);
4587 TCGV_UNUSED_I64(tmp64
);
4590 tmp64
= tcg_const_i64(shift
);
4597 for (pass
= 0; pass
< 2; pass
++) {
4599 neon_load_reg64(cpu_V0
, rm
+ pass
);
4602 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4604 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4607 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4609 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4612 tmp
= neon_load_reg(rm
+ pass
, 0);
4613 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4614 tmp3
= neon_load_reg(rm
+ pass
, 1);
4615 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4616 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4621 if (op
== 8 && !u
) {
4622 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4625 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4627 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4632 neon_store_reg(rd
, 0, tmp2
);
4633 neon_store_reg(rd
, 1, tmp
);
4636 } else if (op
== 10) {
4640 tmp
= neon_load_reg(rm
, 0);
4641 tmp2
= neon_load_reg(rm
, 1);
4642 for (pass
= 0; pass
< 2; pass
++) {
4646 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4649 /* The shift is less than the width of the source
4650 type, so we can just shift the whole register. */
4651 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4652 if (size
< 2 || !u
) {
4655 imm
= (0xffu
>> (8 - shift
));
4658 imm
= 0xffff >> (16 - shift
);
4660 imm64
= imm
| (((uint64_t)imm
) << 32);
4661 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4664 neon_store_reg64(cpu_V0
, rd
+ pass
);
4666 } else if (op
== 15 || op
== 16) {
4667 /* VCVT fixed-point. */
4668 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4669 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4672 gen_vfp_ulto(0, shift
);
4674 gen_vfp_slto(0, shift
);
4677 gen_vfp_toul(0, shift
);
4679 gen_vfp_tosl(0, shift
);
4681 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4686 } else { /* (insn & 0x00380080) == 0 */
4689 op
= (insn
>> 8) & 0xf;
4690 /* One register and immediate. */
4691 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4692 invert
= (insn
& (1 << 5)) != 0;
4710 imm
= (imm
<< 8) | (imm
<< 24);
4713 imm
= (imm
< 8) | 0xff;
4716 imm
= (imm
<< 16) | 0xffff;
4719 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4724 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4725 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4731 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4732 if (op
& 1 && op
< 12) {
4733 tmp
= neon_load_reg(rd
, pass
);
4735 /* The immediate value has already been inverted, so
4737 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4739 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4744 if (op
== 14 && invert
) {
4747 for (n
= 0; n
< 4; n
++) {
4748 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4749 val
|= 0xff << (n
* 8);
4751 tcg_gen_movi_i32(tmp
, val
);
4753 tcg_gen_movi_i32(tmp
, imm
);
4756 neon_store_reg(rd
, pass
, tmp
);
4759 } else { /* (insn & 0x00800010 == 0x00800000) */
4761 op
= (insn
>> 8) & 0xf;
4762 if ((insn
& (1 << 6)) == 0) {
4763 /* Three registers of different lengths. */
4767 /* prewiden, src1_wide, src2_wide */
4768 static const int neon_3reg_wide
[16][3] = {
4769 {1, 0, 0}, /* VADDL */
4770 {1, 1, 0}, /* VADDW */
4771 {1, 0, 0}, /* VSUBL */
4772 {1, 1, 0}, /* VSUBW */
4773 {0, 1, 1}, /* VADDHN */
4774 {0, 0, 0}, /* VABAL */
4775 {0, 1, 1}, /* VSUBHN */
4776 {0, 0, 0}, /* VABDL */
4777 {0, 0, 0}, /* VMLAL */
4778 {0, 0, 0}, /* VQDMLAL */
4779 {0, 0, 0}, /* VMLSL */
4780 {0, 0, 0}, /* VQDMLSL */
4781 {0, 0, 0}, /* Integer VMULL */
4782 {0, 0, 0}, /* VQDMULL */
4783 {0, 0, 0} /* Polynomial VMULL */
4786 prewiden
= neon_3reg_wide
[op
][0];
4787 src1_wide
= neon_3reg_wide
[op
][1];
4788 src2_wide
= neon_3reg_wide
[op
][2];
4790 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4793 /* Avoid overlapping operands. Wide source operands are
4794 always aligned so will never overlap with wide
4795 destinations in problematic ways. */
4796 if (rd
== rm
&& !src2_wide
) {
4797 tmp
= neon_load_reg(rm
, 1);
4798 neon_store_scratch(2, tmp
);
4799 } else if (rd
== rn
&& !src1_wide
) {
4800 tmp
= neon_load_reg(rn
, 1);
4801 neon_store_scratch(2, tmp
);
4804 for (pass
= 0; pass
< 2; pass
++) {
4806 neon_load_reg64(cpu_V0
, rn
+ pass
);
4809 if (pass
== 1 && rd
== rn
) {
4810 tmp
= neon_load_scratch(2);
4812 tmp
= neon_load_reg(rn
, pass
);
4815 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4819 neon_load_reg64(cpu_V1
, rm
+ pass
);
4822 if (pass
== 1 && rd
== rm
) {
4823 tmp2
= neon_load_scratch(2);
4825 tmp2
= neon_load_reg(rm
, pass
);
4828 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4832 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4833 gen_neon_addl(size
);
4835 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4836 gen_neon_subl(size
);
4838 case 5: case 7: /* VABAL, VABDL */
4839 switch ((size
<< 1) | u
) {
4841 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4844 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4847 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4850 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4853 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4856 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4863 case 8: case 9: case 10: case 11: case 12: case 13:
4864 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4865 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4869 case 14: /* Polynomial VMULL */
4870 cpu_abort(env
, "Polynomial VMULL not implemented");
4872 default: /* 15 is RESERVED. */
4875 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4877 if (op
== 10 || op
== 11) {
4878 gen_neon_negl(cpu_V0
, size
);
4882 neon_load_reg64(cpu_V1
, rd
+ pass
);
4886 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4887 gen_neon_addl(size
);
4889 case 9: case 11: /* VQDMLAL, VQDMLSL */
4890 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4891 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4894 case 13: /* VQDMULL */
4895 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4900 neon_store_reg64(cpu_V0
, rd
+ pass
);
4901 } else if (op
== 4 || op
== 6) {
4902 /* Narrowing operation. */
4907 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4910 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4913 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4914 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4921 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4924 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4927 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4928 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4929 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4937 neon_store_reg(rd
, 0, tmp3
);
4938 neon_store_reg(rd
, 1, tmp
);
4941 /* Write back the result. */
4942 neon_store_reg64(cpu_V0
, rd
+ pass
);
4946 /* Two registers and a scalar. */
4948 case 0: /* Integer VMLA scalar */
4949 case 1: /* Float VMLA scalar */
4950 case 4: /* Integer VMLS scalar */
4951 case 5: /* Floating point VMLS scalar */
4952 case 8: /* Integer VMUL scalar */
4953 case 9: /* Floating point VMUL scalar */
4954 case 12: /* VQDMULH scalar */
4955 case 13: /* VQRDMULH scalar */
4956 tmp
= neon_get_scalar(size
, rm
);
4957 neon_store_scratch(0, tmp
);
4958 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
4959 tmp
= neon_load_scratch(0);
4960 tmp2
= neon_load_reg(rn
, pass
);
4963 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4965 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4967 } else if (op
== 13) {
4969 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4971 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4973 } else if (op
& 1) {
4974 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4977 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4978 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4979 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4986 tmp2
= neon_load_reg(rd
, pass
);
4989 gen_neon_add(size
, tmp
, tmp2
);
4992 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4995 gen_neon_rsb(size
, tmp
, tmp2
);
4998 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5005 neon_store_reg(rd
, pass
, tmp
);
5008 case 2: /* VMLAL sclar */
5009 case 3: /* VQDMLAL scalar */
5010 case 6: /* VMLSL scalar */
5011 case 7: /* VQDMLSL scalar */
5012 case 10: /* VMULL scalar */
5013 case 11: /* VQDMULL scalar */
5014 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5017 tmp2
= neon_get_scalar(size
, rm
);
5018 tmp3
= neon_load_reg(rn
, 1);
5020 for (pass
= 0; pass
< 2; pass
++) {
5022 tmp
= neon_load_reg(rn
, 0);
5026 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5028 if (op
== 6 || op
== 7) {
5029 gen_neon_negl(cpu_V0
, size
);
5032 neon_load_reg64(cpu_V1
, rd
+ pass
);
5036 gen_neon_addl(size
);
5039 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5040 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5046 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5051 neon_store_reg64(cpu_V0
, rd
+ pass
);
5057 default: /* 14 and 15 are RESERVED */
5061 } else { /* size == 3 */
5064 imm
= (insn
>> 8) & 0xf;
5071 neon_load_reg64(cpu_V0
, rn
);
5073 neon_load_reg64(cpu_V1
, rn
+ 1);
5075 } else if (imm
== 8) {
5076 neon_load_reg64(cpu_V0
, rn
+ 1);
5078 neon_load_reg64(cpu_V1
, rm
);
5081 tmp64
= tcg_temp_new_i64();
5083 neon_load_reg64(cpu_V0
, rn
);
5084 neon_load_reg64(tmp64
, rn
+ 1);
5086 neon_load_reg64(cpu_V0
, rn
+ 1);
5087 neon_load_reg64(tmp64
, rm
);
5089 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5090 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5091 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5093 neon_load_reg64(cpu_V1
, rm
);
5095 neon_load_reg64(cpu_V1
, rm
+ 1);
5098 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5099 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5100 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5103 neon_load_reg64(cpu_V0
, rn
);
5104 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5105 neon_load_reg64(cpu_V1
, rm
);
5106 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5107 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5109 neon_store_reg64(cpu_V0
, rd
);
5111 neon_store_reg64(cpu_V1
, rd
+ 1);
5113 } else if ((insn
& (1 << 11)) == 0) {
5114 /* Two register misc. */
5115 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5116 size
= (insn
>> 18) & 3;
5118 case 0: /* VREV64 */
5121 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5122 tmp
= neon_load_reg(rm
, pass
* 2);
5123 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5125 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5126 case 1: gen_swap_half(tmp
); break;
5127 case 2: /* no-op */ break;
5130 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5132 neon_store_reg(rd
, pass
* 2, tmp2
);
5135 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5136 case 1: gen_swap_half(tmp2
); break;
5139 neon_store_reg(rd
, pass
* 2, tmp2
);
5143 case 4: case 5: /* VPADDL */
5144 case 12: case 13: /* VPADAL */
5147 for (pass
= 0; pass
< q
+ 1; pass
++) {
5148 tmp
= neon_load_reg(rm
, pass
* 2);
5149 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5150 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5151 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5153 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5154 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5155 case 2: tcg_gen_add_i64(CPU_V001
); break;
5160 neon_load_reg64(cpu_V1
, rd
+ pass
);
5161 gen_neon_addl(size
);
5163 neon_store_reg64(cpu_V0
, rd
+ pass
);
5168 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5169 tmp
= neon_load_reg(rm
, n
);
5170 tmp2
= neon_load_reg(rd
, n
+ 1);
5171 neon_store_reg(rm
, n
, tmp2
);
5172 neon_store_reg(rd
, n
+ 1, tmp
);
5180 Rd A3 A2 A1 A0 B2 B0 A2 A0
5181 Rm B3 B2 B1 B0 B3 B1 A3 A1
5185 gen_neon_unzip(rd
, q
, 0, size
);
5186 gen_neon_unzip(rm
, q
, 4, size
);
5188 static int unzip_order_q
[8] =
5189 {0, 2, 4, 6, 1, 3, 5, 7};
5190 for (n
= 0; n
< 8; n
++) {
5191 int reg
= (n
< 4) ? rd
: rm
;
5192 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5193 neon_store_reg(reg
, n
% 4, tmp
);
5196 static int unzip_order
[4] =
5198 for (n
= 0; n
< 4; n
++) {
5199 int reg
= (n
< 2) ? rd
: rm
;
5200 tmp
= neon_load_scratch(unzip_order
[n
]);
5201 neon_store_reg(reg
, n
% 2, tmp
);
5207 Rd A3 A2 A1 A0 B1 A1 B0 A0
5208 Rm B3 B2 B1 B0 B3 A3 B2 A2
5212 count
= (q
? 4 : 2);
5213 for (n
= 0; n
< count
; n
++) {
5214 tmp
= neon_load_reg(rd
, n
);
5215 tmp2
= neon_load_reg(rd
, n
);
5217 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5218 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5219 case 2: /* no-op */; break;
5222 neon_store_scratch(n
* 2, tmp
);
5223 neon_store_scratch(n
* 2 + 1, tmp2
);
5225 for (n
= 0; n
< count
* 2; n
++) {
5226 int reg
= (n
< count
) ? rd
: rm
;
5227 tmp
= neon_load_scratch(n
);
5228 neon_store_reg(reg
, n
% count
, tmp
);
5231 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5235 for (pass
= 0; pass
< 2; pass
++) {
5236 neon_load_reg64(cpu_V0
, rm
+ pass
);
5238 if (op
== 36 && q
== 0) {
5239 gen_neon_narrow(size
, tmp
, cpu_V0
);
5241 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5243 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5248 neon_store_reg(rd
, 0, tmp2
);
5249 neon_store_reg(rd
, 1, tmp
);
5253 case 38: /* VSHLL */
5256 tmp
= neon_load_reg(rm
, 0);
5257 tmp2
= neon_load_reg(rm
, 1);
5258 for (pass
= 0; pass
< 2; pass
++) {
5261 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5262 neon_store_reg64(cpu_V0
, rd
+ pass
);
5267 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5268 if (op
== 30 || op
== 31 || op
>= 58) {
5269 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5270 neon_reg_offset(rm
, pass
));
5273 tmp
= neon_load_reg(rm
, pass
);
5276 case 1: /* VREV32 */
5278 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5279 case 1: gen_swap_half(tmp
); break;
5283 case 2: /* VREV16 */
5290 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5291 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5292 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5298 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5299 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5300 case 2: gen_helper_clz(tmp
, tmp
); break;
5307 gen_helper_neon_cnt_u8(tmp
, tmp
);
5312 tcg_gen_not_i32(tmp
, tmp
);
5314 case 14: /* VQABS */
5316 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5317 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5318 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5322 case 15: /* VQNEG */
5324 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5325 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5326 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5330 case 16: case 19: /* VCGT #0, VCLE #0 */
5331 tmp2
= tcg_const_i32(0);
5333 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5334 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5335 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5338 tcg_temp_free(tmp2
);
5340 tcg_gen_not_i32(tmp
, tmp
);
5342 case 17: case 20: /* VCGE #0, VCLT #0 */
5343 tmp2
= tcg_const_i32(0);
5345 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5346 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5347 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5350 tcg_temp_free(tmp2
);
5352 tcg_gen_not_i32(tmp
, tmp
);
5354 case 18: /* VCEQ #0 */
5355 tmp2
= tcg_const_i32(0);
5357 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5358 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5359 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5362 tcg_temp_free(tmp2
);
5366 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5367 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5368 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5375 tmp2
= tcg_const_i32(0);
5376 gen_neon_rsb(size
, tmp
, tmp2
);
5377 tcg_temp_free(tmp2
);
5379 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5380 tmp2
= tcg_const_i32(0);
5381 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5382 tcg_temp_free(tmp2
);
5384 tcg_gen_not_i32(tmp
, tmp
);
5386 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5387 tmp2
= tcg_const_i32(0);
5388 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5389 tcg_temp_free(tmp2
);
5391 tcg_gen_not_i32(tmp
, tmp
);
5393 case 26: /* Float VCEQ #0 */
5394 tmp2
= tcg_const_i32(0);
5395 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5396 tcg_temp_free(tmp2
);
5398 case 30: /* Float VABS */
5401 case 31: /* Float VNEG */
5405 tmp2
= neon_load_reg(rd
, pass
);
5406 neon_store_reg(rm
, pass
, tmp2
);
5409 tmp2
= neon_load_reg(rd
, pass
);
5411 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5412 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5416 neon_store_reg(rm
, pass
, tmp2
);
5418 case 56: /* Integer VRECPE */
5419 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5421 case 57: /* Integer VRSQRTE */
5422 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5424 case 58: /* Float VRECPE */
5425 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5427 case 59: /* Float VRSQRTE */
5428 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5430 case 60: /* VCVT.F32.S32 */
5433 case 61: /* VCVT.F32.U32 */
5436 case 62: /* VCVT.S32.F32 */
5439 case 63: /* VCVT.U32.F32 */
5443 /* Reserved: 21, 29, 39-56 */
5446 if (op
== 30 || op
== 31 || op
>= 58) {
5447 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5448 neon_reg_offset(rd
, pass
));
5450 neon_store_reg(rd
, pass
, tmp
);
5455 } else if ((insn
& (1 << 10)) == 0) {
5457 n
= ((insn
>> 5) & 0x18) + 8;
5458 if (insn
& (1 << 6)) {
5459 tmp
= neon_load_reg(rd
, 0);
5462 tcg_gen_movi_i32(tmp
, 0);
5464 tmp2
= neon_load_reg(rm
, 0);
5465 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5468 if (insn
& (1 << 6)) {
5469 tmp
= neon_load_reg(rd
, 1);
5472 tcg_gen_movi_i32(tmp
, 0);
5474 tmp3
= neon_load_reg(rm
, 1);
5475 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5477 neon_store_reg(rd
, 0, tmp2
);
5478 neon_store_reg(rd
, 1, tmp3
);
5480 } else if ((insn
& 0x380) == 0) {
5482 if (insn
& (1 << 19)) {
5483 tmp
= neon_load_reg(rm
, 1);
5485 tmp
= neon_load_reg(rm
, 0);
5487 if (insn
& (1 << 16)) {
5488 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5489 } else if (insn
& (1 << 17)) {
5490 if ((insn
>> 18) & 1)
5491 gen_neon_dup_high16(tmp
);
5493 gen_neon_dup_low16(tmp
);
5495 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5497 tcg_gen_mov_i32(tmp2
, tmp
);
5498 neon_store_reg(rd
, pass
, tmp2
);
5509 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5511 int crn
= (insn
>> 16) & 0xf;
5512 int crm
= insn
& 0xf;
5513 int op1
= (insn
>> 21) & 7;
5514 int op2
= (insn
>> 5) & 7;
5515 int rt
= (insn
>> 12) & 0xf;
5518 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5519 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5523 tmp
= load_cpu_field(teecr
);
5524 store_reg(s
, rt
, tmp
);
5527 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5529 if (IS_USER(s
) && (env
->teecr
& 1))
5531 tmp
= load_cpu_field(teehbr
);
5532 store_reg(s
, rt
, tmp
);
5536 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5537 op1
, crn
, crm
, op2
);
5541 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5543 int crn
= (insn
>> 16) & 0xf;
5544 int crm
= insn
& 0xf;
5545 int op1
= (insn
>> 21) & 7;
5546 int op2
= (insn
>> 5) & 7;
5547 int rt
= (insn
>> 12) & 0xf;
5550 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5551 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5555 tmp
= load_reg(s
, rt
);
5556 gen_helper_set_teecr(cpu_env
, tmp
);
5560 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5562 if (IS_USER(s
) && (env
->teecr
& 1))
5564 tmp
= load_reg(s
, rt
);
5565 store_cpu_field(tmp
, teehbr
);
5569 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5570 op1
, crn
, crm
, op2
);
5574 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5578 cpnum
= (insn
>> 8) & 0xf;
5579 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5580 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5586 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5587 return disas_iwmmxt_insn(env
, s
, insn
);
5588 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5589 return disas_dsp_insn(env
, s
, insn
);
5594 return disas_vfp_insn (env
, s
, insn
);
5596 /* Coprocessors 7-15 are architecturally reserved by ARM.
5597 Unfortunately Intel decided to ignore this. */
5598 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5600 if (insn
& (1 << 20))
5601 return disas_cp14_read(env
, s
, insn
);
5603 return disas_cp14_write(env
, s
, insn
);
5605 return disas_cp15_insn (env
, s
, insn
);
5608 /* Unknown coprocessor. See if the board has hooked it. */
5609 return disas_cp_insn (env
, s
, insn
);
5614 /* Store a 64-bit value to a register pair. Clobbers val. */
5615 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5619 tcg_gen_trunc_i64_i32(tmp
, val
);
5620 store_reg(s
, rlow
, tmp
);
5622 tcg_gen_shri_i64(val
, val
, 32);
5623 tcg_gen_trunc_i64_i32(tmp
, val
);
5624 store_reg(s
, rhigh
, tmp
);
5627 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5628 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5633 /* Load value and extend to 64 bits. */
5634 tmp
= tcg_temp_new_i64();
5635 tmp2
= load_reg(s
, rlow
);
5636 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5638 tcg_gen_add_i64(val
, val
, tmp
);
5641 /* load and add a 64-bit value from a register pair. */
5642 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5648 /* Load 64-bit value rd:rn. */
5649 tmpl
= load_reg(s
, rlow
);
5650 tmph
= load_reg(s
, rhigh
);
5651 tmp
= tcg_temp_new_i64();
5652 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5655 tcg_gen_add_i64(val
, val
, tmp
);
5658 /* Set N and Z flags from a 64-bit value. */
5659 static void gen_logicq_cc(TCGv_i64 val
)
5661 TCGv tmp
= new_tmp();
5662 gen_helper_logicq_cc(tmp
, val
);
5667 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5669 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5676 insn
= ldl_code(s
->pc
);
5679 /* M variants do not implement ARM mode. */
5684 /* Unconditional instructions. */
5685 if (((insn
>> 25) & 7) == 1) {
5686 /* NEON Data processing. */
5687 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5690 if (disas_neon_data_insn(env
, s
, insn
))
5694 if ((insn
& 0x0f100000) == 0x04000000) {
5695 /* NEON load/store. */
5696 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5699 if (disas_neon_ls_insn(env
, s
, insn
))
5703 if ((insn
& 0x0d70f000) == 0x0550f000) {
5706 } else if ((insn
& 0x0ffffdff) == 0x01010000) {
5709 if (insn
& (1 << 9)) {
5710 /* BE8 mode not implemented. */
5714 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5715 switch ((insn
>> 4) & 0xf) {
5718 gen_helper_clrex(cpu_env
);
5724 /* We don't emulate caches so these are a no-op. */
5729 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5735 op1
= (insn
& 0x1f);
5736 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5737 addr
= load_reg(s
, 13);
5740 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5742 i
= (insn
>> 23) & 3;
5744 case 0: offset
= -4; break; /* DA */
5745 case 1: offset
= 0; break; /* IA */
5746 case 2: offset
= -8; break; /* DB */
5747 case 3: offset
= 4; break; /* IB */
5751 tcg_gen_addi_i32(addr
, addr
, offset
);
5752 tmp
= load_reg(s
, 14);
5753 gen_st32(tmp
, addr
, 0);
5754 tmp
= load_cpu_field(spsr
);
5755 tcg_gen_addi_i32(addr
, addr
, 4);
5756 gen_st32(tmp
, addr
, 0);
5757 if (insn
& (1 << 21)) {
5758 /* Base writeback. */
5760 case 0: offset
= -8; break;
5761 case 1: offset
= 4; break;
5762 case 2: offset
= -4; break;
5763 case 3: offset
= 0; break;
5767 tcg_gen_addi_i32(addr
, addr
, offset
);
5768 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5769 store_reg(s
, 13, addr
);
5771 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5777 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5783 rn
= (insn
>> 16) & 0xf;
5784 addr
= load_reg(s
, rn
);
5785 i
= (insn
>> 23) & 3;
5787 case 0: offset
= -4; break; /* DA */
5788 case 1: offset
= 0; break; /* IA */
5789 case 2: offset
= -8; break; /* DB */
5790 case 3: offset
= 4; break; /* IB */
5794 tcg_gen_addi_i32(addr
, addr
, offset
);
5795 /* Load PC into tmp and CPSR into tmp2. */
5796 tmp
= gen_ld32(addr
, 0);
5797 tcg_gen_addi_i32(addr
, addr
, 4);
5798 tmp2
= gen_ld32(addr
, 0);
5799 if (insn
& (1 << 21)) {
5800 /* Base writeback. */
5802 case 0: offset
= -8; break;
5803 case 1: offset
= 4; break;
5804 case 2: offset
= -4; break;
5805 case 3: offset
= 0; break;
5809 tcg_gen_addi_i32(addr
, addr
, offset
);
5810 store_reg(s
, rn
, addr
);
5814 gen_rfe(s
, tmp
, tmp2
);
5816 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5817 /* branch link and change to thumb (blx <offset>) */
5820 val
= (uint32_t)s
->pc
;
5822 tcg_gen_movi_i32(tmp
, val
);
5823 store_reg(s
, 14, tmp
);
5824 /* Sign-extend the 24-bit offset */
5825 offset
= (((int32_t)insn
) << 8) >> 8;
5826 /* offset * 4 + bit24 * 2 + (thumb bit) */
5827 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5828 /* pipeline offset */
5832 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5833 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5834 /* iWMMXt register transfer. */
5835 if (env
->cp15
.c15_cpar
& (1 << 1))
5836 if (!disas_iwmmxt_insn(env
, s
, insn
))
5839 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5840 /* Coprocessor double register transfer. */
5842 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5843 /* Additional coprocessor register transfer. */
5845 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5848 /* cps (privileged) */
5852 if (insn
& (1 << 19)) {
5853 if (insn
& (1 << 8))
5855 if (insn
& (1 << 7))
5857 if (insn
& (1 << 6))
5859 if (insn
& (1 << 18))
5862 if (insn
& (1 << 17)) {
5864 val
|= (insn
& 0x1f);
5867 gen_set_psr_im(s
, mask
, 0, val
);
5874 /* if not always execute, we generate a conditional jump to
5876 s
->condlabel
= gen_new_label();
5877 gen_test_cc(cond
^ 1, s
->condlabel
);
5880 if ((insn
& 0x0f900000) == 0x03000000) {
5881 if ((insn
& (1 << 21)) == 0) {
5883 rd
= (insn
>> 12) & 0xf;
5884 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5885 if ((insn
& (1 << 22)) == 0) {
5888 tcg_gen_movi_i32(tmp
, val
);
5891 tmp
= load_reg(s
, rd
);
5892 tcg_gen_ext16u_i32(tmp
, tmp
);
5893 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5895 store_reg(s
, rd
, tmp
);
5897 if (((insn
>> 12) & 0xf) != 0xf)
5899 if (((insn
>> 16) & 0xf) == 0) {
5900 gen_nop_hint(s
, insn
& 0xff);
5902 /* CPSR = immediate */
5904 shift
= ((insn
>> 8) & 0xf) * 2;
5906 val
= (val
>> shift
) | (val
<< (32 - shift
));
5907 i
= ((insn
& (1 << 22)) != 0);
5908 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5912 } else if ((insn
& 0x0f900000) == 0x01000000
5913 && (insn
& 0x00000090) != 0x00000090) {
5914 /* miscellaneous instructions */
5915 op1
= (insn
>> 21) & 3;
5916 sh
= (insn
>> 4) & 0xf;
5919 case 0x0: /* move program status register */
5922 tmp
= load_reg(s
, rm
);
5923 i
= ((op1
& 2) != 0);
5924 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
5928 rd
= (insn
>> 12) & 0xf;
5932 tmp
= load_cpu_field(spsr
);
5935 gen_helper_cpsr_read(tmp
);
5937 store_reg(s
, rd
, tmp
);
5942 /* branch/exchange thumb (bx). */
5943 tmp
= load_reg(s
, rm
);
5945 } else if (op1
== 3) {
5947 rd
= (insn
>> 12) & 0xf;
5948 tmp
= load_reg(s
, rm
);
5949 gen_helper_clz(tmp
, tmp
);
5950 store_reg(s
, rd
, tmp
);
5958 /* Trivial implementation equivalent to bx. */
5959 tmp
= load_reg(s
, rm
);
5969 /* branch link/exchange thumb (blx) */
5970 tmp
= load_reg(s
, rm
);
5972 tcg_gen_movi_i32(tmp2
, s
->pc
);
5973 store_reg(s
, 14, tmp2
);
5976 case 0x5: /* saturating add/subtract */
5977 rd
= (insn
>> 12) & 0xf;
5978 rn
= (insn
>> 16) & 0xf;
5979 tmp
= load_reg(s
, rm
);
5980 tmp2
= load_reg(s
, rn
);
5982 gen_helper_double_saturate(tmp2
, tmp2
);
5984 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
5986 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
5988 store_reg(s
, rd
, tmp
);
5992 gen_set_condexec(s
);
5993 gen_set_pc_im(s
->pc
- 4);
5994 gen_exception(EXCP_BKPT
);
5995 s
->is_jmp
= DISAS_JUMP
;
5997 case 0x8: /* signed multiply */
6001 rs
= (insn
>> 8) & 0xf;
6002 rn
= (insn
>> 12) & 0xf;
6003 rd
= (insn
>> 16) & 0xf;
6005 /* (32 * 16) >> 16 */
6006 tmp
= load_reg(s
, rm
);
6007 tmp2
= load_reg(s
, rs
);
6009 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6012 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6013 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6015 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6016 if ((sh
& 2) == 0) {
6017 tmp2
= load_reg(s
, rn
);
6018 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6021 store_reg(s
, rd
, tmp
);
6024 tmp
= load_reg(s
, rm
);
6025 tmp2
= load_reg(s
, rs
);
6026 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6029 tmp64
= tcg_temp_new_i64();
6030 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6032 gen_addq(s
, tmp64
, rn
, rd
);
6033 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6036 tmp2
= load_reg(s
, rn
);
6037 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6040 store_reg(s
, rd
, tmp
);
6047 } else if (((insn
& 0x0e000000) == 0 &&
6048 (insn
& 0x00000090) != 0x90) ||
6049 ((insn
& 0x0e000000) == (1 << 25))) {
6050 int set_cc
, logic_cc
, shiftop
;
6052 op1
= (insn
>> 21) & 0xf;
6053 set_cc
= (insn
>> 20) & 1;
6054 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6056 /* data processing instruction */
6057 if (insn
& (1 << 25)) {
6058 /* immediate operand */
6060 shift
= ((insn
>> 8) & 0xf) * 2;
6062 val
= (val
>> shift
) | (val
<< (32 - shift
));
6065 tcg_gen_movi_i32(tmp2
, val
);
6066 if (logic_cc
&& shift
) {
6067 gen_set_CF_bit31(tmp2
);
6072 tmp2
= load_reg(s
, rm
);
6073 shiftop
= (insn
>> 5) & 3;
6074 if (!(insn
& (1 << 4))) {
6075 shift
= (insn
>> 7) & 0x1f;
6076 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6078 rs
= (insn
>> 8) & 0xf;
6079 tmp
= load_reg(s
, rs
);
6080 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6083 if (op1
!= 0x0f && op1
!= 0x0d) {
6084 rn
= (insn
>> 16) & 0xf;
6085 tmp
= load_reg(s
, rn
);
6089 rd
= (insn
>> 12) & 0xf;
6092 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6096 store_reg_bx(env
, s
, rd
, tmp
);
6099 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6103 store_reg_bx(env
, s
, rd
, tmp
);
6106 if (set_cc
&& rd
== 15) {
6107 /* SUBS r15, ... is used for exception return. */
6111 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6112 gen_exception_return(s
, tmp
);
6115 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6117 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6119 store_reg_bx(env
, s
, rd
, tmp
);
6124 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6126 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6128 store_reg_bx(env
, s
, rd
, tmp
);
6132 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6134 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6136 store_reg_bx(env
, s
, rd
, tmp
);
6140 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6142 gen_add_carry(tmp
, tmp
, tmp2
);
6144 store_reg_bx(env
, s
, rd
, tmp
);
6148 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6150 gen_sub_carry(tmp
, tmp
, tmp2
);
6152 store_reg_bx(env
, s
, rd
, tmp
);
6156 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6158 gen_sub_carry(tmp
, tmp2
, tmp
);
6160 store_reg_bx(env
, s
, rd
, tmp
);
6164 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6171 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6178 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6184 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6189 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6193 store_reg_bx(env
, s
, rd
, tmp
);
6196 if (logic_cc
&& rd
== 15) {
6197 /* MOVS r15, ... is used for exception return. */
6201 gen_exception_return(s
, tmp2
);
6206 store_reg_bx(env
, s
, rd
, tmp2
);
6210 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6214 store_reg_bx(env
, s
, rd
, tmp
);
6218 tcg_gen_not_i32(tmp2
, tmp2
);
6222 store_reg_bx(env
, s
, rd
, tmp2
);
6225 if (op1
!= 0x0f && op1
!= 0x0d) {
6229 /* other instructions */
6230 op1
= (insn
>> 24) & 0xf;
6234 /* multiplies, extra load/stores */
6235 sh
= (insn
>> 5) & 3;
6238 rd
= (insn
>> 16) & 0xf;
6239 rn
= (insn
>> 12) & 0xf;
6240 rs
= (insn
>> 8) & 0xf;
6242 op1
= (insn
>> 20) & 0xf;
6244 case 0: case 1: case 2: case 3: case 6:
6246 tmp
= load_reg(s
, rs
);
6247 tmp2
= load_reg(s
, rm
);
6248 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6250 if (insn
& (1 << 22)) {
6251 /* Subtract (mls) */
6253 tmp2
= load_reg(s
, rn
);
6254 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6256 } else if (insn
& (1 << 21)) {
6258 tmp2
= load_reg(s
, rn
);
6259 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6262 if (insn
& (1 << 20))
6264 store_reg(s
, rd
, tmp
);
6268 tmp
= load_reg(s
, rs
);
6269 tmp2
= load_reg(s
, rm
);
6270 if (insn
& (1 << 22))
6271 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6273 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6274 if (insn
& (1 << 21)) /* mult accumulate */
6275 gen_addq(s
, tmp64
, rn
, rd
);
6276 if (!(insn
& (1 << 23))) { /* double accumulate */
6278 gen_addq_lo(s
, tmp64
, rn
);
6279 gen_addq_lo(s
, tmp64
, rd
);
6281 if (insn
& (1 << 20))
6282 gen_logicq_cc(tmp64
);
6283 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6287 rn
= (insn
>> 16) & 0xf;
6288 rd
= (insn
>> 12) & 0xf;
6289 if (insn
& (1 << 23)) {
6290 /* load/store exclusive */
6291 op1
= (insn
>> 21) & 0x3;
6296 addr
= tcg_temp_local_new_i32();
6297 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
6298 if (insn
& (1 << 20)) {
6299 gen_helper_mark_exclusive(cpu_env
, addr
);
6302 tmp
= gen_ld32(addr
, IS_USER(s
));
6304 case 1: /* ldrexd */
6305 tmp
= gen_ld32(addr
, IS_USER(s
));
6306 store_reg(s
, rd
, tmp
);
6307 tcg_gen_addi_i32(addr
, addr
, 4);
6308 tmp
= gen_ld32(addr
, IS_USER(s
));
6311 case 2: /* ldrexb */
6312 tmp
= gen_ld8u(addr
, IS_USER(s
));
6314 case 3: /* ldrexh */
6315 tmp
= gen_ld16u(addr
, IS_USER(s
));
6320 store_reg(s
, rd
, tmp
);
6322 int label
= gen_new_label();
6324 tmp2
= tcg_temp_local_new_i32();
6325 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6326 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6327 tmp
= load_reg(s
,rm
);
6330 gen_st32(tmp
, addr
, IS_USER(s
));
6332 case 1: /* strexd */
6333 gen_st32(tmp
, addr
, IS_USER(s
));
6334 tcg_gen_addi_i32(addr
, addr
, 4);
6335 tmp
= load_reg(s
, rm
+ 1);
6336 gen_st32(tmp
, addr
, IS_USER(s
));
6338 case 2: /* strexb */
6339 gen_st8(tmp
, addr
, IS_USER(s
));
6341 case 3: /* strexh */
6342 gen_st16(tmp
, addr
, IS_USER(s
));
6347 gen_set_label(label
);
6348 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6349 tcg_temp_free(tmp2
);
6351 tcg_temp_free(addr
);
6353 /* SWP instruction */
6356 /* ??? This is not really atomic. However we know
6357 we never have multiple CPUs running in parallel,
6358 so it is good enough. */
6359 addr
= load_reg(s
, rn
);
6360 tmp
= load_reg(s
, rm
);
6361 if (insn
& (1 << 22)) {
6362 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6363 gen_st8(tmp
, addr
, IS_USER(s
));
6365 tmp2
= gen_ld32(addr
, IS_USER(s
));
6366 gen_st32(tmp
, addr
, IS_USER(s
));
6369 store_reg(s
, rd
, tmp2
);
6375 /* Misc load/store */
6376 rn
= (insn
>> 16) & 0xf;
6377 rd
= (insn
>> 12) & 0xf;
6378 addr
= load_reg(s
, rn
);
6379 if (insn
& (1 << 24))
6380 gen_add_datah_offset(s
, insn
, 0, addr
);
6382 if (insn
& (1 << 20)) {
6386 tmp
= gen_ld16u(addr
, IS_USER(s
));
6389 tmp
= gen_ld8s(addr
, IS_USER(s
));
6393 tmp
= gen_ld16s(addr
, IS_USER(s
));
6397 } else if (sh
& 2) {
6401 tmp
= load_reg(s
, rd
);
6402 gen_st32(tmp
, addr
, IS_USER(s
));
6403 tcg_gen_addi_i32(addr
, addr
, 4);
6404 tmp
= load_reg(s
, rd
+ 1);
6405 gen_st32(tmp
, addr
, IS_USER(s
));
6409 tmp
= gen_ld32(addr
, IS_USER(s
));
6410 store_reg(s
, rd
, tmp
);
6411 tcg_gen_addi_i32(addr
, addr
, 4);
6412 tmp
= gen_ld32(addr
, IS_USER(s
));
6416 address_offset
= -4;
6419 tmp
= load_reg(s
, rd
);
6420 gen_st16(tmp
, addr
, IS_USER(s
));
6423 /* Perform base writeback before the loaded value to
6424 ensure correct behavior with overlapping index registers.
6425 ldrd with base writeback is is undefined if the
6426 destination and index registers overlap. */
6427 if (!(insn
& (1 << 24))) {
6428 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6429 store_reg(s
, rn
, addr
);
6430 } else if (insn
& (1 << 21)) {
6432 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6433 store_reg(s
, rn
, addr
);
6438 /* Complete the load. */
6439 store_reg(s
, rd
, tmp
);
6448 if (insn
& (1 << 4)) {
6450 /* Armv6 Media instructions. */
6452 rn
= (insn
>> 16) & 0xf;
6453 rd
= (insn
>> 12) & 0xf;
6454 rs
= (insn
>> 8) & 0xf;
6455 switch ((insn
>> 23) & 3) {
6456 case 0: /* Parallel add/subtract. */
6457 op1
= (insn
>> 20) & 7;
6458 tmp
= load_reg(s
, rn
);
6459 tmp2
= load_reg(s
, rm
);
6460 sh
= (insn
>> 5) & 7;
6461 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6463 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6465 store_reg(s
, rd
, tmp
);
6468 if ((insn
& 0x00700020) == 0) {
6469 /* Halfword pack. */
6470 tmp
= load_reg(s
, rn
);
6471 tmp2
= load_reg(s
, rm
);
6472 shift
= (insn
>> 7) & 0x1f;
6473 if (insn
& (1 << 6)) {
6477 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6478 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6479 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6483 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6484 tcg_gen_ext16u_i32(tmp
, tmp
);
6485 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6487 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6489 store_reg(s
, rd
, tmp
);
6490 } else if ((insn
& 0x00200020) == 0x00200000) {
6492 tmp
= load_reg(s
, rm
);
6493 shift
= (insn
>> 7) & 0x1f;
6494 if (insn
& (1 << 6)) {
6497 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6499 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6501 sh
= (insn
>> 16) & 0x1f;
6503 if (insn
& (1 << 22))
6504 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6506 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6508 store_reg(s
, rd
, tmp
);
6509 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6511 tmp
= load_reg(s
, rm
);
6512 sh
= (insn
>> 16) & 0x1f;
6514 if (insn
& (1 << 22))
6515 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6517 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6519 store_reg(s
, rd
, tmp
);
6520 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6522 tmp
= load_reg(s
, rn
);
6523 tmp2
= load_reg(s
, rm
);
6525 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6526 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6529 store_reg(s
, rd
, tmp
);
6530 } else if ((insn
& 0x000003e0) == 0x00000060) {
6531 tmp
= load_reg(s
, rm
);
6532 shift
= (insn
>> 10) & 3;
6533 /* ??? In many cases it's not neccessary to do a
6534 rotate, a shift is sufficient. */
6536 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6537 op1
= (insn
>> 20) & 7;
6539 case 0: gen_sxtb16(tmp
); break;
6540 case 2: gen_sxtb(tmp
); break;
6541 case 3: gen_sxth(tmp
); break;
6542 case 4: gen_uxtb16(tmp
); break;
6543 case 6: gen_uxtb(tmp
); break;
6544 case 7: gen_uxth(tmp
); break;
6545 default: goto illegal_op
;
6548 tmp2
= load_reg(s
, rn
);
6549 if ((op1
& 3) == 0) {
6550 gen_add16(tmp
, tmp2
);
6552 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6556 store_reg(s
, rd
, tmp
);
6557 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6559 tmp
= load_reg(s
, rm
);
6560 if (insn
& (1 << 22)) {
6561 if (insn
& (1 << 7)) {
6565 gen_helper_rbit(tmp
, tmp
);
6568 if (insn
& (1 << 7))
6571 tcg_gen_bswap32_i32(tmp
, tmp
);
6573 store_reg(s
, rd
, tmp
);
6578 case 2: /* Multiplies (Type 3). */
6579 tmp
= load_reg(s
, rm
);
6580 tmp2
= load_reg(s
, rs
);
6581 if (insn
& (1 << 20)) {
6582 /* Signed multiply most significant [accumulate]. */
6583 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6584 if (insn
& (1 << 5))
6585 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6586 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6588 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6590 tmp2
= load_reg(s
, rd
);
6591 if (insn
& (1 << 6)) {
6592 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6594 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6598 store_reg(s
, rn
, tmp
);
6600 if (insn
& (1 << 5))
6601 gen_swap_half(tmp2
);
6602 gen_smul_dual(tmp
, tmp2
);
6603 /* This addition cannot overflow. */
6604 if (insn
& (1 << 6)) {
6605 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6607 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6610 if (insn
& (1 << 22)) {
6611 /* smlald, smlsld */
6612 tmp64
= tcg_temp_new_i64();
6613 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6615 gen_addq(s
, tmp64
, rd
, rn
);
6616 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6618 /* smuad, smusd, smlad, smlsd */
6621 tmp2
= load_reg(s
, rd
);
6622 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6625 store_reg(s
, rn
, tmp
);
6630 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6632 case 0: /* Unsigned sum of absolute differences. */
6634 tmp
= load_reg(s
, rm
);
6635 tmp2
= load_reg(s
, rs
);
6636 gen_helper_usad8(tmp
, tmp
, tmp2
);
6639 tmp2
= load_reg(s
, rd
);
6640 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6643 store_reg(s
, rn
, tmp
);
6645 case 0x20: case 0x24: case 0x28: case 0x2c:
6646 /* Bitfield insert/clear. */
6648 shift
= (insn
>> 7) & 0x1f;
6649 i
= (insn
>> 16) & 0x1f;
6653 tcg_gen_movi_i32(tmp
, 0);
6655 tmp
= load_reg(s
, rm
);
6658 tmp2
= load_reg(s
, rd
);
6659 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6662 store_reg(s
, rd
, tmp
);
6664 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6665 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6667 tmp
= load_reg(s
, rm
);
6668 shift
= (insn
>> 7) & 0x1f;
6669 i
= ((insn
>> 16) & 0x1f) + 1;
6674 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6676 gen_sbfx(tmp
, shift
, i
);
6679 store_reg(s
, rd
, tmp
);
6689 /* Check for undefined extension instructions
6690 * per the ARM Bible IE:
6691 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6693 sh
= (0xf << 20) | (0xf << 4);
6694 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6698 /* load/store byte/word */
6699 rn
= (insn
>> 16) & 0xf;
6700 rd
= (insn
>> 12) & 0xf;
6701 tmp2
= load_reg(s
, rn
);
6702 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6703 if (insn
& (1 << 24))
6704 gen_add_data_offset(s
, insn
, tmp2
);
6705 if (insn
& (1 << 20)) {
6707 if (insn
& (1 << 22)) {
6708 tmp
= gen_ld8u(tmp2
, i
);
6710 tmp
= gen_ld32(tmp2
, i
);
6714 tmp
= load_reg(s
, rd
);
6715 if (insn
& (1 << 22))
6716 gen_st8(tmp
, tmp2
, i
);
6718 gen_st32(tmp
, tmp2
, i
);
6720 if (!(insn
& (1 << 24))) {
6721 gen_add_data_offset(s
, insn
, tmp2
);
6722 store_reg(s
, rn
, tmp2
);
6723 } else if (insn
& (1 << 21)) {
6724 store_reg(s
, rn
, tmp2
);
6728 if (insn
& (1 << 20)) {
6729 /* Complete the load. */
6730 if (rd
== 15 && ENABLE_ARCH_5
)
6733 store_reg(s
, rd
, tmp
);
6739 int j
, n
, user
, loaded_base
;
6742 /* load/store multiple words */
6743 /* XXX: store correct base if write back */
6745 if (insn
& (1 << 22)) {
6747 goto illegal_op
; /* only usable in supervisor mode */
6749 if ((insn
& (1 << 15)) == 0)
6752 rn
= (insn
>> 16) & 0xf;
6753 addr
= load_reg(s
, rn
);
6755 /* compute total size */
6757 TCGV_UNUSED(loaded_var
);
6760 if (insn
& (1 << i
))
6763 /* XXX: test invalid n == 0 case ? */
6764 if (insn
& (1 << 23)) {
6765 if (insn
& (1 << 24)) {
6767 tcg_gen_addi_i32(addr
, addr
, 4);
6769 /* post increment */
6772 if (insn
& (1 << 24)) {
6774 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6776 /* post decrement */
6778 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6782 if (insn
& (1 << 21)) {
6784 if (insn
& (1 << 23)) {
6785 if (insn
& (1 << 24)) {
6788 /* post increment */
6792 if (insn
& (1 << 24)) {
6795 crement
= -((n
- 1) * 4);
6798 /* post decrement */
6802 if (arm_feature(env
, ARM_FEATURE_ABORT_BU
)) {
6803 /* base-updated abort model: update base register
6804 before an abort can happen */
6805 crement
+= (n
- 1) * 4;
6807 tcg_gen_addi_i32(tmp
, addr
, crement
);
6808 store_reg(s
, rn
, tmp
);
6815 if (insn
& (1 << i
)) {
6816 if (insn
& (1 << 20)) {
6818 tmp
= gen_ld32(addr
, IS_USER(s
));
6820 if (ENABLE_ARCH_5
) {
6823 store_reg(s
, i
, tmp
);
6826 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6828 } else if (i
== rn
) {
6832 store_reg(s
, i
, tmp
);
6837 /* special case: r15 = PC + 8 */
6838 val
= (long)s
->pc
+ 4;
6840 tcg_gen_movi_i32(tmp
, val
);
6843 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6845 tmp
= load_reg(s
, i
);
6847 gen_st32(tmp
, addr
, IS_USER(s
));
6850 /* no need to add after the last transfer */
6852 tcg_gen_addi_i32(addr
, addr
, 4);
6855 if (!arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << 21))) {
6856 tcg_gen_addi_i32(addr
, addr
, crement
);
6857 store_reg(s
, rn
, addr
);
6862 store_reg(s
, rn
, loaded_var
);
6864 if ((insn
& (1 << 22)) && !user
) {
6865 /* Restore CPSR from SPSR. */
6866 tmp
= load_cpu_field(spsr
);
6867 gen_set_cpsr(tmp
, 0xffffffff);
6869 s
->is_jmp
= DISAS_UPDATE
;
6878 /* branch (and link) */
6879 val
= (int32_t)s
->pc
;
6880 if (insn
& (1 << 24)) {
6882 tcg_gen_movi_i32(tmp
, val
);
6883 store_reg(s
, 14, tmp
);
6885 offset
= (((int32_t)insn
<< 8) >> 8);
6886 val
+= (offset
<< 2) + 4;
6894 if (disas_coproc_insn(env
, s
, insn
))
6899 gen_set_pc_im(s
->pc
);
6900 s
->is_jmp
= DISAS_SWI
;
6904 gen_set_condexec(s
);
6905 gen_set_pc_im(s
->pc
- 4);
6906 gen_exception(EXCP_UDEF
);
6907 s
->is_jmp
= DISAS_JUMP
;
6913 /* Return true if this is a Thumb-2 logical op. */
6915 thumb2_logic_op(int op
)
6920 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6921 then set condition code flags based on the result of the operation.
6922 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6923 to the high bit of T1.
6924 Returns zero if the opcode is valid. */
6927 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
6934 tcg_gen_and_i32(t0
, t0
, t1
);
6938 tcg_gen_bic_i32(t0
, t0
, t1
);
6942 tcg_gen_or_i32(t0
, t0
, t1
);
6946 tcg_gen_not_i32(t1
, t1
);
6947 tcg_gen_or_i32(t0
, t0
, t1
);
6951 tcg_gen_xor_i32(t0
, t0
, t1
);
6956 gen_helper_add_cc(t0
, t0
, t1
);
6958 tcg_gen_add_i32(t0
, t0
, t1
);
6962 gen_helper_adc_cc(t0
, t0
, t1
);
6964 gen_add_carry(t0
, t0
, t1
);
6968 gen_helper_sbc_cc(t0
, t0
, t1
);
6970 gen_sub_carry(t0
, t0
, t1
);
6974 gen_helper_sub_cc(t0
, t0
, t1
);
6976 tcg_gen_sub_i32(t0
, t0
, t1
);
6980 gen_helper_sub_cc(t0
, t1
, t0
);
6982 tcg_gen_sub_i32(t0
, t1
, t0
);
6984 default: /* 5, 6, 7, 9, 12, 15. */
6990 gen_set_CF_bit31(t1
);
6995 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6997 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6999 uint32_t insn
, imm
, shift
, offset
;
7000 uint32_t rd
, rn
, rm
, rs
;
7011 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7012 || arm_feature (env
, ARM_FEATURE_M
))) {
7013 /* Thumb-1 cores may need to treat bl and blx as a pair of
7014 16-bit instructions to get correct prefetch abort behavior. */
7016 if ((insn
& (1 << 12)) == 0) {
7018 /* Second half of blx. */
7019 offset
= ((insn
& 0x7ff) << 1);
7020 tmp
= load_reg(s
, 14);
7021 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7022 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7025 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7026 store_reg(s
, 14, tmp2
);
7030 if (insn
& (1 << 11)) {
7031 /* Second half of bl. */
7032 offset
= ((insn
& 0x7ff) << 1) | 1;
7033 tmp
= load_reg(s
, 14);
7034 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7037 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7038 store_reg(s
, 14, tmp2
);
7042 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7043 /* Instruction spans a page boundary. Implement it as two
7044 16-bit instructions in case the second half causes an
7046 offset
= ((int32_t)insn
<< 21) >> 9;
7047 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7050 /* Fall through to 32-bit decode. */
7053 insn
= lduw_code(s
->pc
);
7055 insn
|= (uint32_t)insn_hw1
<< 16;
7057 if ((insn
& 0xf800e800) != 0xf000e800) {
7061 rn
= (insn
>> 16) & 0xf;
7062 rs
= (insn
>> 12) & 0xf;
7063 rd
= (insn
>> 8) & 0xf;
7065 switch ((insn
>> 25) & 0xf) {
7066 case 0: case 1: case 2: case 3:
7067 /* 16-bit instructions. Should never happen. */
7070 if (insn
& (1 << 22)) {
7071 /* Other load/store, table branch. */
7072 if (insn
& 0x01200000) {
7073 /* Load/store doubleword. */
7077 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7079 addr
= load_reg(s
, rn
);
7081 offset
= (insn
& 0xff) * 4;
7082 if ((insn
& (1 << 23)) == 0)
7084 if (insn
& (1 << 24)) {
7085 tcg_gen_addi_i32(addr
, addr
, offset
);
7088 if (insn
& (1 << 20)) {
7090 tmp
= gen_ld32(addr
, IS_USER(s
));
7091 store_reg(s
, rs
, tmp
);
7092 tcg_gen_addi_i32(addr
, addr
, 4);
7093 tmp
= gen_ld32(addr
, IS_USER(s
));
7094 store_reg(s
, rd
, tmp
);
7097 tmp
= load_reg(s
, rs
);
7098 gen_st32(tmp
, addr
, IS_USER(s
));
7099 tcg_gen_addi_i32(addr
, addr
, 4);
7100 tmp
= load_reg(s
, rd
);
7101 gen_st32(tmp
, addr
, IS_USER(s
));
7103 if (insn
& (1 << 21)) {
7104 /* Base writeback. */
7107 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7108 store_reg(s
, rn
, addr
);
7112 } else if ((insn
& (1 << 23)) == 0) {
7113 /* Load/store exclusive word. */
7114 addr
= tcg_temp_local_new();
7115 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7116 if (insn
& (1 << 20)) {
7117 gen_helper_mark_exclusive(cpu_env
, addr
);
7118 tmp
= gen_ld32(addr
, IS_USER(s
));
7119 store_reg(s
, rd
, tmp
);
7121 int label
= gen_new_label();
7122 tmp2
= tcg_temp_local_new();
7123 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7124 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7125 tmp
= load_reg(s
, rs
);
7126 gen_st32(tmp
, addr
, IS_USER(s
));
7127 gen_set_label(label
);
7128 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7129 tcg_temp_free(tmp2
);
7131 tcg_temp_free(addr
);
7132 } else if ((insn
& (1 << 6)) == 0) {
7136 tcg_gen_movi_i32(addr
, s
->pc
);
7138 addr
= load_reg(s
, rn
);
7140 tmp
= load_reg(s
, rm
);
7141 tcg_gen_add_i32(addr
, addr
, tmp
);
7142 if (insn
& (1 << 4)) {
7144 tcg_gen_add_i32(addr
, addr
, tmp
);
7146 tmp
= gen_ld16u(addr
, IS_USER(s
));
7149 tmp
= gen_ld8u(addr
, IS_USER(s
));
7152 tcg_gen_shli_i32(tmp
, tmp
, 1);
7153 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7154 store_reg(s
, 15, tmp
);
7156 /* Load/store exclusive byte/halfword/doubleword. */
7157 /* ??? These are not really atomic. However we know
7158 we never have multiple CPUs running in parallel,
7159 so it is good enough. */
7160 op
= (insn
>> 4) & 0x3;
7161 addr
= tcg_temp_local_new();
7162 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7163 if (insn
& (1 << 20)) {
7164 gen_helper_mark_exclusive(cpu_env
, addr
);
7167 tmp
= gen_ld8u(addr
, IS_USER(s
));
7170 tmp
= gen_ld16u(addr
, IS_USER(s
));
7173 tmp
= gen_ld32(addr
, IS_USER(s
));
7174 tcg_gen_addi_i32(addr
, addr
, 4);
7175 tmp2
= gen_ld32(addr
, IS_USER(s
));
7176 store_reg(s
, rd
, tmp2
);
7181 store_reg(s
, rs
, tmp
);
7183 int label
= gen_new_label();
7184 tmp2
= tcg_temp_local_new();
7185 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7186 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7187 tmp
= load_reg(s
, rs
);
7190 gen_st8(tmp
, addr
, IS_USER(s
));
7193 gen_st16(tmp
, addr
, IS_USER(s
));
7196 gen_st32(tmp
, addr
, IS_USER(s
));
7197 tcg_gen_addi_i32(addr
, addr
, 4);
7198 tmp
= load_reg(s
, rd
);
7199 gen_st32(tmp
, addr
, IS_USER(s
));
7204 gen_set_label(label
);
7205 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7206 tcg_temp_free(tmp2
);
7208 tcg_temp_free(addr
);
7211 /* Load/store multiple, RFE, SRS. */
7212 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7213 /* Not available in user mode. */
7216 if (insn
& (1 << 20)) {
7218 addr
= load_reg(s
, rn
);
7219 if ((insn
& (1 << 24)) == 0)
7220 tcg_gen_addi_i32(addr
, addr
, -8);
7221 /* Load PC into tmp and CPSR into tmp2. */
7222 tmp
= gen_ld32(addr
, 0);
7223 tcg_gen_addi_i32(addr
, addr
, 4);
7224 tmp2
= gen_ld32(addr
, 0);
7225 if (insn
& (1 << 21)) {
7226 /* Base writeback. */
7227 if (insn
& (1 << 24)) {
7228 tcg_gen_addi_i32(addr
, addr
, 4);
7230 tcg_gen_addi_i32(addr
, addr
, -4);
7232 store_reg(s
, rn
, addr
);
7236 gen_rfe(s
, tmp
, tmp2
);
7240 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7241 addr
= load_reg(s
, 13);
7244 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7246 if ((insn
& (1 << 24)) == 0) {
7247 tcg_gen_addi_i32(addr
, addr
, -8);
7249 tmp
= load_reg(s
, 14);
7250 gen_st32(tmp
, addr
, 0);
7251 tcg_gen_addi_i32(addr
, addr
, 4);
7253 gen_helper_cpsr_read(tmp
);
7254 gen_st32(tmp
, addr
, 0);
7255 if (insn
& (1 << 21)) {
7256 if ((insn
& (1 << 24)) == 0) {
7257 tcg_gen_addi_i32(addr
, addr
, -4);
7259 tcg_gen_addi_i32(addr
, addr
, 4);
7261 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7262 store_reg(s
, 13, addr
);
7264 gen_helper_set_r13_banked(cpu_env
,
7265 tcg_const_i32(op
), addr
);
7273 /* Load/store multiple. */
7274 addr
= load_reg(s
, rn
);
7276 for (i
= 0; i
< 16; i
++) {
7277 if (insn
& (1 << i
))
7280 if (insn
& (1 << 24)) {
7281 tcg_gen_addi_i32(addr
, addr
, -offset
);
7284 for (i
= 0; i
< 16; i
++) {
7285 if ((insn
& (1 << i
)) == 0)
7287 if (insn
& (1 << 20)) {
7289 tmp
= gen_ld32(addr
, IS_USER(s
));
7290 if (i
== 15 && ENABLE_ARCH_5
) {
7293 store_reg(s
, i
, tmp
);
7297 tmp
= load_reg(s
, i
);
7298 gen_st32(tmp
, addr
, IS_USER(s
));
7300 tcg_gen_addi_i32(addr
, addr
, 4);
7302 if (insn
& (1 << 21)) {
7303 /* Base register writeback. */
7304 if (insn
& (1 << 24)) {
7305 tcg_gen_addi_i32(addr
, addr
, -offset
);
7307 /* Fault if writeback register is in register list. */
7308 if (insn
& (1 << rn
))
7310 store_reg(s
, rn
, addr
);
7317 case 5: /* Data processing register constant shift. */
7320 tcg_gen_movi_i32(tmp
, 0);
7322 tmp
= load_reg(s
, rn
);
7324 tmp2
= load_reg(s
, rm
);
7325 op
= (insn
>> 21) & 0xf;
7326 shiftop
= (insn
>> 4) & 3;
7327 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7328 conds
= (insn
& (1 << 20)) != 0;
7329 logic_cc
= (conds
&& thumb2_logic_op(op
));
7330 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7331 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7335 store_reg(s
, rd
, tmp
);
7340 case 13: /* Misc data processing. */
7341 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7342 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7345 case 0: /* Register controlled shift. */
7346 tmp
= load_reg(s
, rn
);
7347 tmp2
= load_reg(s
, rm
);
7348 if ((insn
& 0x70) != 0)
7350 op
= (insn
>> 21) & 3;
7351 logic_cc
= (insn
& (1 << 20)) != 0;
7352 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7355 store_reg_bx(env
, s
, rd
, tmp
);
7357 case 1: /* Sign/zero extend. */
7358 tmp
= load_reg(s
, rm
);
7359 shift
= (insn
>> 4) & 3;
7360 /* ??? In many cases it's not neccessary to do a
7361 rotate, a shift is sufficient. */
7363 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7364 op
= (insn
>> 20) & 7;
7366 case 0: gen_sxth(tmp
); break;
7367 case 1: gen_uxth(tmp
); break;
7368 case 2: gen_sxtb16(tmp
); break;
7369 case 3: gen_uxtb16(tmp
); break;
7370 case 4: gen_sxtb(tmp
); break;
7371 case 5: gen_uxtb(tmp
); break;
7372 default: goto illegal_op
;
7375 tmp2
= load_reg(s
, rn
);
7376 if ((op
>> 1) == 1) {
7377 gen_add16(tmp
, tmp2
);
7379 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7383 store_reg(s
, rd
, tmp
);
7385 case 2: /* SIMD add/subtract. */
7386 op
= (insn
>> 20) & 7;
7387 shift
= (insn
>> 4) & 7;
7388 if ((op
& 3) == 3 || (shift
& 3) == 3)
7390 tmp
= load_reg(s
, rn
);
7391 tmp2
= load_reg(s
, rm
);
7392 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7394 store_reg(s
, rd
, tmp
);
7396 case 3: /* Other data processing. */
7397 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7399 /* Saturating add/subtract. */
7400 tmp
= load_reg(s
, rn
);
7401 tmp2
= load_reg(s
, rm
);
7403 gen_helper_double_saturate(tmp
, tmp
);
7405 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7407 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7410 tmp
= load_reg(s
, rn
);
7412 case 0x0a: /* rbit */
7413 gen_helper_rbit(tmp
, tmp
);
7415 case 0x08: /* rev */
7416 tcg_gen_bswap32_i32(tmp
, tmp
);
7418 case 0x09: /* rev16 */
7421 case 0x0b: /* revsh */
7424 case 0x10: /* sel */
7425 tmp2
= load_reg(s
, rm
);
7427 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7428 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7432 case 0x18: /* clz */
7433 gen_helper_clz(tmp
, tmp
);
7439 store_reg(s
, rd
, tmp
);
7441 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7442 op
= (insn
>> 4) & 0xf;
7443 tmp
= load_reg(s
, rn
);
7444 tmp2
= load_reg(s
, rm
);
7445 switch ((insn
>> 20) & 7) {
7446 case 0: /* 32 x 32 -> 32 */
7447 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7450 tmp2
= load_reg(s
, rs
);
7452 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7454 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7458 case 1: /* 16 x 16 -> 32 */
7459 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7462 tmp2
= load_reg(s
, rs
);
7463 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7467 case 2: /* Dual multiply add. */
7468 case 4: /* Dual multiply subtract. */
7470 gen_swap_half(tmp2
);
7471 gen_smul_dual(tmp
, tmp2
);
7472 /* This addition cannot overflow. */
7473 if (insn
& (1 << 22)) {
7474 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7476 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7481 tmp2
= load_reg(s
, rs
);
7482 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7486 case 3: /* 32 * 16 -> 32msb */
7488 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7491 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7492 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7494 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7497 tmp2
= load_reg(s
, rs
);
7498 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7502 case 5: case 6: /* 32 * 32 -> 32msb */
7503 gen_imull(tmp
, tmp2
);
7504 if (insn
& (1 << 5)) {
7505 gen_roundqd(tmp
, tmp2
);
7512 tmp2
= load_reg(s
, rs
);
7513 if (insn
& (1 << 21)) {
7514 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7516 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7521 case 7: /* Unsigned sum of absolute differences. */
7522 gen_helper_usad8(tmp
, tmp
, tmp2
);
7525 tmp2
= load_reg(s
, rs
);
7526 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7531 store_reg(s
, rd
, tmp
);
7533 case 6: case 7: /* 64-bit multiply, Divide. */
7534 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7535 tmp
= load_reg(s
, rn
);
7536 tmp2
= load_reg(s
, rm
);
7537 if ((op
& 0x50) == 0x10) {
7539 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7542 gen_helper_udiv(tmp
, tmp
, tmp2
);
7544 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7546 store_reg(s
, rd
, tmp
);
7547 } else if ((op
& 0xe) == 0xc) {
7548 /* Dual multiply accumulate long. */
7550 gen_swap_half(tmp2
);
7551 gen_smul_dual(tmp
, tmp2
);
7553 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7555 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7559 tmp64
= tcg_temp_new_i64();
7560 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7562 gen_addq(s
, tmp64
, rs
, rd
);
7563 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7566 /* Unsigned 64-bit multiply */
7567 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7571 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7573 tmp64
= tcg_temp_new_i64();
7574 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7577 /* Signed 64-bit multiply */
7578 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7583 gen_addq_lo(s
, tmp64
, rs
);
7584 gen_addq_lo(s
, tmp64
, rd
);
7585 } else if (op
& 0x40) {
7586 /* 64-bit accumulate. */
7587 gen_addq(s
, tmp64
, rs
, rd
);
7589 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7594 case 6: case 7: case 14: case 15:
7596 if (((insn
>> 24) & 3) == 3) {
7597 /* Translate into the equivalent ARM encoding. */
7598 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7599 if (disas_neon_data_insn(env
, s
, insn
))
7602 if (insn
& (1 << 28))
7604 if (disas_coproc_insn (env
, s
, insn
))
7608 case 8: case 9: case 10: case 11:
7609 if (insn
& (1 << 15)) {
7610 /* Branches, misc control. */
7611 if (insn
& 0x5000) {
7612 /* Unconditional branch. */
7613 /* signextend(hw1[10:0]) -> offset[:12]. */
7614 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7615 /* hw1[10:0] -> offset[11:1]. */
7616 offset
|= (insn
& 0x7ff) << 1;
7617 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7618 offset[24:22] already have the same value because of the
7619 sign extension above. */
7620 offset
^= ((~insn
) & (1 << 13)) << 10;
7621 offset
^= ((~insn
) & (1 << 11)) << 11;
7623 if (insn
& (1 << 14)) {
7624 /* Branch and link. */
7625 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7629 if (insn
& (1 << 12)) {
7635 offset
&= ~(uint32_t)2;
7636 gen_bx_im(s
, offset
);
7638 } else if (((insn
>> 23) & 7) == 7) {
7640 if (insn
& (1 << 13))
7643 if (insn
& (1 << 26)) {
7644 /* Secure monitor call (v6Z) */
7645 goto illegal_op
; /* not implemented. */
7647 op
= (insn
>> 20) & 7;
7649 case 0: /* msr cpsr. */
7651 tmp
= load_reg(s
, rn
);
7652 addr
= tcg_const_i32(insn
& 0xff);
7653 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7658 case 1: /* msr spsr. */
7661 tmp
= load_reg(s
, rn
);
7663 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7667 case 2: /* cps, nop-hint. */
7668 if (((insn
>> 8) & 7) == 0) {
7669 gen_nop_hint(s
, insn
& 0xff);
7671 /* Implemented as NOP in user mode. */
7676 if (insn
& (1 << 10)) {
7677 if (insn
& (1 << 7))
7679 if (insn
& (1 << 6))
7681 if (insn
& (1 << 5))
7683 if (insn
& (1 << 9))
7684 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7686 if (insn
& (1 << 8)) {
7688 imm
|= (insn
& 0x1f);
7691 gen_set_psr_im(s
, offset
, 0, imm
);
7694 case 3: /* Special control operations. */
7695 op
= (insn
>> 4) & 0xf;
7698 gen_helper_clrex(cpu_env
);
7703 /* These execute as NOPs. */
7711 /* Trivial implementation equivalent to bx. */
7712 tmp
= load_reg(s
, rn
);
7715 case 5: /* Exception return. */
7716 /* Unpredictable in user mode. */
7718 case 6: /* mrs cpsr. */
7721 addr
= tcg_const_i32(insn
& 0xff);
7722 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7724 gen_helper_cpsr_read(tmp
);
7726 store_reg(s
, rd
, tmp
);
7728 case 7: /* mrs spsr. */
7729 /* Not accessible in user mode. */
7730 if (IS_USER(s
) || IS_M(env
))
7732 tmp
= load_cpu_field(spsr
);
7733 store_reg(s
, rd
, tmp
);
7738 /* Conditional branch. */
7739 op
= (insn
>> 22) & 0xf;
7740 /* Generate a conditional jump to next instruction. */
7741 s
->condlabel
= gen_new_label();
7742 gen_test_cc(op
^ 1, s
->condlabel
);
7745 /* offset[11:1] = insn[10:0] */
7746 offset
= (insn
& 0x7ff) << 1;
7747 /* offset[17:12] = insn[21:16]. */
7748 offset
|= (insn
& 0x003f0000) >> 4;
7749 /* offset[31:20] = insn[26]. */
7750 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7751 /* offset[18] = insn[13]. */
7752 offset
|= (insn
& (1 << 13)) << 5;
7753 /* offset[19] = insn[11]. */
7754 offset
|= (insn
& (1 << 11)) << 8;
7756 /* jump to the offset */
7757 gen_jmp(s
, s
->pc
+ offset
);
7760 /* Data processing immediate. */
7761 if (insn
& (1 << 25)) {
7762 if (insn
& (1 << 24)) {
7763 if (insn
& (1 << 20))
7765 /* Bitfield/Saturate. */
7766 op
= (insn
>> 21) & 7;
7768 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7771 tcg_gen_movi_i32(tmp
, 0);
7773 tmp
= load_reg(s
, rn
);
7776 case 2: /* Signed bitfield extract. */
7778 if (shift
+ imm
> 32)
7781 gen_sbfx(tmp
, shift
, imm
);
7783 case 6: /* Unsigned bitfield extract. */
7785 if (shift
+ imm
> 32)
7788 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7790 case 3: /* Bitfield insert/clear. */
7793 imm
= imm
+ 1 - shift
;
7795 tmp2
= load_reg(s
, rd
);
7796 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7802 default: /* Saturate. */
7805 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7807 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7809 tmp2
= tcg_const_i32(imm
);
7812 if ((op
& 1) && shift
== 0)
7813 gen_helper_usat16(tmp
, tmp
, tmp2
);
7815 gen_helper_usat(tmp
, tmp
, tmp2
);
7818 if ((op
& 1) && shift
== 0)
7819 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7821 gen_helper_ssat(tmp
, tmp
, tmp2
);
7825 store_reg(s
, rd
, tmp
);
7827 imm
= ((insn
& 0x04000000) >> 15)
7828 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7829 if (insn
& (1 << 22)) {
7830 /* 16-bit immediate. */
7831 imm
|= (insn
>> 4) & 0xf000;
7832 if (insn
& (1 << 23)) {
7834 tmp
= load_reg(s
, rd
);
7835 tcg_gen_ext16u_i32(tmp
, tmp
);
7836 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7840 tcg_gen_movi_i32(tmp
, imm
);
7843 /* Add/sub 12-bit immediate. */
7845 offset
= s
->pc
& ~(uint32_t)3;
7846 if (insn
& (1 << 23))
7851 tcg_gen_movi_i32(tmp
, offset
);
7853 tmp
= load_reg(s
, rn
);
7854 if (insn
& (1 << 23))
7855 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7857 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7860 store_reg(s
, rd
, tmp
);
7863 int shifter_out
= 0;
7864 /* modified 12-bit immediate. */
7865 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7866 imm
= (insn
& 0xff);
7869 /* Nothing to do. */
7871 case 1: /* 00XY00XY */
7874 case 2: /* XY00XY00 */
7878 case 3: /* XYXYXYXY */
7882 default: /* Rotated constant. */
7883 shift
= (shift
<< 1) | (imm
>> 7);
7885 imm
= imm
<< (32 - shift
);
7890 tcg_gen_movi_i32(tmp2
, imm
);
7891 rn
= (insn
>> 16) & 0xf;
7894 tcg_gen_movi_i32(tmp
, 0);
7896 tmp
= load_reg(s
, rn
);
7898 op
= (insn
>> 21) & 0xf;
7899 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7900 shifter_out
, tmp
, tmp2
))
7903 rd
= (insn
>> 8) & 0xf;
7905 store_reg(s
, rd
, tmp
);
7912 case 12: /* Load/store single data item. */
7917 if ((insn
& 0x01100000) == 0x01000000) {
7918 if (disas_neon_ls_insn(env
, s
, insn
))
7926 /* s->pc has already been incremented by 4. */
7927 imm
= s
->pc
& 0xfffffffc;
7928 if (insn
& (1 << 23))
7929 imm
+= insn
& 0xfff;
7931 imm
-= insn
& 0xfff;
7932 tcg_gen_movi_i32(addr
, imm
);
7934 addr
= load_reg(s
, rn
);
7935 if (insn
& (1 << 23)) {
7936 /* Positive offset. */
7938 tcg_gen_addi_i32(addr
, addr
, imm
);
7940 op
= (insn
>> 8) & 7;
7943 case 0: case 8: /* Shifted Register. */
7944 shift
= (insn
>> 4) & 0xf;
7947 tmp
= load_reg(s
, rm
);
7949 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7950 tcg_gen_add_i32(addr
, addr
, tmp
);
7953 case 4: /* Negative offset. */
7954 tcg_gen_addi_i32(addr
, addr
, -imm
);
7956 case 6: /* User privilege. */
7957 tcg_gen_addi_i32(addr
, addr
, imm
);
7960 case 1: /* Post-decrement. */
7963 case 3: /* Post-increment. */
7967 case 5: /* Pre-decrement. */
7970 case 7: /* Pre-increment. */
7971 tcg_gen_addi_i32(addr
, addr
, imm
);
7979 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7980 if (insn
& (1 << 20)) {
7982 if (rs
== 15 && op
!= 2) {
7985 /* Memory hint. Implemented as NOP. */
7988 case 0: tmp
= gen_ld8u(addr
, user
); break;
7989 case 4: tmp
= gen_ld8s(addr
, user
); break;
7990 case 1: tmp
= gen_ld16u(addr
, user
); break;
7991 case 5: tmp
= gen_ld16s(addr
, user
); break;
7992 case 2: tmp
= gen_ld32(addr
, user
); break;
7993 default: goto illegal_op
;
7995 if (rs
== 15 && ENABLE_ARCH_5
) {
7998 store_reg(s
, rs
, tmp
);
8005 tmp
= load_reg(s
, rs
);
8007 case 0: gen_st8(tmp
, addr
, user
); break;
8008 case 1: gen_st16(tmp
, addr
, user
); break;
8009 case 2: gen_st32(tmp
, addr
, user
); break;
8010 default: goto illegal_op
;
8014 tcg_gen_addi_i32(addr
, addr
, imm
);
8016 store_reg(s
, rn
, addr
);
8030 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8032 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8040 if (s
->condexec_mask
) {
8041 cond
= s
->condexec_cond
;
8042 s
->condlabel
= gen_new_label();
8043 gen_test_cc(cond
^ 1, s
->condlabel
);
8047 insn
= lduw_code(s
->pc
);
8050 switch (insn
>> 12) {
8054 op
= (insn
>> 11) & 3;
8057 rn
= (insn
>> 3) & 7;
8058 tmp
= load_reg(s
, rn
);
8059 if (insn
& (1 << 10)) {
8062 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8065 rm
= (insn
>> 6) & 7;
8066 tmp2
= load_reg(s
, rm
);
8068 if (insn
& (1 << 9)) {
8069 if (s
->condexec_mask
)
8070 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8072 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8074 if (s
->condexec_mask
)
8075 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8077 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8080 store_reg(s
, rd
, tmp
);
8082 /* shift immediate */
8083 rm
= (insn
>> 3) & 7;
8084 shift
= (insn
>> 6) & 0x1f;
8085 tmp
= load_reg(s
, rm
);
8086 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8087 if (!s
->condexec_mask
)
8089 store_reg(s
, rd
, tmp
);
8093 /* arithmetic large immediate */
8094 op
= (insn
>> 11) & 3;
8095 rd
= (insn
>> 8) & 0x7;
8096 if (op
== 0) { /* mov */
8098 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8099 if (!s
->condexec_mask
)
8101 store_reg(s
, rd
, tmp
);
8103 tmp
= load_reg(s
, rd
);
8105 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8108 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8113 if (s
->condexec_mask
)
8114 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8116 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8118 store_reg(s
, rd
, tmp
);
8121 if (s
->condexec_mask
)
8122 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8124 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8126 store_reg(s
, rd
, tmp
);
8132 if (insn
& (1 << 11)) {
8133 rd
= (insn
>> 8) & 7;
8134 /* load pc-relative. Bit 1 of PC is ignored. */
8135 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8136 val
&= ~(uint32_t)2;
8138 tcg_gen_movi_i32(addr
, val
);
8139 tmp
= gen_ld32(addr
, IS_USER(s
));
8141 store_reg(s
, rd
, tmp
);
8144 if (insn
& (1 << 10)) {
8145 /* data processing extended or blx */
8146 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8147 rm
= (insn
>> 3) & 0xf;
8148 op
= (insn
>> 8) & 3;
8151 tmp
= load_reg(s
, rd
);
8152 tmp2
= load_reg(s
, rm
);
8153 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8155 store_reg(s
, rd
, tmp
);
8158 tmp
= load_reg(s
, rd
);
8159 tmp2
= load_reg(s
, rm
);
8160 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8164 case 2: /* mov/cpy */
8165 tmp
= load_reg(s
, rm
);
8166 store_reg(s
, rd
, tmp
);
8168 case 3:/* branch [and link] exchange thumb register */
8169 tmp
= load_reg(s
, rm
);
8170 if (insn
& (1 << 7)) {
8172 val
= (uint32_t)s
->pc
| 1;
8174 tcg_gen_movi_i32(tmp2
, val
);
8175 store_reg(s
, 14, tmp2
);
8183 /* data processing register */
8185 rm
= (insn
>> 3) & 7;
8186 op
= (insn
>> 6) & 0xf;
8187 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8188 /* the shift/rotate ops want the operands backwards */
8197 if (op
== 9) { /* neg */
8199 tcg_gen_movi_i32(tmp
, 0);
8200 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8201 tmp
= load_reg(s
, rd
);
8206 tmp2
= load_reg(s
, rm
);
8209 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8210 if (!s
->condexec_mask
)
8214 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8215 if (!s
->condexec_mask
)
8219 if (s
->condexec_mask
) {
8220 gen_helper_shl(tmp2
, tmp2
, tmp
);
8222 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8227 if (s
->condexec_mask
) {
8228 gen_helper_shr(tmp2
, tmp2
, tmp
);
8230 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8235 if (s
->condexec_mask
) {
8236 gen_helper_sar(tmp2
, tmp2
, tmp
);
8238 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8243 if (s
->condexec_mask
)
8244 gen_add_carry(tmp
, tmp
, tmp2
);
8246 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8249 if (s
->condexec_mask
)
8250 gen_sub_carry(tmp
, tmp
, tmp2
);
8252 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8255 if (s
->condexec_mask
) {
8256 gen_helper_ror(tmp2
, tmp2
, tmp
);
8258 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8263 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8268 if (s
->condexec_mask
)
8269 tcg_gen_neg_i32(tmp
, tmp2
);
8271 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8274 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8278 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8282 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8283 if (!s
->condexec_mask
)
8287 gen_mull(tmp
, tmp2
);
8288 if (!s
->condexec_mask
)
8292 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8293 if (!s
->condexec_mask
)
8297 tcg_gen_not_i32(tmp2
, tmp2
);
8298 if (!s
->condexec_mask
)
8306 store_reg(s
, rm
, tmp2
);
8310 store_reg(s
, rd
, tmp
);
8320 /* load/store register offset. */
8322 rn
= (insn
>> 3) & 7;
8323 rm
= (insn
>> 6) & 7;
8324 op
= (insn
>> 9) & 7;
8325 addr
= load_reg(s
, rn
);
8326 tmp
= load_reg(s
, rm
);
8327 tcg_gen_add_i32(addr
, addr
, tmp
);
8330 if (op
< 3) /* store */
8331 tmp
= load_reg(s
, rd
);
8335 gen_st32(tmp
, addr
, IS_USER(s
));
8338 gen_st16(tmp
, addr
, IS_USER(s
));
8341 gen_st8(tmp
, addr
, IS_USER(s
));
8344 tmp
= gen_ld8s(addr
, IS_USER(s
));
8347 tmp
= gen_ld32(addr
, IS_USER(s
));
8350 tmp
= gen_ld16u(addr
, IS_USER(s
));
8353 tmp
= gen_ld8u(addr
, IS_USER(s
));
8356 tmp
= gen_ld16s(addr
, IS_USER(s
));
8359 if (op
>= 3) /* load */
8360 store_reg(s
, rd
, tmp
);
8365 /* load/store word immediate offset */
8367 rn
= (insn
>> 3) & 7;
8368 addr
= load_reg(s
, rn
);
8369 val
= (insn
>> 4) & 0x7c;
8370 tcg_gen_addi_i32(addr
, addr
, val
);
8372 if (insn
& (1 << 11)) {
8374 tmp
= gen_ld32(addr
, IS_USER(s
));
8375 store_reg(s
, rd
, tmp
);
8378 tmp
= load_reg(s
, rd
);
8379 gen_st32(tmp
, addr
, IS_USER(s
));
8385 /* load/store byte immediate offset */
8387 rn
= (insn
>> 3) & 7;
8388 addr
= load_reg(s
, rn
);
8389 val
= (insn
>> 6) & 0x1f;
8390 tcg_gen_addi_i32(addr
, addr
, val
);
8392 if (insn
& (1 << 11)) {
8394 tmp
= gen_ld8u(addr
, IS_USER(s
));
8395 store_reg(s
, rd
, tmp
);
8398 tmp
= load_reg(s
, rd
);
8399 gen_st8(tmp
, addr
, IS_USER(s
));
8405 /* load/store halfword immediate offset */
8407 rn
= (insn
>> 3) & 7;
8408 addr
= load_reg(s
, rn
);
8409 val
= (insn
>> 5) & 0x3e;
8410 tcg_gen_addi_i32(addr
, addr
, val
);
8412 if (insn
& (1 << 11)) {
8414 tmp
= gen_ld16u(addr
, IS_USER(s
));
8415 store_reg(s
, rd
, tmp
);
8418 tmp
= load_reg(s
, rd
);
8419 gen_st16(tmp
, addr
, IS_USER(s
));
8425 /* load/store from stack */
8426 rd
= (insn
>> 8) & 7;
8427 addr
= load_reg(s
, 13);
8428 val
= (insn
& 0xff) * 4;
8429 tcg_gen_addi_i32(addr
, addr
, val
);
8431 if (insn
& (1 << 11)) {
8433 tmp
= gen_ld32(addr
, IS_USER(s
));
8434 store_reg(s
, rd
, tmp
);
8437 tmp
= load_reg(s
, rd
);
8438 gen_st32(tmp
, addr
, IS_USER(s
));
8444 /* add to high reg */
8445 rd
= (insn
>> 8) & 7;
8446 if (insn
& (1 << 11)) {
8448 tmp
= load_reg(s
, 13);
8450 /* PC. bit 1 is ignored. */
8452 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8454 val
= (insn
& 0xff) * 4;
8455 tcg_gen_addi_i32(tmp
, tmp
, val
);
8456 store_reg(s
, rd
, tmp
);
8461 op
= (insn
>> 8) & 0xf;
8464 /* adjust stack pointer */
8465 tmp
= load_reg(s
, 13);
8466 val
= (insn
& 0x7f) * 4;
8467 if (insn
& (1 << 7))
8468 val
= -(int32_t)val
;
8469 tcg_gen_addi_i32(tmp
, tmp
, val
);
8470 store_reg(s
, 13, tmp
);
8473 case 2: /* sign/zero extend. */
8476 rm
= (insn
>> 3) & 7;
8477 tmp
= load_reg(s
, rm
);
8478 switch ((insn
>> 6) & 3) {
8479 case 0: gen_sxth(tmp
); break;
8480 case 1: gen_sxtb(tmp
); break;
8481 case 2: gen_uxth(tmp
); break;
8482 case 3: gen_uxtb(tmp
); break;
8484 store_reg(s
, rd
, tmp
);
8486 case 4: case 5: case 0xc: case 0xd:
8488 addr
= load_reg(s
, 13);
8489 if (insn
& (1 << 8))
8493 for (i
= 0; i
< 8; i
++) {
8494 if (insn
& (1 << i
))
8497 if ((insn
& (1 << 11)) == 0) {
8498 tcg_gen_addi_i32(addr
, addr
, -offset
);
8500 for (i
= 0; i
< 8; i
++) {
8501 if (insn
& (1 << i
)) {
8502 if (insn
& (1 << 11)) {
8504 tmp
= gen_ld32(addr
, IS_USER(s
));
8505 store_reg(s
, i
, tmp
);
8508 tmp
= load_reg(s
, i
);
8509 gen_st32(tmp
, addr
, IS_USER(s
));
8511 /* advance to the next address. */
8512 tcg_gen_addi_i32(addr
, addr
, 4);
8516 if (insn
& (1 << 8)) {
8517 if (insn
& (1 << 11)) {
8519 tmp
= gen_ld32(addr
, IS_USER(s
));
8520 /* don't set the pc until the rest of the instruction
8524 tmp
= load_reg(s
, 14);
8525 gen_st32(tmp
, addr
, IS_USER(s
));
8527 tcg_gen_addi_i32(addr
, addr
, 4);
8529 if ((insn
& (1 << 11)) == 0) {
8530 tcg_gen_addi_i32(addr
, addr
, -offset
);
8532 /* write back the new stack pointer */
8533 store_reg(s
, 13, addr
);
8534 /* set the new PC value */
8535 if ((insn
& 0x0900) == 0x0900) {
8536 if (ENABLE_ARCH_5
) {
8539 store_reg(s
, 15, tmp
);
8544 case 1: case 3: case 9: case 11: /* czb */
8546 tmp
= load_reg(s
, rm
);
8547 s
->condlabel
= gen_new_label();
8549 if (insn
& (1 << 11))
8550 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8552 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8554 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8555 val
= (uint32_t)s
->pc
+ 2;
8560 case 15: /* IT, nop-hint. */
8561 if ((insn
& 0xf) == 0) {
8562 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8566 s
->condexec_cond
= (insn
>> 4) & 0xe;
8567 s
->condexec_mask
= insn
& 0x1f;
8568 /* No actual code generated for this insn, just setup state. */
8571 case 0xe: /* bkpt */
8572 gen_set_condexec(s
);
8573 gen_set_pc_im(s
->pc
- 2);
8574 gen_exception(EXCP_BKPT
);
8575 s
->is_jmp
= DISAS_JUMP
;
8580 rn
= (insn
>> 3) & 0x7;
8582 tmp
= load_reg(s
, rn
);
8583 switch ((insn
>> 6) & 3) {
8584 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8585 case 1: gen_rev16(tmp
); break;
8586 case 3: gen_revsh(tmp
); break;
8587 default: goto illegal_op
;
8589 store_reg(s
, rd
, tmp
);
8597 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8600 addr
= tcg_const_i32(16);
8601 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8605 addr
= tcg_const_i32(17);
8606 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8610 if (insn
& (1 << 4))
8611 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8614 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8624 /* load/store multiple */
8625 rn
= (insn
>> 8) & 0x7;
8626 addr
= load_reg(s
, rn
);
8627 if (arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << rn
)) == 0) {
8628 /* base-updated abort model: update base register
8629 before an abort can happen */
8631 for (i
= 0; i
< 8; i
++) {
8632 if (insn
& (1 << i
)) {
8637 tcg_gen_addi_i32(tmp
, addr
, crement
);
8638 store_reg(s
, rn
, tmp
);
8640 for (i
= 0; i
< 8; i
++) {
8641 if (insn
& (1 << i
)) {
8642 if (insn
& (1 << 11)) {
8644 tmp
= gen_ld32(addr
, IS_USER(s
));
8645 store_reg(s
, i
, tmp
);
8648 tmp
= load_reg(s
, i
);
8649 gen_st32(tmp
, addr
, IS_USER(s
));
8651 /* advance to the next address */
8652 tcg_gen_addi_i32(addr
, addr
, 4);
8655 /* Base register writeback. */
8656 if (!arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << rn
)) == 0) {
8657 store_reg(s
, rn
, addr
);
8664 /* conditional branch or swi */
8665 cond
= (insn
>> 8) & 0xf;
8671 gen_set_condexec(s
);
8672 gen_set_pc_im(s
->pc
);
8673 s
->is_jmp
= DISAS_SWI
;
8676 /* generate a conditional jump to next instruction */
8677 s
->condlabel
= gen_new_label();
8678 gen_test_cc(cond
^ 1, s
->condlabel
);
8681 /* jump to the offset */
8682 val
= (uint32_t)s
->pc
+ 2;
8683 offset
= ((int32_t)insn
<< 24) >> 24;
8689 if (insn
& (1 << 11)) {
8690 if (disas_thumb2_insn(env
, s
, insn
))
8694 /* unconditional branch */
8695 val
= (uint32_t)s
->pc
;
8696 offset
= ((int32_t)insn
<< 21) >> 21;
8697 val
+= (offset
<< 1) + 2;
8702 if (disas_thumb2_insn(env
, s
, insn
))
8708 gen_set_condexec(s
);
8709 gen_set_pc_im(s
->pc
- 4);
8710 gen_exception(EXCP_UDEF
);
8711 s
->is_jmp
= DISAS_JUMP
;
8715 gen_set_condexec(s
);
8716 gen_set_pc_im(s
->pc
- 2);
8717 gen_exception(EXCP_UDEF
);
8718 s
->is_jmp
= DISAS_JUMP
;
8721 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8722 basic block 'tb'. If search_pc is TRUE, also generate PC
8723 information for each intermediate instruction. */
8724 static inline void gen_intermediate_code_internal(CPUState
*env
,
8725 TranslationBlock
*tb
,
8728 DisasContext dc1
, *dc
= &dc1
;
8730 uint16_t *gen_opc_end
;
8732 target_ulong pc_start
;
8733 uint32_t next_page_start
;
8737 /* generate intermediate code */
8744 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8746 dc
->is_jmp
= DISAS_NEXT
;
8748 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8750 dc
->thumb
= env
->thumb
;
8751 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8752 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8753 #if !defined(CONFIG_USER_ONLY)
8755 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8757 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8760 cpu_F0s
= tcg_temp_new_i32();
8761 cpu_F1s
= tcg_temp_new_i32();
8762 cpu_F0d
= tcg_temp_new_i64();
8763 cpu_F1d
= tcg_temp_new_i64();
8766 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8767 cpu_M0
= tcg_temp_new_i64();
8768 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8771 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8773 max_insns
= CF_COUNT_MASK
;
8776 /* Reset the conditional execution bits immediately. This avoids
8777 complications trying to do it at the end of the block. */
8778 if (env
->condexec_bits
)
8780 TCGv tmp
= new_tmp();
8781 tcg_gen_movi_i32(tmp
, 0);
8782 store_cpu_field(tmp
, condexec_bits
);
8785 #ifdef CONFIG_USER_ONLY
8786 /* Intercept jump to the magic kernel page. */
8787 if (dc
->pc
>= 0xffff0000) {
8788 /* We always get here via a jump, so know we are not in a
8789 conditional execution block. */
8790 gen_exception(EXCP_KERNEL_TRAP
);
8791 dc
->is_jmp
= DISAS_UPDATE
;
8795 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8796 /* We always get here via a jump, so know we are not in a
8797 conditional execution block. */
8798 gen_exception(EXCP_EXCEPTION_EXIT
);
8799 dc
->is_jmp
= DISAS_UPDATE
;
8804 if (unlikely(!TAILQ_EMPTY(&env
->breakpoints
))) {
8805 TAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8806 if (bp
->pc
== dc
->pc
) {
8807 gen_set_condexec(dc
);
8808 gen_set_pc_im(dc
->pc
);
8809 gen_exception(EXCP_DEBUG
);
8810 dc
->is_jmp
= DISAS_JUMP
;
8811 /* Advance PC so that clearing the breakpoint will
8812 invalidate this TB. */
8814 goto done_generating
;
8820 j
= gen_opc_ptr
- gen_opc_buf
;
8824 gen_opc_instr_start
[lj
++] = 0;
8826 gen_opc_pc
[lj
] = dc
->pc
;
8827 gen_opc_instr_start
[lj
] = 1;
8828 gen_opc_icount
[lj
] = num_insns
;
8831 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8835 disas_thumb_insn(env
, dc
);
8836 if (dc
->condexec_mask
) {
8837 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8838 | ((dc
->condexec_mask
>> 4) & 1);
8839 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8840 if (dc
->condexec_mask
== 0) {
8841 dc
->condexec_cond
= 0;
8845 disas_arm_insn(env
, dc
);
8848 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8852 if (dc
->condjmp
&& !dc
->is_jmp
) {
8853 gen_set_label(dc
->condlabel
);
8856 /* Translation stops when a conditional branch is encountered.
8857 * Otherwise the subsequent code could get translated several times.
8858 * Also stop translation when a page boundary is reached. This
8859 * ensures prefetch aborts occur at the right place. */
8861 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8862 !env
->singlestep_enabled
&&
8864 dc
->pc
< next_page_start
&&
8865 num_insns
< max_insns
);
8867 if (tb
->cflags
& CF_LAST_IO
) {
8869 /* FIXME: This can theoretically happen with self-modifying
8871 cpu_abort(env
, "IO on conditional branch instruction");
8876 /* At this stage dc->condjmp will only be set when the skipped
8877 instruction was a conditional branch or trap, and the PC has
8878 already been written. */
8879 if (unlikely(env
->singlestep_enabled
)) {
8880 /* Make sure the pc is updated, and raise a debug exception. */
8882 gen_set_condexec(dc
);
8883 if (dc
->is_jmp
== DISAS_SWI
) {
8884 gen_exception(EXCP_SWI
);
8886 gen_exception(EXCP_DEBUG
);
8888 gen_set_label(dc
->condlabel
);
8890 if (dc
->condjmp
|| !dc
->is_jmp
) {
8891 gen_set_pc_im(dc
->pc
);
8894 gen_set_condexec(dc
);
8895 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8896 gen_exception(EXCP_SWI
);
8898 /* FIXME: Single stepping a WFI insn will not halt
8900 gen_exception(EXCP_DEBUG
);
8903 /* While branches must always occur at the end of an IT block,
8904 there are a few other things that can cause us to terminate
8905 the TB in the middel of an IT block:
8906 - Exception generating instructions (bkpt, swi, undefined).
8908 - Hardware watchpoints.
8909 Hardware breakpoints have already been handled and skip this code.
8911 gen_set_condexec(dc
);
8912 switch(dc
->is_jmp
) {
8914 gen_goto_tb(dc
, 1, dc
->pc
);
8919 /* indicate that the hash table must be used to find the next TB */
8923 /* nothing more to generate */
8929 gen_exception(EXCP_SWI
);
8933 gen_set_label(dc
->condlabel
);
8934 gen_set_condexec(dc
);
8935 gen_goto_tb(dc
, 1, dc
->pc
);
8941 gen_icount_end(tb
, num_insns
);
8942 *gen_opc_ptr
= INDEX_op_end
;
8945 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8946 qemu_log("----------------\n");
8947 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8948 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8953 j
= gen_opc_ptr
- gen_opc_buf
;
8956 gen_opc_instr_start
[lj
++] = 0;
8958 tb
->size
= dc
->pc
- pc_start
;
8959 tb
->icount
= num_insns
;
8963 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8965 gen_intermediate_code_internal(env
, tb
, 0);
8968 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8970 gen_intermediate_code_internal(env
, tb
, 1);
8973 static const char *cpu_mode_names
[16] = {
8974 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8975 "???", "???", "???", "und", "???", "???", "???", "sys"
8978 void cpu_dump_state(CPUState
*env
, FILE *f
,
8979 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8989 /* ??? This assumes float64 and double have the same layout.
8990 Oh well, it's only debug dumps. */
8999 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
9001 cpu_fprintf(f
, "\n");
9003 cpu_fprintf(f
, " ");
9005 psr
= cpsr_read(env
);
9006 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9008 psr
& (1 << 31) ? 'N' : '-',
9009 psr
& (1 << 30) ? 'Z' : '-',
9010 psr
& (1 << 29) ? 'C' : '-',
9011 psr
& (1 << 28) ? 'V' : '-',
9012 psr
& CPSR_T
? 'T' : 'A',
9013 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9016 for (i
= 0; i
< 16; i
++) {
9017 d
.d
= env
->vfp
.regs
[i
];
9021 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9022 i
* 2, (int)s0
.i
, s0
.s
,
9023 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9024 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9027 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9031 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9032 uintptr_t searched_pc
, int pc_pos
, void *puc
)
9034 env
->regs
[15] = gen_opc_pc
[pc_pos
];