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_mov_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
);
3143 /* load/store multiple */
3145 n
= (insn
>> 1) & 0x7f;
3149 if (insn
& (1 << 24)) /* pre-decrement */
3150 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3156 for (i
= 0; i
< n
; i
++) {
3157 if (insn
& ARM_CP_RW_BIT
) {
3159 gen_vfp_ld(s
, dp
, addr
);
3160 gen_mov_vreg_F0(dp
, rd
+ i
);
3163 gen_mov_F0_vreg(dp
, rd
+ i
);
3164 gen_vfp_st(s
, dp
, addr
);
3166 tcg_gen_addi_i32(addr
, addr
, offset
);
3168 if (insn
& (1 << 21)) {
3170 if (insn
& (1 << 24))
3171 offset
= -offset
* n
;
3172 else if (dp
&& (insn
& 1))
3178 tcg_gen_addi_i32(addr
, addr
, offset
);
3179 store_reg(s
, rn
, addr
);
3187 /* Should never happen. */
3193 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3195 TranslationBlock
*tb
;
3198 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3200 gen_set_pc_im(dest
);
3201 tcg_gen_exit_tb((long)tb
+ n
);
3203 gen_set_pc_im(dest
);
3208 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3210 if (unlikely(s
->singlestep_enabled
)) {
3211 /* An indirect jump so that we still trigger the debug exception. */
3216 gen_goto_tb(s
, 0, dest
);
3217 s
->is_jmp
= DISAS_TB_JUMP
;
3221 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3224 tcg_gen_sari_i32(t0
, t0
, 16);
3228 tcg_gen_sari_i32(t1
, t1
, 16);
3231 tcg_gen_mul_i32(t0
, t0
, t1
);
3234 /* Return the mask of PSR bits set by a MSR instruction. */
3235 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3239 if (flags
& (1 << 0))
3241 if (flags
& (1 << 1))
3243 if (flags
& (1 << 2))
3245 if (flags
& (1 << 3))
3248 /* Mask out undefined bits. */
3249 mask
&= ~CPSR_RESERVED
;
3250 if (!arm_feature(env
, ARM_FEATURE_V6
))
3251 mask
&= ~(CPSR_E
| CPSR_GE
);
3252 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3254 /* Mask out execution state bits. */
3257 /* Mask out privileged bits. */
3263 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3264 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv t0
)
3268 /* ??? This is also undefined in system mode. */
3272 tmp
= load_cpu_field(spsr
);
3273 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3274 tcg_gen_andi_i32(t0
, t0
, mask
);
3275 tcg_gen_or_i32(tmp
, tmp
, t0
);
3276 store_cpu_field(tmp
, spsr
);
3278 gen_set_cpsr(t0
, mask
);
3285 /* Returns nonzero if access to the PSR is not permitted. */
3286 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3290 tcg_gen_movi_i32(tmp
, val
);
3291 return gen_set_psr(s
, mask
, spsr
, tmp
);
3294 /* Generate an old-style exception return. Marks pc as dead. */
3295 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3298 store_reg(s
, 15, pc
);
3299 tmp
= load_cpu_field(spsr
);
3300 gen_set_cpsr(tmp
, 0xffffffff);
3302 s
->is_jmp
= DISAS_UPDATE
;
3305 /* Generate a v6 exception return. Marks both values as dead. */
3306 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3308 gen_set_cpsr(cpsr
, 0xffffffff);
3310 store_reg(s
, 15, pc
);
3311 s
->is_jmp
= DISAS_UPDATE
;
3315 gen_set_condexec (DisasContext
*s
)
3317 if (s
->condexec_mask
) {
3318 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3319 TCGv tmp
= new_tmp();
3320 tcg_gen_movi_i32(tmp
, val
);
3321 store_cpu_field(tmp
, condexec_bits
);
3325 static void gen_nop_hint(DisasContext
*s
, int val
)
3329 gen_set_pc_im(s
->pc
);
3330 s
->is_jmp
= DISAS_WFI
;
3334 /* TODO: Implement SEV and WFE. May help SMP performance. */
3340 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3342 static inline int gen_neon_add(int size
, TCGv t0
, TCGv t1
)
3345 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3346 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3347 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3353 static inline void gen_neon_rsb(int size
, TCGv t0
, TCGv t1
)
3356 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3357 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3358 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3363 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3364 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3365 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3366 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3367 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3369 /* FIXME: This is wrong. They set the wrong overflow bit. */
3370 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3371 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3372 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3373 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3375 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3376 switch ((size << 1) | u) { \
3378 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3381 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3384 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3387 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3390 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3393 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3395 default: return 1; \
3398 #define GEN_NEON_INTEGER_OP(name) do { \
3399 switch ((size << 1) | u) { \
3401 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3404 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3407 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3410 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3413 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3416 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3418 default: return 1; \
3421 static TCGv
neon_load_scratch(int scratch
)
3423 TCGv tmp
= new_tmp();
3424 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3428 static void neon_store_scratch(int scratch
, TCGv var
)
3430 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3434 static inline TCGv
neon_get_scalar(int size
, int reg
)
3438 tmp
= neon_load_reg(reg
>> 1, reg
& 1);
3440 tmp
= neon_load_reg(reg
>> 2, (reg
>> 1) & 1);
3442 gen_neon_dup_low16(tmp
);
3444 gen_neon_dup_high16(tmp
);
3450 static void gen_neon_unzip_u8(TCGv t0
, TCGv t1
)
3458 tcg_gen_andi_i32(rd
, t0
, 0xff);
3459 tcg_gen_shri_i32(tmp
, t0
, 8);
3460 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3461 tcg_gen_or_i32(rd
, rd
, tmp
);
3462 tcg_gen_shli_i32(tmp
, t1
, 16);
3463 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3464 tcg_gen_or_i32(rd
, rd
, tmp
);
3465 tcg_gen_shli_i32(tmp
, t1
, 8);
3466 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3467 tcg_gen_or_i32(rd
, rd
, tmp
);
3469 tcg_gen_shri_i32(rm
, t0
, 8);
3470 tcg_gen_andi_i32(rm
, rm
, 0xff);
3471 tcg_gen_shri_i32(tmp
, t0
, 16);
3472 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3473 tcg_gen_or_i32(rm
, rm
, tmp
);
3474 tcg_gen_shli_i32(tmp
, t1
, 8);
3475 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3476 tcg_gen_or_i32(rm
, rm
, tmp
);
3477 tcg_gen_andi_i32(tmp
, t1
, 0xff000000);
3478 tcg_gen_or_i32(t1
, rm
, tmp
);
3479 tcg_gen_mov_i32(t0
, rd
);
3486 static void gen_neon_zip_u8(TCGv t0
, TCGv t1
)
3494 tcg_gen_andi_i32(rd
, t0
, 0xff);
3495 tcg_gen_shli_i32(tmp
, t1
, 8);
3496 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3497 tcg_gen_or_i32(rd
, rd
, tmp
);
3498 tcg_gen_shli_i32(tmp
, t0
, 16);
3499 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3500 tcg_gen_or_i32(rd
, rd
, tmp
);
3501 tcg_gen_shli_i32(tmp
, t1
, 24);
3502 tcg_gen_andi_i32(tmp
, tmp
, 0xff000000);
3503 tcg_gen_or_i32(rd
, rd
, tmp
);
3505 tcg_gen_andi_i32(rm
, t1
, 0xff000000);
3506 tcg_gen_shri_i32(tmp
, t0
, 8);
3507 tcg_gen_andi_i32(tmp
, tmp
, 0xff0000);
3508 tcg_gen_or_i32(rm
, rm
, tmp
);
3509 tcg_gen_shri_i32(tmp
, t1
, 8);
3510 tcg_gen_andi_i32(tmp
, tmp
, 0xff00);
3511 tcg_gen_or_i32(rm
, rm
, tmp
);
3512 tcg_gen_shri_i32(tmp
, t0
, 16);
3513 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
3514 tcg_gen_or_i32(t1
, rm
, tmp
);
3515 tcg_gen_mov_i32(t0
, rd
);
3522 static void gen_neon_zip_u16(TCGv t0
, TCGv t1
)
3529 tcg_gen_andi_i32(tmp
, t0
, 0xffff);
3530 tcg_gen_shli_i32(tmp2
, t1
, 16);
3531 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3532 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
3533 tcg_gen_shri_i32(tmp2
, t0
, 16);
3534 tcg_gen_or_i32(t1
, t1
, tmp2
);
3535 tcg_gen_mov_i32(t0
, tmp
);
3541 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3546 for (n
= 0; n
< q
+ 1; n
+= 2) {
3547 t0
= neon_load_reg(reg
, n
);
3548 t1
= neon_load_reg(reg
, n
+ 1);
3550 case 0: gen_neon_unzip_u8(t0
, t1
); break;
3551 case 1: gen_neon_zip_u16(t0
, t1
); break; /* zip and unzip are the same. */
3552 case 2: /* no-op */; break;
3555 neon_store_scratch(tmp
+ n
, t0
);
3556 neon_store_scratch(tmp
+ n
+ 1, t1
);
3560 static void gen_neon_trn_u8(TCGv t0
, TCGv t1
)
3567 tcg_gen_shli_i32(rd
, t0
, 8);
3568 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3569 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3570 tcg_gen_or_i32(rd
, rd
, tmp
);
3572 tcg_gen_shri_i32(t1
, t1
, 8);
3573 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3574 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3575 tcg_gen_or_i32(t1
, t1
, tmp
);
3576 tcg_gen_mov_i32(t0
, rd
);
3582 static void gen_neon_trn_u16(TCGv t0
, TCGv t1
)
3589 tcg_gen_shli_i32(rd
, t0
, 16);
3590 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3591 tcg_gen_or_i32(rd
, rd
, tmp
);
3592 tcg_gen_shri_i32(t1
, t1
, 16);
3593 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3594 tcg_gen_or_i32(t1
, t1
, tmp
);
3595 tcg_gen_mov_i32(t0
, rd
);
3606 } neon_ls_element_type
[11] = {
3620 /* Translate a NEON load/store element instruction. Return nonzero if the
3621 instruction is invalid. */
3622 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3639 if (!vfp_enabled(env
))
3641 VFP_DREG_D(rd
, insn
);
3642 rn
= (insn
>> 16) & 0xf;
3644 load
= (insn
& (1 << 21)) != 0;
3646 if ((insn
& (1 << 23)) == 0) {
3647 /* Load store all elements. */
3648 op
= (insn
>> 8) & 0xf;
3649 size
= (insn
>> 6) & 3;
3650 if (op
> 10 || size
== 3)
3652 nregs
= neon_ls_element_type
[op
].nregs
;
3653 interleave
= neon_ls_element_type
[op
].interleave
;
3654 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3655 stride
= (1 << size
) * interleave
;
3656 for (reg
= 0; reg
< nregs
; reg
++) {
3657 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3658 tcg_gen_add_i32(addr
, cpu_R
[rn
], (1 << size
) * reg
);
3659 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3660 tcg_gen_add_i32(addr
, cpu_R
[rn
], 1 << size
);
3662 for (pass
= 0; pass
< 2; pass
++) {
3665 tmp
= gen_ld32(addr
, IS_USER(s
));
3666 neon_store_reg(rd
, pass
, tmp
);
3668 tmp
= neon_load_reg(rd
, pass
);
3669 gen_st32(tmp
, addr
, IS_USER(s
));
3671 tcg_gen_addi_i32(addr
, addr
, stride
);
3672 } else if (size
== 1) {
3674 tmp
= gen_ld16u(addr
, IS_USER(s
));
3675 tcg_gen_addi_i32(addr
, addr
, stride
);
3676 tmp2
= gen_ld16u(addr
, IS_USER(s
));
3677 tcg_gen_addi_i32(addr
, addr
, stride
);
3678 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3680 neon_store_reg(rd
, pass
, tmp
);
3682 tmp
= neon_load_reg(rd
, pass
);
3684 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3685 gen_st16(tmp
, addr
, IS_USER(s
));
3686 tcg_gen_addi_i32(addr
, addr
, stride
);
3687 gen_st16(tmp2
, addr
, IS_USER(s
));
3688 tcg_gen_addi_i32(addr
, addr
, stride
);
3690 } else /* size == 0 */ {
3693 for (n
= 0; n
< 4; n
++) {
3694 tmp
= gen_ld8u(addr
, IS_USER(s
));
3695 tcg_gen_addi_i32(addr
, addr
, stride
);
3699 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3703 neon_store_reg(rd
, pass
, tmp2
);
3705 tmp2
= neon_load_reg(rd
, pass
);
3706 for (n
= 0; n
< 4; n
++) {
3709 tcg_gen_mov_i32(tmp
, tmp2
);
3711 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3713 gen_st8(tmp
, addr
, IS_USER(s
));
3714 tcg_gen_addi_i32(addr
, addr
, stride
);
3720 rd
+= neon_ls_element_type
[op
].spacing
;
3724 size
= (insn
>> 10) & 3;
3726 /* Load single element to all lanes. */
3729 size
= (insn
>> 6) & 3;
3730 nregs
= ((insn
>> 8) & 3) + 1;
3731 stride
= (insn
& (1 << 5)) ? 2 : 1;
3732 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3733 for (reg
= 0; reg
< nregs
; reg
++) {
3736 tmp
= gen_ld8u(addr
, IS_USER(s
));
3737 gen_neon_dup_u8(tmp
, 0);
3740 tmp
= gen_ld16u(addr
, IS_USER(s
));
3741 gen_neon_dup_low16(tmp
);
3744 tmp
= gen_ld32(addr
, IS_USER(s
));
3748 default: /* Avoid compiler warnings. */
3751 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3753 tcg_gen_mov_i32(tmp2
, tmp
);
3754 neon_store_reg(rd
, 0, tmp2
);
3755 neon_store_reg(rd
, 1, tmp
);
3758 stride
= (1 << size
) * nregs
;
3760 /* Single element. */
3761 pass
= (insn
>> 7) & 1;
3764 shift
= ((insn
>> 5) & 3) * 8;
3768 shift
= ((insn
>> 6) & 1) * 16;
3769 stride
= (insn
& (1 << 5)) ? 2 : 1;
3773 stride
= (insn
& (1 << 6)) ? 2 : 1;
3778 nregs
= ((insn
>> 8) & 3) + 1;
3779 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
3780 for (reg
= 0; reg
< nregs
; reg
++) {
3784 tmp
= gen_ld8u(addr
, IS_USER(s
));
3787 tmp
= gen_ld16u(addr
, IS_USER(s
));
3790 tmp
= gen_ld32(addr
, IS_USER(s
));
3792 default: /* Avoid compiler warnings. */
3796 tmp2
= neon_load_reg(rd
, pass
);
3797 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3800 neon_store_reg(rd
, pass
, tmp
);
3801 } else { /* Store */
3802 tmp
= neon_load_reg(rd
, pass
);
3804 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3807 gen_st8(tmp
, addr
, IS_USER(s
));
3810 gen_st16(tmp
, addr
, IS_USER(s
));
3813 gen_st32(tmp
, addr
, IS_USER(s
));
3818 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3820 stride
= nregs
* (1 << size
);
3827 base
= load_reg(s
, rn
);
3829 tcg_gen_addi_i32(base
, base
, stride
);
3832 index
= load_reg(s
, rm
);
3833 tcg_gen_add_i32(base
, base
, index
);
3836 store_reg(s
, rn
, base
);
3841 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3842 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3844 tcg_gen_and_i32(t
, t
, c
);
3845 tcg_gen_bic_i32(f
, f
, c
);
3846 tcg_gen_or_i32(dest
, t
, f
);
3849 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3852 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3853 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3854 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3859 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3862 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3863 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3864 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3869 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3872 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3873 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3874 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3879 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3885 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3886 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3891 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3892 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3899 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3900 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3905 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3906 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3913 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3917 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3918 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3919 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3924 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3925 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3926 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3933 static inline void gen_neon_addl(int size
)
3936 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3937 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3938 case 2: tcg_gen_add_i64(CPU_V001
); break;
3943 static inline void gen_neon_subl(int size
)
3946 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
3947 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
3948 case 2: tcg_gen_sub_i64(CPU_V001
); break;
3953 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
3956 case 0: gen_helper_neon_negl_u16(var
, var
); break;
3957 case 1: gen_helper_neon_negl_u32(var
, var
); break;
3958 case 2: gen_helper_neon_negl_u64(var
, var
); break;
3963 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
3966 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
3967 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
3972 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
3976 switch ((size
<< 1) | u
) {
3977 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
3978 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
3979 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
3980 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
3982 tmp
= gen_muls_i64_i32(a
, b
);
3983 tcg_gen_mov_i64(dest
, tmp
);
3986 tmp
= gen_mulu_i64_i32(a
, b
);
3987 tcg_gen_mov_i64(dest
, tmp
);
3993 /* Translate a NEON data processing instruction. Return nonzero if the
3994 instruction is invalid.
3995 We process data in a mixture of 32-bit and 64-bit chunks.
3996 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
3998 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4016 if (!vfp_enabled(env
))
4018 q
= (insn
& (1 << 6)) != 0;
4019 u
= (insn
>> 24) & 1;
4020 VFP_DREG_D(rd
, insn
);
4021 VFP_DREG_N(rn
, insn
);
4022 VFP_DREG_M(rm
, insn
);
4023 size
= (insn
>> 20) & 3;
4024 if ((insn
& (1 << 23)) == 0) {
4025 /* Three register same length. */
4026 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4027 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4028 || op
== 10 || op
== 11 || op
== 16)) {
4029 /* 64-bit element instructions. */
4030 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4031 neon_load_reg64(cpu_V0
, rn
+ pass
);
4032 neon_load_reg64(cpu_V1
, rm
+ pass
);
4036 gen_helper_neon_add_saturate_u64(CPU_V001
);
4038 gen_helper_neon_add_saturate_s64(CPU_V001
);
4043 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4045 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4050 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4052 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4057 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4060 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4064 case 10: /* VRSHL */
4066 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4068 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4071 case 11: /* VQRSHL */
4073 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4076 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4082 tcg_gen_sub_i64(CPU_V001
);
4084 tcg_gen_add_i64(CPU_V001
);
4090 neon_store_reg64(cpu_V0
, rd
+ pass
);
4097 case 10: /* VRSHL */
4098 case 11: /* VQRSHL */
4101 /* Shift instruction operands are reversed. */
4108 case 20: /* VPMAX */
4109 case 21: /* VPMIN */
4110 case 23: /* VPADD */
4113 case 26: /* VPADD (float) */
4114 pairwise
= (u
&& size
< 2);
4116 case 30: /* VPMIN/VPMAX (float) */
4124 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4133 tmp
= neon_load_reg(rn
, n
);
4134 tmp2
= neon_load_reg(rn
, n
+ 1);
4136 tmp
= neon_load_reg(rm
, n
);
4137 tmp2
= neon_load_reg(rm
, n
+ 1);
4141 tmp
= neon_load_reg(rn
, pass
);
4142 tmp2
= neon_load_reg(rm
, pass
);
4146 GEN_NEON_INTEGER_OP(hadd
);
4149 GEN_NEON_INTEGER_OP_ENV(qadd
);
4151 case 2: /* VRHADD */
4152 GEN_NEON_INTEGER_OP(rhadd
);
4154 case 3: /* Logic ops. */
4155 switch ((u
<< 2) | size
) {
4157 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4160 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
4163 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4166 tcg_gen_not_i32(tmp2
, tmp2
);
4167 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4170 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4173 tmp3
= neon_load_reg(rd
, pass
);
4174 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4178 tmp3
= neon_load_reg(rd
, pass
);
4179 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4183 tmp3
= neon_load_reg(rd
, pass
);
4184 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4190 GEN_NEON_INTEGER_OP(hsub
);
4193 GEN_NEON_INTEGER_OP_ENV(qsub
);
4196 GEN_NEON_INTEGER_OP(cgt
);
4199 GEN_NEON_INTEGER_OP(cge
);
4202 GEN_NEON_INTEGER_OP(shl
);
4205 GEN_NEON_INTEGER_OP_ENV(qshl
);
4207 case 10: /* VRSHL */
4208 GEN_NEON_INTEGER_OP(rshl
);
4210 case 11: /* VQRSHL */
4211 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4214 GEN_NEON_INTEGER_OP(max
);
4217 GEN_NEON_INTEGER_OP(min
);
4220 GEN_NEON_INTEGER_OP(abd
);
4223 GEN_NEON_INTEGER_OP(abd
);
4225 tmp2
= neon_load_reg(rd
, pass
);
4226 gen_neon_add(size
, tmp
, tmp2
);
4229 if (!u
) { /* VADD */
4230 if (gen_neon_add(size
, tmp
, tmp2
))
4234 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4235 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4236 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4242 if (!u
) { /* VTST */
4244 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4245 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4246 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4251 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4252 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4253 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4258 case 18: /* Multiply. */
4260 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4261 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4262 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4266 tmp2
= neon_load_reg(rd
, pass
);
4268 gen_neon_rsb(size
, tmp
, tmp2
);
4270 gen_neon_add(size
, tmp
, tmp2
);
4274 if (u
) { /* polynomial */
4275 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4276 } else { /* Integer */
4278 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4279 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4280 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4285 case 20: /* VPMAX */
4286 GEN_NEON_INTEGER_OP(pmax
);
4288 case 21: /* VPMIN */
4289 GEN_NEON_INTEGER_OP(pmin
);
4291 case 22: /* Hultiply high. */
4292 if (!u
) { /* VQDMULH */
4294 case 1: gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4295 case 2: gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4298 } else { /* VQRDHMUL */
4300 case 1: gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
); break;
4301 case 2: gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
); break;
4306 case 23: /* VPADD */
4310 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4311 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4312 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4316 case 26: /* Floating point arithnetic. */
4317 switch ((u
<< 2) | size
) {
4319 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4322 gen_helper_neon_sub_f32(tmp
, tmp
, tmp2
);
4325 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4328 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
);
4334 case 27: /* Float multiply. */
4335 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4338 tmp2
= neon_load_reg(rd
, pass
);
4340 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4342 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
4346 case 28: /* Float compare. */
4348 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
4351 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
4353 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
4356 case 29: /* Float compare absolute. */
4360 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
);
4362 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
);
4364 case 30: /* Float min/max. */
4366 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
);
4368 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
);
4372 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4374 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4381 /* Save the result. For elementwise operations we can put it
4382 straight into the destination register. For pairwise operations
4383 we have to be careful to avoid clobbering the source operands. */
4384 if (pairwise
&& rd
== rm
) {
4385 neon_store_scratch(pass
, tmp
);
4387 neon_store_reg(rd
, pass
, tmp
);
4391 if (pairwise
&& rd
== rm
) {
4392 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4393 tmp
= neon_load_scratch(pass
);
4394 neon_store_reg(rd
, pass
, tmp
);
4397 /* End of 3 register same size operations. */
4398 } else if (insn
& (1 << 4)) {
4399 if ((insn
& 0x00380080) != 0) {
4400 /* Two registers and shift. */
4401 op
= (insn
>> 8) & 0xf;
4402 if (insn
& (1 << 7)) {
4407 while ((insn
& (1 << (size
+ 19))) == 0)
4410 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4411 /* To avoid excessive dumplication of ops we implement shift
4412 by immediate using the variable shift operations. */
4414 /* Shift by immediate:
4415 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4416 /* Right shifts are encoded as N - shift, where N is the
4417 element size in bits. */
4419 shift
= shift
- (1 << (size
+ 3));
4427 imm
= (uint8_t) shift
;
4432 imm
= (uint16_t) shift
;
4443 for (pass
= 0; pass
< count
; pass
++) {
4445 neon_load_reg64(cpu_V0
, rm
+ pass
);
4446 tcg_gen_movi_i64(cpu_V1
, imm
);
4451 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4453 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4458 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4460 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4465 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4467 case 5: /* VSHL, VSLI */
4468 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4472 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4474 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4476 case 7: /* VQSHLU */
4477 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4480 if (op
== 1 || op
== 3) {
4482 neon_load_reg64(cpu_V0
, rd
+ pass
);
4483 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4484 } else if (op
== 4 || (op
== 5 && u
)) {
4486 cpu_abort(env
, "VS[LR]I.64 not implemented");
4488 neon_store_reg64(cpu_V0
, rd
+ pass
);
4489 } else { /* size < 3 */
4490 /* Operands in T0 and T1. */
4491 tmp
= neon_load_reg(rm
, pass
);
4493 tcg_gen_movi_i32(tmp2
, imm
);
4497 GEN_NEON_INTEGER_OP(shl
);
4501 GEN_NEON_INTEGER_OP(rshl
);
4506 GEN_NEON_INTEGER_OP(shl
);
4508 case 5: /* VSHL, VSLI */
4510 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
4511 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
4512 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
4517 GEN_NEON_INTEGER_OP_ENV(qshl
);
4519 case 7: /* VQSHLU */
4521 case 0: gen_helper_neon_qshl_u8(tmp
, cpu_env
, tmp
, tmp2
); break;
4522 case 1: gen_helper_neon_qshl_u16(tmp
, cpu_env
, tmp
, tmp2
); break;
4523 case 2: gen_helper_neon_qshl_u32(tmp
, cpu_env
, tmp
, tmp2
); break;
4530 if (op
== 1 || op
== 3) {
4532 tmp2
= neon_load_reg(rd
, pass
);
4533 gen_neon_add(size
, tmp2
, tmp
);
4535 } else if (op
== 4 || (op
== 5 && u
)) {
4540 imm
= 0xff >> -shift
;
4542 imm
= (uint8_t)(0xff << shift
);
4548 imm
= 0xffff >> -shift
;
4550 imm
= (uint16_t)(0xffff << shift
);
4555 imm
= 0xffffffffu
>> -shift
;
4557 imm
= 0xffffffffu
<< shift
;
4562 tmp2
= neon_load_reg(rd
, pass
);
4563 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4564 tcg_gen_andi_i32(tmp2
, tmp2
, ~imm
);
4565 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4568 neon_store_reg(rd
, pass
, tmp
);
4571 } else if (op
< 10) {
4572 /* Shift by immediate and narrow:
4573 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4574 shift
= shift
- (1 << (size
+ 3));
4578 imm
= (uint16_t)shift
;
4580 tmp2
= tcg_const_i32(imm
);
4581 TCGV_UNUSED_I64(tmp64
);
4584 imm
= (uint32_t)shift
;
4585 tmp2
= tcg_const_i32(imm
);
4586 TCGV_UNUSED_I64(tmp64
);
4589 tmp64
= tcg_const_i64(shift
);
4596 for (pass
= 0; pass
< 2; pass
++) {
4598 neon_load_reg64(cpu_V0
, rm
+ pass
);
4601 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4603 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4606 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4608 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4611 tmp
= neon_load_reg(rm
+ pass
, 0);
4612 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4613 tmp3
= neon_load_reg(rm
+ pass
, 1);
4614 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4615 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4620 if (op
== 8 && !u
) {
4621 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4624 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4626 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4631 neon_store_reg(rd
, 0, tmp2
);
4632 neon_store_reg(rd
, 1, tmp
);
4635 } else if (op
== 10) {
4639 tmp
= neon_load_reg(rm
, 0);
4640 tmp2
= neon_load_reg(rm
, 1);
4641 for (pass
= 0; pass
< 2; pass
++) {
4645 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4648 /* The shift is less than the width of the source
4649 type, so we can just shift the whole register. */
4650 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4651 if (size
< 2 || !u
) {
4654 imm
= (0xffu
>> (8 - shift
));
4657 imm
= 0xffff >> (16 - shift
);
4659 imm64
= imm
| (((uint64_t)imm
) << 32);
4660 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4663 neon_store_reg64(cpu_V0
, rd
+ pass
);
4665 } else if (op
== 15 || op
== 16) {
4666 /* VCVT fixed-point. */
4667 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4668 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4671 gen_vfp_ulto(0, shift
);
4673 gen_vfp_slto(0, shift
);
4676 gen_vfp_toul(0, shift
);
4678 gen_vfp_tosl(0, shift
);
4680 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4685 } else { /* (insn & 0x00380080) == 0 */
4688 op
= (insn
>> 8) & 0xf;
4689 /* One register and immediate. */
4690 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4691 invert
= (insn
& (1 << 5)) != 0;
4709 imm
= (imm
<< 8) | (imm
<< 24);
4712 imm
= (imm
< 8) | 0xff;
4715 imm
= (imm
<< 16) | 0xffff;
4718 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4723 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4724 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4730 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4731 if (op
& 1 && op
< 12) {
4732 tmp
= neon_load_reg(rd
, pass
);
4734 /* The immediate value has already been inverted, so
4736 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4738 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4743 if (op
== 14 && invert
) {
4746 for (n
= 0; n
< 4; n
++) {
4747 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4748 val
|= 0xff << (n
* 8);
4750 tcg_gen_movi_i32(tmp
, val
);
4752 tcg_gen_movi_i32(tmp
, imm
);
4755 neon_store_reg(rd
, pass
, tmp
);
4758 } else { /* (insn & 0x00800010 == 0x00800000) */
4760 op
= (insn
>> 8) & 0xf;
4761 if ((insn
& (1 << 6)) == 0) {
4762 /* Three registers of different lengths. */
4766 /* prewiden, src1_wide, src2_wide */
4767 static const int neon_3reg_wide
[16][3] = {
4768 {1, 0, 0}, /* VADDL */
4769 {1, 1, 0}, /* VADDW */
4770 {1, 0, 0}, /* VSUBL */
4771 {1, 1, 0}, /* VSUBW */
4772 {0, 1, 1}, /* VADDHN */
4773 {0, 0, 0}, /* VABAL */
4774 {0, 1, 1}, /* VSUBHN */
4775 {0, 0, 0}, /* VABDL */
4776 {0, 0, 0}, /* VMLAL */
4777 {0, 0, 0}, /* VQDMLAL */
4778 {0, 0, 0}, /* VMLSL */
4779 {0, 0, 0}, /* VQDMLSL */
4780 {0, 0, 0}, /* Integer VMULL */
4781 {0, 0, 0}, /* VQDMULL */
4782 {0, 0, 0} /* Polynomial VMULL */
4785 prewiden
= neon_3reg_wide
[op
][0];
4786 src1_wide
= neon_3reg_wide
[op
][1];
4787 src2_wide
= neon_3reg_wide
[op
][2];
4789 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4792 /* Avoid overlapping operands. Wide source operands are
4793 always aligned so will never overlap with wide
4794 destinations in problematic ways. */
4795 if (rd
== rm
&& !src2_wide
) {
4796 tmp
= neon_load_reg(rm
, 1);
4797 neon_store_scratch(2, tmp
);
4798 } else if (rd
== rn
&& !src1_wide
) {
4799 tmp
= neon_load_reg(rn
, 1);
4800 neon_store_scratch(2, tmp
);
4803 for (pass
= 0; pass
< 2; pass
++) {
4805 neon_load_reg64(cpu_V0
, rn
+ pass
);
4808 if (pass
== 1 && rd
== rn
) {
4809 tmp
= neon_load_scratch(2);
4811 tmp
= neon_load_reg(rn
, pass
);
4814 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4818 neon_load_reg64(cpu_V1
, rm
+ pass
);
4821 if (pass
== 1 && rd
== rm
) {
4822 tmp2
= neon_load_scratch(2);
4824 tmp2
= neon_load_reg(rm
, pass
);
4827 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4831 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4832 gen_neon_addl(size
);
4834 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4835 gen_neon_subl(size
);
4837 case 5: case 7: /* VABAL, VABDL */
4838 switch ((size
<< 1) | u
) {
4840 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4843 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4846 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4849 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4852 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4855 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4862 case 8: case 9: case 10: case 11: case 12: case 13:
4863 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4864 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4868 case 14: /* Polynomial VMULL */
4869 cpu_abort(env
, "Polynomial VMULL not implemented");
4871 default: /* 15 is RESERVED. */
4874 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4876 if (op
== 10 || op
== 11) {
4877 gen_neon_negl(cpu_V0
, size
);
4881 neon_load_reg64(cpu_V1
, rd
+ pass
);
4885 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4886 gen_neon_addl(size
);
4888 case 9: case 11: /* VQDMLAL, VQDMLSL */
4889 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4890 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4893 case 13: /* VQDMULL */
4894 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4899 neon_store_reg64(cpu_V0
, rd
+ pass
);
4900 } else if (op
== 4 || op
== 6) {
4901 /* Narrowing operation. */
4906 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4909 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4912 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4913 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4920 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4923 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4926 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4927 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4928 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4936 neon_store_reg(rd
, 0, tmp3
);
4937 neon_store_reg(rd
, 1, tmp
);
4940 /* Write back the result. */
4941 neon_store_reg64(cpu_V0
, rd
+ pass
);
4945 /* Two registers and a scalar. */
4947 case 0: /* Integer VMLA scalar */
4948 case 1: /* Float VMLA scalar */
4949 case 4: /* Integer VMLS scalar */
4950 case 5: /* Floating point VMLS scalar */
4951 case 8: /* Integer VMUL scalar */
4952 case 9: /* Floating point VMUL scalar */
4953 case 12: /* VQDMULH scalar */
4954 case 13: /* VQRDMULH scalar */
4955 tmp
= neon_get_scalar(size
, rm
);
4956 neon_store_scratch(0, tmp
);
4957 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
4958 tmp
= neon_load_scratch(0);
4959 tmp2
= neon_load_reg(rn
, pass
);
4962 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4964 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4966 } else if (op
== 13) {
4968 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4970 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4972 } else if (op
& 1) {
4973 gen_helper_neon_mul_f32(tmp
, tmp
, tmp2
);
4976 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4977 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4978 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4985 tmp2
= neon_load_reg(rd
, pass
);
4988 gen_neon_add(size
, tmp
, tmp2
);
4991 gen_helper_neon_add_f32(tmp
, tmp
, tmp2
);
4994 gen_neon_rsb(size
, tmp
, tmp2
);
4997 gen_helper_neon_sub_f32(tmp
, tmp2
, tmp
);
5004 neon_store_reg(rd
, pass
, tmp
);
5007 case 2: /* VMLAL sclar */
5008 case 3: /* VQDMLAL scalar */
5009 case 6: /* VMLSL scalar */
5010 case 7: /* VQDMLSL scalar */
5011 case 10: /* VMULL scalar */
5012 case 11: /* VQDMULL scalar */
5013 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5016 tmp2
= neon_get_scalar(size
, rm
);
5017 tmp3
= neon_load_reg(rn
, 1);
5019 for (pass
= 0; pass
< 2; pass
++) {
5021 tmp
= neon_load_reg(rn
, 0);
5025 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5027 if (op
== 6 || op
== 7) {
5028 gen_neon_negl(cpu_V0
, size
);
5031 neon_load_reg64(cpu_V1
, rd
+ pass
);
5035 gen_neon_addl(size
);
5038 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5039 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5045 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5050 neon_store_reg64(cpu_V0
, rd
+ pass
);
5056 default: /* 14 and 15 are RESERVED */
5060 } else { /* size == 3 */
5063 imm
= (insn
>> 8) & 0xf;
5070 neon_load_reg64(cpu_V0
, rn
);
5072 neon_load_reg64(cpu_V1
, rn
+ 1);
5074 } else if (imm
== 8) {
5075 neon_load_reg64(cpu_V0
, rn
+ 1);
5077 neon_load_reg64(cpu_V1
, rm
);
5080 tmp64
= tcg_temp_new_i64();
5082 neon_load_reg64(cpu_V0
, rn
);
5083 neon_load_reg64(tmp64
, rn
+ 1);
5085 neon_load_reg64(cpu_V0
, rn
+ 1);
5086 neon_load_reg64(tmp64
, rm
);
5088 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5089 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5090 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5092 neon_load_reg64(cpu_V1
, rm
);
5094 neon_load_reg64(cpu_V1
, rm
+ 1);
5097 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5098 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5099 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5102 neon_load_reg64(cpu_V0
, rn
);
5103 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5104 neon_load_reg64(cpu_V1
, rm
);
5105 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5106 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5108 neon_store_reg64(cpu_V0
, rd
);
5110 neon_store_reg64(cpu_V1
, rd
+ 1);
5112 } else if ((insn
& (1 << 11)) == 0) {
5113 /* Two register misc. */
5114 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5115 size
= (insn
>> 18) & 3;
5117 case 0: /* VREV64 */
5120 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5121 tmp
= neon_load_reg(rm
, pass
* 2);
5122 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5124 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5125 case 1: gen_swap_half(tmp
); break;
5126 case 2: /* no-op */ break;
5129 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5131 neon_store_reg(rd
, pass
* 2, tmp2
);
5134 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5135 case 1: gen_swap_half(tmp2
); break;
5138 neon_store_reg(rd
, pass
* 2, tmp2
);
5142 case 4: case 5: /* VPADDL */
5143 case 12: case 13: /* VPADAL */
5146 for (pass
= 0; pass
< q
+ 1; pass
++) {
5147 tmp
= neon_load_reg(rm
, pass
* 2);
5148 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5149 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5150 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5152 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5153 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5154 case 2: tcg_gen_add_i64(CPU_V001
); break;
5159 neon_load_reg64(cpu_V1
, rd
+ pass
);
5160 gen_neon_addl(size
);
5162 neon_store_reg64(cpu_V0
, rd
+ pass
);
5167 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5168 tmp
= neon_load_reg(rm
, n
);
5169 tmp2
= neon_load_reg(rd
, n
+ 1);
5170 neon_store_reg(rm
, n
, tmp2
);
5171 neon_store_reg(rd
, n
+ 1, tmp
);
5179 Rd A3 A2 A1 A0 B2 B0 A2 A0
5180 Rm B3 B2 B1 B0 B3 B1 A3 A1
5184 gen_neon_unzip(rd
, q
, 0, size
);
5185 gen_neon_unzip(rm
, q
, 4, size
);
5187 static int unzip_order_q
[8] =
5188 {0, 2, 4, 6, 1, 3, 5, 7};
5189 for (n
= 0; n
< 8; n
++) {
5190 int reg
= (n
< 4) ? rd
: rm
;
5191 tmp
= neon_load_scratch(unzip_order_q
[n
]);
5192 neon_store_reg(reg
, n
% 4, tmp
);
5195 static int unzip_order
[4] =
5197 for (n
= 0; n
< 4; n
++) {
5198 int reg
= (n
< 2) ? rd
: rm
;
5199 tmp
= neon_load_scratch(unzip_order
[n
]);
5200 neon_store_reg(reg
, n
% 2, tmp
);
5206 Rd A3 A2 A1 A0 B1 A1 B0 A0
5207 Rm B3 B2 B1 B0 B3 A3 B2 A2
5211 count
= (q
? 4 : 2);
5212 for (n
= 0; n
< count
; n
++) {
5213 tmp
= neon_load_reg(rd
, n
);
5214 tmp2
= neon_load_reg(rd
, n
);
5216 case 0: gen_neon_zip_u8(tmp
, tmp2
); break;
5217 case 1: gen_neon_zip_u16(tmp
, tmp2
); break;
5218 case 2: /* no-op */; break;
5221 neon_store_scratch(n
* 2, tmp
);
5222 neon_store_scratch(n
* 2 + 1, tmp2
);
5224 for (n
= 0; n
< count
* 2; n
++) {
5225 int reg
= (n
< count
) ? rd
: rm
;
5226 tmp
= neon_load_scratch(n
);
5227 neon_store_reg(reg
, n
% count
, tmp
);
5230 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5234 for (pass
= 0; pass
< 2; pass
++) {
5235 neon_load_reg64(cpu_V0
, rm
+ pass
);
5237 if (op
== 36 && q
== 0) {
5238 gen_neon_narrow(size
, tmp
, cpu_V0
);
5240 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5242 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5247 neon_store_reg(rd
, 0, tmp2
);
5248 neon_store_reg(rd
, 1, tmp
);
5252 case 38: /* VSHLL */
5255 tmp
= neon_load_reg(rm
, 0);
5256 tmp2
= neon_load_reg(rm
, 1);
5257 for (pass
= 0; pass
< 2; pass
++) {
5260 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5261 neon_store_reg64(cpu_V0
, rd
+ pass
);
5266 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5267 if (op
== 30 || op
== 31 || op
>= 58) {
5268 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5269 neon_reg_offset(rm
, pass
));
5272 tmp
= neon_load_reg(rm
, pass
);
5275 case 1: /* VREV32 */
5277 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5278 case 1: gen_swap_half(tmp
); break;
5282 case 2: /* VREV16 */
5289 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5290 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5291 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5297 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5298 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5299 case 2: gen_helper_clz(tmp
, tmp
); break;
5306 gen_helper_neon_cnt_u8(tmp
, tmp
);
5311 tcg_gen_not_i32(tmp
, tmp
);
5313 case 14: /* VQABS */
5315 case 0: gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
); break;
5316 case 1: gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
); break;
5317 case 2: gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
); break;
5321 case 15: /* VQNEG */
5323 case 0: gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
); break;
5324 case 1: gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
); break;
5325 case 2: gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
); break;
5329 case 16: case 19: /* VCGT #0, VCLE #0 */
5330 tmp2
= tcg_const_i32(0);
5332 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5333 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5334 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5337 tcg_temp_free(tmp2
);
5339 tcg_gen_not_i32(tmp
, tmp
);
5341 case 17: case 20: /* VCGE #0, VCLT #0 */
5342 tmp2
= tcg_const_i32(0);
5344 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
5345 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
5346 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
5349 tcg_temp_free(tmp2
);
5351 tcg_gen_not_i32(tmp
, tmp
);
5353 case 18: /* VCEQ #0 */
5354 tmp2
= tcg_const_i32(0);
5356 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
5357 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
5358 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
5361 tcg_temp_free(tmp2
);
5365 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
5366 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
5367 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
5374 tmp2
= tcg_const_i32(0);
5375 gen_neon_rsb(size
, tmp
, tmp2
);
5376 tcg_temp_free(tmp2
);
5378 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5379 tmp2
= tcg_const_i32(0);
5380 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
);
5381 tcg_temp_free(tmp2
);
5383 tcg_gen_not_i32(tmp
, tmp
);
5385 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5386 tmp2
= tcg_const_i32(0);
5387 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
);
5388 tcg_temp_free(tmp2
);
5390 tcg_gen_not_i32(tmp
, tmp
);
5392 case 26: /* Float VCEQ #0 */
5393 tmp2
= tcg_const_i32(0);
5394 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
);
5395 tcg_temp_free(tmp2
);
5397 case 30: /* Float VABS */
5400 case 31: /* Float VNEG */
5404 tmp2
= neon_load_reg(rd
, pass
);
5405 neon_store_reg(rm
, pass
, tmp2
);
5408 tmp2
= neon_load_reg(rd
, pass
);
5410 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
5411 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
5415 neon_store_reg(rm
, pass
, tmp2
);
5417 case 56: /* Integer VRECPE */
5418 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
5420 case 57: /* Integer VRSQRTE */
5421 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
5423 case 58: /* Float VRECPE */
5424 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5426 case 59: /* Float VRSQRTE */
5427 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5429 case 60: /* VCVT.F32.S32 */
5432 case 61: /* VCVT.F32.U32 */
5435 case 62: /* VCVT.S32.F32 */
5438 case 63: /* VCVT.U32.F32 */
5442 /* Reserved: 21, 29, 39-56 */
5445 if (op
== 30 || op
== 31 || op
>= 58) {
5446 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5447 neon_reg_offset(rd
, pass
));
5449 neon_store_reg(rd
, pass
, tmp
);
5454 } else if ((insn
& (1 << 10)) == 0) {
5456 n
= ((insn
>> 5) & 0x18) + 8;
5457 if (insn
& (1 << 6)) {
5458 tmp
= neon_load_reg(rd
, 0);
5461 tcg_gen_movi_i32(tmp
, 0);
5463 tmp2
= neon_load_reg(rm
, 0);
5464 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5467 if (insn
& (1 << 6)) {
5468 tmp
= neon_load_reg(rd
, 1);
5471 tcg_gen_movi_i32(tmp
, 0);
5473 tmp3
= neon_load_reg(rm
, 1);
5474 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5476 neon_store_reg(rd
, 0, tmp2
);
5477 neon_store_reg(rd
, 1, tmp3
);
5479 } else if ((insn
& 0x380) == 0) {
5481 if (insn
& (1 << 19)) {
5482 tmp
= neon_load_reg(rm
, 1);
5484 tmp
= neon_load_reg(rm
, 0);
5486 if (insn
& (1 << 16)) {
5487 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
5488 } else if (insn
& (1 << 17)) {
5489 if ((insn
>> 18) & 1)
5490 gen_neon_dup_high16(tmp
);
5492 gen_neon_dup_low16(tmp
);
5494 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5496 tcg_gen_mov_i32(tmp2
, tmp
);
5497 neon_store_reg(rd
, pass
, tmp2
);
5508 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5510 int crn
= (insn
>> 16) & 0xf;
5511 int crm
= insn
& 0xf;
5512 int op1
= (insn
>> 21) & 7;
5513 int op2
= (insn
>> 5) & 7;
5514 int rt
= (insn
>> 12) & 0xf;
5517 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5518 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5522 tmp
= load_cpu_field(teecr
);
5523 store_reg(s
, rt
, tmp
);
5526 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5528 if (IS_USER(s
) && (env
->teecr
& 1))
5530 tmp
= load_cpu_field(teehbr
);
5531 store_reg(s
, rt
, tmp
);
5535 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5536 op1
, crn
, crm
, op2
);
5540 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5542 int crn
= (insn
>> 16) & 0xf;
5543 int crm
= insn
& 0xf;
5544 int op1
= (insn
>> 21) & 7;
5545 int op2
= (insn
>> 5) & 7;
5546 int rt
= (insn
>> 12) & 0xf;
5549 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5550 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5554 tmp
= load_reg(s
, rt
);
5555 gen_helper_set_teecr(cpu_env
, tmp
);
5559 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5561 if (IS_USER(s
) && (env
->teecr
& 1))
5563 tmp
= load_reg(s
, rt
);
5564 store_cpu_field(tmp
, teehbr
);
5568 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5569 op1
, crn
, crm
, op2
);
5573 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5577 cpnum
= (insn
>> 8) & 0xf;
5578 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5579 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5585 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5586 return disas_iwmmxt_insn(env
, s
, insn
);
5587 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5588 return disas_dsp_insn(env
, s
, insn
);
5593 return disas_vfp_insn (env
, s
, insn
);
5595 /* Coprocessors 7-15 are architecturally reserved by ARM.
5596 Unfortunately Intel decided to ignore this. */
5597 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5599 if (insn
& (1 << 20))
5600 return disas_cp14_read(env
, s
, insn
);
5602 return disas_cp14_write(env
, s
, insn
);
5604 return disas_cp15_insn (env
, s
, insn
);
5607 /* Unknown coprocessor. See if the board has hooked it. */
5608 return disas_cp_insn (env
, s
, insn
);
5613 /* Store a 64-bit value to a register pair. Clobbers val. */
5614 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5618 tcg_gen_trunc_i64_i32(tmp
, val
);
5619 store_reg(s
, rlow
, tmp
);
5621 tcg_gen_shri_i64(val
, val
, 32);
5622 tcg_gen_trunc_i64_i32(tmp
, val
);
5623 store_reg(s
, rhigh
, tmp
);
5626 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5627 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5632 /* Load value and extend to 64 bits. */
5633 tmp
= tcg_temp_new_i64();
5634 tmp2
= load_reg(s
, rlow
);
5635 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5637 tcg_gen_add_i64(val
, val
, tmp
);
5640 /* load and add a 64-bit value from a register pair. */
5641 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5647 /* Load 64-bit value rd:rn. */
5648 tmpl
= load_reg(s
, rlow
);
5649 tmph
= load_reg(s
, rhigh
);
5650 tmp
= tcg_temp_new_i64();
5651 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5654 tcg_gen_add_i64(val
, val
, tmp
);
5657 /* Set N and Z flags from a 64-bit value. */
5658 static void gen_logicq_cc(TCGv_i64 val
)
5660 TCGv tmp
= new_tmp();
5661 gen_helper_logicq_cc(tmp
, val
);
5666 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5668 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5675 insn
= ldl_code(s
->pc
);
5678 /* M variants do not implement ARM mode. */
5683 /* Unconditional instructions. */
5684 if (((insn
>> 25) & 7) == 1) {
5685 /* NEON Data processing. */
5686 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5689 if (disas_neon_data_insn(env
, s
, insn
))
5693 if ((insn
& 0x0f100000) == 0x04000000) {
5694 /* NEON load/store. */
5695 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5698 if (disas_neon_ls_insn(env
, s
, insn
))
5702 if ((insn
& 0x0d70f000) == 0x0550f000) {
5705 } else if ((insn
& 0x0ffffdff) == 0x01010000) {
5708 if (insn
& (1 << 9)) {
5709 /* BE8 mode not implemented. */
5713 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5714 switch ((insn
>> 4) & 0xf) {
5717 gen_helper_clrex(cpu_env
);
5723 /* We don't emulate caches so these are a no-op. */
5728 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5734 op1
= (insn
& 0x1f);
5735 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5736 addr
= load_reg(s
, 13);
5739 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5741 i
= (insn
>> 23) & 3;
5743 case 0: offset
= -4; break; /* DA */
5744 case 1: offset
= 0; break; /* IA */
5745 case 2: offset
= -8; break; /* DB */
5746 case 3: offset
= 4; break; /* IB */
5750 tcg_gen_addi_i32(addr
, addr
, offset
);
5751 tmp
= load_reg(s
, 14);
5752 gen_st32(tmp
, addr
, 0);
5753 tmp
= load_cpu_field(spsr
);
5754 tcg_gen_addi_i32(addr
, addr
, 4);
5755 gen_st32(tmp
, addr
, 0);
5756 if (insn
& (1 << 21)) {
5757 /* Base writeback. */
5759 case 0: offset
= -8; break;
5760 case 1: offset
= 4; break;
5761 case 2: offset
= -4; break;
5762 case 3: offset
= 0; break;
5766 tcg_gen_addi_i32(addr
, addr
, offset
);
5767 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5768 store_reg(s
, 13, addr
);
5770 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), addr
);
5776 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5782 rn
= (insn
>> 16) & 0xf;
5783 addr
= load_reg(s
, rn
);
5784 i
= (insn
>> 23) & 3;
5786 case 0: offset
= -4; break; /* DA */
5787 case 1: offset
= 0; break; /* IA */
5788 case 2: offset
= -8; break; /* DB */
5789 case 3: offset
= 4; break; /* IB */
5793 tcg_gen_addi_i32(addr
, addr
, offset
);
5794 /* Load PC into tmp and CPSR into tmp2. */
5795 tmp
= gen_ld32(addr
, 0);
5796 tcg_gen_addi_i32(addr
, addr
, 4);
5797 tmp2
= gen_ld32(addr
, 0);
5798 if (insn
& (1 << 21)) {
5799 /* Base writeback. */
5801 case 0: offset
= -8; break;
5802 case 1: offset
= 4; break;
5803 case 2: offset
= -4; break;
5804 case 3: offset
= 0; break;
5808 tcg_gen_addi_i32(addr
, addr
, offset
);
5809 store_reg(s
, rn
, addr
);
5813 gen_rfe(s
, tmp
, tmp2
);
5815 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5816 /* branch link and change to thumb (blx <offset>) */
5819 val
= (uint32_t)s
->pc
;
5821 tcg_gen_movi_i32(tmp
, val
);
5822 store_reg(s
, 14, tmp
);
5823 /* Sign-extend the 24-bit offset */
5824 offset
= (((int32_t)insn
) << 8) >> 8;
5825 /* offset * 4 + bit24 * 2 + (thumb bit) */
5826 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5827 /* pipeline offset */
5831 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5832 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5833 /* iWMMXt register transfer. */
5834 if (env
->cp15
.c15_cpar
& (1 << 1))
5835 if (!disas_iwmmxt_insn(env
, s
, insn
))
5838 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5839 /* Coprocessor double register transfer. */
5841 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5842 /* Additional coprocessor register transfer. */
5844 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5847 /* cps (privileged) */
5851 if (insn
& (1 << 19)) {
5852 if (insn
& (1 << 8))
5854 if (insn
& (1 << 7))
5856 if (insn
& (1 << 6))
5858 if (insn
& (1 << 18))
5861 if (insn
& (1 << 17)) {
5863 val
|= (insn
& 0x1f);
5866 gen_set_psr_im(s
, mask
, 0, val
);
5873 /* if not always execute, we generate a conditional jump to
5875 s
->condlabel
= gen_new_label();
5876 gen_test_cc(cond
^ 1, s
->condlabel
);
5879 if ((insn
& 0x0f900000) == 0x03000000) {
5880 if ((insn
& (1 << 21)) == 0) {
5882 rd
= (insn
>> 12) & 0xf;
5883 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5884 if ((insn
& (1 << 22)) == 0) {
5887 tcg_gen_movi_i32(tmp
, val
);
5890 tmp
= load_reg(s
, rd
);
5891 tcg_gen_ext16u_i32(tmp
, tmp
);
5892 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5894 store_reg(s
, rd
, tmp
);
5896 if (((insn
>> 12) & 0xf) != 0xf)
5898 if (((insn
>> 16) & 0xf) == 0) {
5899 gen_nop_hint(s
, insn
& 0xff);
5901 /* CPSR = immediate */
5903 shift
= ((insn
>> 8) & 0xf) * 2;
5905 val
= (val
>> shift
) | (val
<< (32 - shift
));
5906 i
= ((insn
& (1 << 22)) != 0);
5907 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
5911 } else if ((insn
& 0x0f900000) == 0x01000000
5912 && (insn
& 0x00000090) != 0x00000090) {
5913 /* miscellaneous instructions */
5914 op1
= (insn
>> 21) & 3;
5915 sh
= (insn
>> 4) & 0xf;
5918 case 0x0: /* move program status register */
5921 tmp
= load_reg(s
, rm
);
5922 i
= ((op1
& 2) != 0);
5923 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
5927 rd
= (insn
>> 12) & 0xf;
5931 tmp
= load_cpu_field(spsr
);
5934 gen_helper_cpsr_read(tmp
);
5936 store_reg(s
, rd
, tmp
);
5941 /* branch/exchange thumb (bx). */
5942 tmp
= load_reg(s
, rm
);
5944 } else if (op1
== 3) {
5946 rd
= (insn
>> 12) & 0xf;
5947 tmp
= load_reg(s
, rm
);
5948 gen_helper_clz(tmp
, tmp
);
5949 store_reg(s
, rd
, tmp
);
5957 /* Trivial implementation equivalent to bx. */
5958 tmp
= load_reg(s
, rm
);
5968 /* branch link/exchange thumb (blx) */
5969 tmp
= load_reg(s
, rm
);
5971 tcg_gen_movi_i32(tmp2
, s
->pc
);
5972 store_reg(s
, 14, tmp2
);
5975 case 0x5: /* saturating add/subtract */
5976 rd
= (insn
>> 12) & 0xf;
5977 rn
= (insn
>> 16) & 0xf;
5978 tmp
= load_reg(s
, rm
);
5979 tmp2
= load_reg(s
, rn
);
5981 gen_helper_double_saturate(tmp2
, tmp2
);
5983 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
5985 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
5987 store_reg(s
, rd
, tmp
);
5991 gen_set_condexec(s
);
5992 gen_set_pc_im(s
->pc
- 4);
5993 gen_exception(EXCP_BKPT
);
5994 s
->is_jmp
= DISAS_JUMP
;
5996 case 0x8: /* signed multiply */
6000 rs
= (insn
>> 8) & 0xf;
6001 rn
= (insn
>> 12) & 0xf;
6002 rd
= (insn
>> 16) & 0xf;
6004 /* (32 * 16) >> 16 */
6005 tmp
= load_reg(s
, rm
);
6006 tmp2
= load_reg(s
, rs
);
6008 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6011 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6012 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6014 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6015 if ((sh
& 2) == 0) {
6016 tmp2
= load_reg(s
, rn
);
6017 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6020 store_reg(s
, rd
, tmp
);
6023 tmp
= load_reg(s
, rm
);
6024 tmp2
= load_reg(s
, rs
);
6025 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6028 tmp64
= tcg_temp_new_i64();
6029 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6031 gen_addq(s
, tmp64
, rn
, rd
);
6032 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6035 tmp2
= load_reg(s
, rn
);
6036 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6039 store_reg(s
, rd
, tmp
);
6046 } else if (((insn
& 0x0e000000) == 0 &&
6047 (insn
& 0x00000090) != 0x90) ||
6048 ((insn
& 0x0e000000) == (1 << 25))) {
6049 int set_cc
, logic_cc
, shiftop
;
6051 op1
= (insn
>> 21) & 0xf;
6052 set_cc
= (insn
>> 20) & 1;
6053 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6055 /* data processing instruction */
6056 if (insn
& (1 << 25)) {
6057 /* immediate operand */
6059 shift
= ((insn
>> 8) & 0xf) * 2;
6061 val
= (val
>> shift
) | (val
<< (32 - shift
));
6064 tcg_gen_movi_i32(tmp2
, val
);
6065 if (logic_cc
&& shift
) {
6066 gen_set_CF_bit31(tmp2
);
6071 tmp2
= load_reg(s
, rm
);
6072 shiftop
= (insn
>> 5) & 3;
6073 if (!(insn
& (1 << 4))) {
6074 shift
= (insn
>> 7) & 0x1f;
6075 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6077 rs
= (insn
>> 8) & 0xf;
6078 tmp
= load_reg(s
, rs
);
6079 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6082 if (op1
!= 0x0f && op1
!= 0x0d) {
6083 rn
= (insn
>> 16) & 0xf;
6084 tmp
= load_reg(s
, rn
);
6088 rd
= (insn
>> 12) & 0xf;
6091 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6095 store_reg_bx(env
, s
, rd
, tmp
);
6098 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6102 store_reg_bx(env
, s
, rd
, tmp
);
6105 if (set_cc
&& rd
== 15) {
6106 /* SUBS r15, ... is used for exception return. */
6110 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6111 gen_exception_return(s
, tmp
);
6114 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6116 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6118 store_reg_bx(env
, s
, rd
, tmp
);
6123 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6125 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6127 store_reg_bx(env
, s
, rd
, tmp
);
6131 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6133 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6135 store_reg_bx(env
, s
, rd
, tmp
);
6139 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6141 gen_add_carry(tmp
, tmp
, tmp2
);
6143 store_reg_bx(env
, s
, rd
, tmp
);
6147 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6149 gen_sub_carry(tmp
, tmp
, tmp2
);
6151 store_reg_bx(env
, s
, rd
, tmp
);
6155 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6157 gen_sub_carry(tmp
, tmp2
, tmp
);
6159 store_reg_bx(env
, s
, rd
, tmp
);
6163 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6170 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6177 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6183 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6188 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6192 store_reg_bx(env
, s
, rd
, tmp
);
6195 if (logic_cc
&& rd
== 15) {
6196 /* MOVS r15, ... is used for exception return. */
6200 gen_exception_return(s
, tmp2
);
6205 store_reg_bx(env
, s
, rd
, tmp2
);
6209 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6213 store_reg_bx(env
, s
, rd
, tmp
);
6217 tcg_gen_not_i32(tmp2
, tmp2
);
6221 store_reg_bx(env
, s
, rd
, tmp2
);
6224 if (op1
!= 0x0f && op1
!= 0x0d) {
6228 /* other instructions */
6229 op1
= (insn
>> 24) & 0xf;
6233 /* multiplies, extra load/stores */
6234 sh
= (insn
>> 5) & 3;
6237 rd
= (insn
>> 16) & 0xf;
6238 rn
= (insn
>> 12) & 0xf;
6239 rs
= (insn
>> 8) & 0xf;
6241 op1
= (insn
>> 20) & 0xf;
6243 case 0: case 1: case 2: case 3: case 6:
6245 tmp
= load_reg(s
, rs
);
6246 tmp2
= load_reg(s
, rm
);
6247 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6249 if (insn
& (1 << 22)) {
6250 /* Subtract (mls) */
6252 tmp2
= load_reg(s
, rn
);
6253 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6255 } else if (insn
& (1 << 21)) {
6257 tmp2
= load_reg(s
, rn
);
6258 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6261 if (insn
& (1 << 20))
6263 store_reg(s
, rd
, tmp
);
6267 tmp
= load_reg(s
, rs
);
6268 tmp2
= load_reg(s
, rm
);
6269 if (insn
& (1 << 22))
6270 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6272 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6273 if (insn
& (1 << 21)) /* mult accumulate */
6274 gen_addq(s
, tmp64
, rn
, rd
);
6275 if (!(insn
& (1 << 23))) { /* double accumulate */
6277 gen_addq_lo(s
, tmp64
, rn
);
6278 gen_addq_lo(s
, tmp64
, rd
);
6280 if (insn
& (1 << 20))
6281 gen_logicq_cc(tmp64
);
6282 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6286 rn
= (insn
>> 16) & 0xf;
6287 rd
= (insn
>> 12) & 0xf;
6288 if (insn
& (1 << 23)) {
6289 /* load/store exclusive */
6290 op1
= (insn
>> 21) & 0x3;
6295 addr
= tcg_temp_local_new_i32();
6296 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
6297 if (insn
& (1 << 20)) {
6298 gen_helper_mark_exclusive(cpu_env
, addr
);
6301 tmp
= gen_ld32(addr
, IS_USER(s
));
6303 case 1: /* ldrexd */
6304 tmp
= gen_ld32(addr
, IS_USER(s
));
6305 store_reg(s
, rd
, tmp
);
6306 tcg_gen_addi_i32(addr
, addr
, 4);
6307 tmp
= gen_ld32(addr
, IS_USER(s
));
6310 case 2: /* ldrexb */
6311 tmp
= gen_ld8u(addr
, IS_USER(s
));
6313 case 3: /* ldrexh */
6314 tmp
= gen_ld16u(addr
, IS_USER(s
));
6319 store_reg(s
, rd
, tmp
);
6321 int label
= gen_new_label();
6323 tmp2
= tcg_temp_local_new_i32();
6324 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
6325 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
6326 tmp
= load_reg(s
,rm
);
6329 gen_st32(tmp
, addr
, IS_USER(s
));
6331 case 1: /* strexd */
6332 gen_st32(tmp
, addr
, IS_USER(s
));
6333 tcg_gen_addi_i32(addr
, addr
, 4);
6334 tmp
= load_reg(s
, rm
+ 1);
6335 gen_st32(tmp
, addr
, IS_USER(s
));
6337 case 2: /* strexb */
6338 gen_st8(tmp
, addr
, IS_USER(s
));
6340 case 3: /* strexh */
6341 gen_st16(tmp
, addr
, IS_USER(s
));
6346 gen_set_label(label
);
6347 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
6348 tcg_temp_free(tmp2
);
6350 tcg_temp_free(addr
);
6352 /* SWP instruction */
6355 /* ??? This is not really atomic. However we know
6356 we never have multiple CPUs running in parallel,
6357 so it is good enough. */
6358 addr
= load_reg(s
, rn
);
6359 tmp
= load_reg(s
, rm
);
6360 if (insn
& (1 << 22)) {
6361 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6362 gen_st8(tmp
, addr
, IS_USER(s
));
6364 tmp2
= gen_ld32(addr
, IS_USER(s
));
6365 gen_st32(tmp
, addr
, IS_USER(s
));
6368 store_reg(s
, rd
, tmp2
);
6374 /* Misc load/store */
6375 rn
= (insn
>> 16) & 0xf;
6376 rd
= (insn
>> 12) & 0xf;
6377 addr
= load_reg(s
, rn
);
6378 if (insn
& (1 << 24))
6379 gen_add_datah_offset(s
, insn
, 0, addr
);
6381 if (insn
& (1 << 20)) {
6385 tmp
= gen_ld16u(addr
, IS_USER(s
));
6388 tmp
= gen_ld8s(addr
, IS_USER(s
));
6392 tmp
= gen_ld16s(addr
, IS_USER(s
));
6396 } else if (sh
& 2) {
6400 tmp
= load_reg(s
, rd
);
6401 gen_st32(tmp
, addr
, IS_USER(s
));
6402 tcg_gen_addi_i32(addr
, addr
, 4);
6403 tmp
= load_reg(s
, rd
+ 1);
6404 gen_st32(tmp
, addr
, IS_USER(s
));
6408 tmp
= gen_ld32(addr
, IS_USER(s
));
6409 store_reg(s
, rd
, tmp
);
6410 tcg_gen_addi_i32(addr
, addr
, 4);
6411 tmp
= gen_ld32(addr
, IS_USER(s
));
6415 address_offset
= -4;
6418 tmp
= load_reg(s
, rd
);
6419 gen_st16(tmp
, addr
, IS_USER(s
));
6422 /* Perform base writeback before the loaded value to
6423 ensure correct behavior with overlapping index registers.
6424 ldrd with base writeback is is undefined if the
6425 destination and index registers overlap. */
6426 if (!(insn
& (1 << 24))) {
6427 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6428 store_reg(s
, rn
, addr
);
6429 } else if (insn
& (1 << 21)) {
6431 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6432 store_reg(s
, rn
, addr
);
6437 /* Complete the load. */
6438 store_reg(s
, rd
, tmp
);
6447 if (insn
& (1 << 4)) {
6449 /* Armv6 Media instructions. */
6451 rn
= (insn
>> 16) & 0xf;
6452 rd
= (insn
>> 12) & 0xf;
6453 rs
= (insn
>> 8) & 0xf;
6454 switch ((insn
>> 23) & 3) {
6455 case 0: /* Parallel add/subtract. */
6456 op1
= (insn
>> 20) & 7;
6457 tmp
= load_reg(s
, rn
);
6458 tmp2
= load_reg(s
, rm
);
6459 sh
= (insn
>> 5) & 7;
6460 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6462 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6464 store_reg(s
, rd
, tmp
);
6467 if ((insn
& 0x00700020) == 0) {
6468 /* Halfword pack. */
6469 tmp
= load_reg(s
, rn
);
6470 tmp2
= load_reg(s
, rm
);
6471 shift
= (insn
>> 7) & 0x1f;
6472 if (insn
& (1 << 6)) {
6476 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6477 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6478 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6482 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6483 tcg_gen_ext16u_i32(tmp
, tmp
);
6484 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6486 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6488 store_reg(s
, rd
, tmp
);
6489 } else if ((insn
& 0x00200020) == 0x00200000) {
6491 tmp
= load_reg(s
, rm
);
6492 shift
= (insn
>> 7) & 0x1f;
6493 if (insn
& (1 << 6)) {
6496 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6498 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6500 sh
= (insn
>> 16) & 0x1f;
6502 if (insn
& (1 << 22))
6503 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6505 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6507 store_reg(s
, rd
, tmp
);
6508 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6510 tmp
= load_reg(s
, rm
);
6511 sh
= (insn
>> 16) & 0x1f;
6513 if (insn
& (1 << 22))
6514 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6516 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6518 store_reg(s
, rd
, tmp
);
6519 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6521 tmp
= load_reg(s
, rn
);
6522 tmp2
= load_reg(s
, rm
);
6524 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6525 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6528 store_reg(s
, rd
, tmp
);
6529 } else if ((insn
& 0x000003e0) == 0x00000060) {
6530 tmp
= load_reg(s
, rm
);
6531 shift
= (insn
>> 10) & 3;
6532 /* ??? In many cases it's not neccessary to do a
6533 rotate, a shift is sufficient. */
6535 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
6536 op1
= (insn
>> 20) & 7;
6538 case 0: gen_sxtb16(tmp
); break;
6539 case 2: gen_sxtb(tmp
); break;
6540 case 3: gen_sxth(tmp
); break;
6541 case 4: gen_uxtb16(tmp
); break;
6542 case 6: gen_uxtb(tmp
); break;
6543 case 7: gen_uxth(tmp
); break;
6544 default: goto illegal_op
;
6547 tmp2
= load_reg(s
, rn
);
6548 if ((op1
& 3) == 0) {
6549 gen_add16(tmp
, tmp2
);
6551 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6555 store_reg(s
, rd
, tmp
);
6556 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6558 tmp
= load_reg(s
, rm
);
6559 if (insn
& (1 << 22)) {
6560 if (insn
& (1 << 7)) {
6564 gen_helper_rbit(tmp
, tmp
);
6567 if (insn
& (1 << 7))
6570 tcg_gen_bswap32_i32(tmp
, tmp
);
6572 store_reg(s
, rd
, tmp
);
6577 case 2: /* Multiplies (Type 3). */
6578 tmp
= load_reg(s
, rm
);
6579 tmp2
= load_reg(s
, rs
);
6580 if (insn
& (1 << 20)) {
6581 /* Signed multiply most significant [accumulate]. */
6582 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6583 if (insn
& (1 << 5))
6584 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6585 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6587 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6589 tmp2
= load_reg(s
, rd
);
6590 if (insn
& (1 << 6)) {
6591 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6593 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6597 store_reg(s
, rn
, tmp
);
6599 if (insn
& (1 << 5))
6600 gen_swap_half(tmp2
);
6601 gen_smul_dual(tmp
, tmp2
);
6602 /* This addition cannot overflow. */
6603 if (insn
& (1 << 6)) {
6604 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6606 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6609 if (insn
& (1 << 22)) {
6610 /* smlald, smlsld */
6611 tmp64
= tcg_temp_new_i64();
6612 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6614 gen_addq(s
, tmp64
, rd
, rn
);
6615 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6617 /* smuad, smusd, smlad, smlsd */
6620 tmp2
= load_reg(s
, rd
);
6621 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6624 store_reg(s
, rn
, tmp
);
6629 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6631 case 0: /* Unsigned sum of absolute differences. */
6633 tmp
= load_reg(s
, rm
);
6634 tmp2
= load_reg(s
, rs
);
6635 gen_helper_usad8(tmp
, tmp
, tmp2
);
6638 tmp2
= load_reg(s
, rd
);
6639 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6642 store_reg(s
, rn
, tmp
);
6644 case 0x20: case 0x24: case 0x28: case 0x2c:
6645 /* Bitfield insert/clear. */
6647 shift
= (insn
>> 7) & 0x1f;
6648 i
= (insn
>> 16) & 0x1f;
6652 tcg_gen_movi_i32(tmp
, 0);
6654 tmp
= load_reg(s
, rm
);
6657 tmp2
= load_reg(s
, rd
);
6658 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6661 store_reg(s
, rd
, tmp
);
6663 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6664 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6666 tmp
= load_reg(s
, rm
);
6667 shift
= (insn
>> 7) & 0x1f;
6668 i
= ((insn
>> 16) & 0x1f) + 1;
6673 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6675 gen_sbfx(tmp
, shift
, i
);
6678 store_reg(s
, rd
, tmp
);
6688 /* Check for undefined extension instructions
6689 * per the ARM Bible IE:
6690 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6692 sh
= (0xf << 20) | (0xf << 4);
6693 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6697 /* load/store byte/word */
6698 rn
= (insn
>> 16) & 0xf;
6699 rd
= (insn
>> 12) & 0xf;
6700 tmp2
= load_reg(s
, rn
);
6701 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6702 if (insn
& (1 << 24))
6703 gen_add_data_offset(s
, insn
, tmp2
);
6704 if (insn
& (1 << 20)) {
6706 if (insn
& (1 << 22)) {
6707 tmp
= gen_ld8u(tmp2
, i
);
6709 tmp
= gen_ld32(tmp2
, i
);
6713 tmp
= load_reg(s
, rd
);
6714 if (insn
& (1 << 22))
6715 gen_st8(tmp
, tmp2
, i
);
6717 gen_st32(tmp
, tmp2
, i
);
6719 if (!(insn
& (1 << 24))) {
6720 gen_add_data_offset(s
, insn
, tmp2
);
6721 store_reg(s
, rn
, tmp2
);
6722 } else if (insn
& (1 << 21)) {
6723 store_reg(s
, rn
, tmp2
);
6727 if (insn
& (1 << 20)) {
6728 /* Complete the load. */
6729 if (rd
== 15 && ENABLE_ARCH_5
)
6732 store_reg(s
, rd
, tmp
);
6738 int j
, n
, user
, loaded_base
;
6741 /* load/store multiple words */
6742 /* XXX: store correct base if write back */
6744 if (insn
& (1 << 22)) {
6746 goto illegal_op
; /* only usable in supervisor mode */
6748 if ((insn
& (1 << 15)) == 0)
6751 rn
= (insn
>> 16) & 0xf;
6752 addr
= load_reg(s
, rn
);
6754 /* compute total size */
6756 TCGV_UNUSED(loaded_var
);
6759 if (insn
& (1 << i
))
6762 /* XXX: test invalid n == 0 case ? */
6763 if (insn
& (1 << 23)) {
6764 if (insn
& (1 << 24)) {
6766 tcg_gen_addi_i32(addr
, addr
, 4);
6768 /* post increment */
6771 if (insn
& (1 << 24)) {
6773 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6775 /* post decrement */
6777 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6781 if (insn
& (1 << 21)) {
6783 if (insn
& (1 << 23)) {
6784 if (insn
& (1 << 24)) {
6787 /* post increment */
6791 if (insn
& (1 << 24)) {
6794 crement
= -((n
- 1) * 4);
6797 /* post decrement */
6801 if (arm_feature(env
, ARM_FEATURE_ABORT_BU
)) {
6802 /* base-updated abort model: update base register
6803 before an abort can happen */
6804 crement
+= (n
- 1) * 4;
6806 tcg_gen_addi_i32(tmp
, addr
, crement
);
6807 store_reg(s
, rn
, tmp
);
6814 if (insn
& (1 << i
)) {
6815 if (insn
& (1 << 20)) {
6817 tmp
= gen_ld32(addr
, IS_USER(s
));
6819 if (ENABLE_ARCH_5
) {
6822 store_reg(s
, i
, tmp
);
6825 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6827 } else if (i
== rn
) {
6831 store_reg(s
, i
, tmp
);
6836 /* special case: r15 = PC + 8 */
6837 val
= (long)s
->pc
+ 4;
6839 tcg_gen_movi_i32(tmp
, val
);
6842 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6844 tmp
= load_reg(s
, i
);
6846 gen_st32(tmp
, addr
, IS_USER(s
));
6849 /* no need to add after the last transfer */
6851 tcg_gen_addi_i32(addr
, addr
, 4);
6854 if (!arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << 21))) {
6855 tcg_gen_addi_i32(addr
, addr
, crement
);
6856 store_reg(s
, rn
, addr
);
6861 store_reg(s
, rn
, loaded_var
);
6863 if ((insn
& (1 << 22)) && !user
) {
6864 /* Restore CPSR from SPSR. */
6865 tmp
= load_cpu_field(spsr
);
6866 gen_set_cpsr(tmp
, 0xffffffff);
6868 s
->is_jmp
= DISAS_UPDATE
;
6877 /* branch (and link) */
6878 val
= (int32_t)s
->pc
;
6879 if (insn
& (1 << 24)) {
6881 tcg_gen_movi_i32(tmp
, val
);
6882 store_reg(s
, 14, tmp
);
6884 offset
= (((int32_t)insn
<< 8) >> 8);
6885 val
+= (offset
<< 2) + 4;
6893 if (disas_coproc_insn(env
, s
, insn
))
6898 gen_set_pc_im(s
->pc
);
6899 s
->is_jmp
= DISAS_SWI
;
6903 gen_set_condexec(s
);
6904 gen_set_pc_im(s
->pc
- 4);
6905 gen_exception(EXCP_UDEF
);
6906 s
->is_jmp
= DISAS_JUMP
;
6912 /* Return true if this is a Thumb-2 logical op. */
6914 thumb2_logic_op(int op
)
6919 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6920 then set condition code flags based on the result of the operation.
6921 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6922 to the high bit of T1.
6923 Returns zero if the opcode is valid. */
6926 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
, TCGv t0
, TCGv t1
)
6933 tcg_gen_and_i32(t0
, t0
, t1
);
6937 tcg_gen_bic_i32(t0
, t0
, t1
);
6941 tcg_gen_or_i32(t0
, t0
, t1
);
6945 tcg_gen_not_i32(t1
, t1
);
6946 tcg_gen_or_i32(t0
, t0
, t1
);
6950 tcg_gen_xor_i32(t0
, t0
, t1
);
6955 gen_helper_add_cc(t0
, t0
, t1
);
6957 tcg_gen_add_i32(t0
, t0
, t1
);
6961 gen_helper_adc_cc(t0
, t0
, t1
);
6963 gen_add_carry(t0
, t0
, t1
);
6967 gen_helper_sbc_cc(t0
, t0
, t1
);
6969 gen_sub_carry(t0
, t0
, t1
);
6973 gen_helper_sub_cc(t0
, t0
, t1
);
6975 tcg_gen_sub_i32(t0
, t0
, t1
);
6979 gen_helper_sub_cc(t0
, t1
, t0
);
6981 tcg_gen_sub_i32(t0
, t1
, t0
);
6983 default: /* 5, 6, 7, 9, 12, 15. */
6989 gen_set_CF_bit31(t1
);
6994 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6996 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6998 uint32_t insn
, imm
, shift
, offset
;
6999 uint32_t rd
, rn
, rm
, rs
;
7010 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7011 || arm_feature (env
, ARM_FEATURE_M
))) {
7012 /* Thumb-1 cores may need to treat bl and blx as a pair of
7013 16-bit instructions to get correct prefetch abort behavior. */
7015 if ((insn
& (1 << 12)) == 0) {
7017 /* Second half of blx. */
7018 offset
= ((insn
& 0x7ff) << 1);
7019 tmp
= load_reg(s
, 14);
7020 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7021 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7024 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7025 store_reg(s
, 14, tmp2
);
7029 if (insn
& (1 << 11)) {
7030 /* Second half of bl. */
7031 offset
= ((insn
& 0x7ff) << 1) | 1;
7032 tmp
= load_reg(s
, 14);
7033 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7036 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7037 store_reg(s
, 14, tmp2
);
7041 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7042 /* Instruction spans a page boundary. Implement it as two
7043 16-bit instructions in case the second half causes an
7045 offset
= ((int32_t)insn
<< 21) >> 9;
7046 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
7049 /* Fall through to 32-bit decode. */
7052 insn
= lduw_code(s
->pc
);
7054 insn
|= (uint32_t)insn_hw1
<< 16;
7056 if ((insn
& 0xf800e800) != 0xf000e800) {
7060 rn
= (insn
>> 16) & 0xf;
7061 rs
= (insn
>> 12) & 0xf;
7062 rd
= (insn
>> 8) & 0xf;
7064 switch ((insn
>> 25) & 0xf) {
7065 case 0: case 1: case 2: case 3:
7066 /* 16-bit instructions. Should never happen. */
7069 if (insn
& (1 << 22)) {
7070 /* Other load/store, table branch. */
7071 if (insn
& 0x01200000) {
7072 /* Load/store doubleword. */
7076 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7078 addr
= load_reg(s
, rn
);
7080 offset
= (insn
& 0xff) * 4;
7081 if ((insn
& (1 << 23)) == 0)
7083 if (insn
& (1 << 24)) {
7084 tcg_gen_addi_i32(addr
, addr
, offset
);
7087 if (insn
& (1 << 20)) {
7089 tmp
= gen_ld32(addr
, IS_USER(s
));
7090 store_reg(s
, rs
, tmp
);
7091 tcg_gen_addi_i32(addr
, addr
, 4);
7092 tmp
= gen_ld32(addr
, IS_USER(s
));
7093 store_reg(s
, rd
, tmp
);
7096 tmp
= load_reg(s
, rs
);
7097 gen_st32(tmp
, addr
, IS_USER(s
));
7098 tcg_gen_addi_i32(addr
, addr
, 4);
7099 tmp
= load_reg(s
, rd
);
7100 gen_st32(tmp
, addr
, IS_USER(s
));
7102 if (insn
& (1 << 21)) {
7103 /* Base writeback. */
7106 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7107 store_reg(s
, rn
, addr
);
7111 } else if ((insn
& (1 << 23)) == 0) {
7112 /* Load/store exclusive word. */
7113 addr
= tcg_temp_local_new();
7114 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7115 if (insn
& (1 << 20)) {
7116 gen_helper_mark_exclusive(cpu_env
, addr
);
7117 tmp
= gen_ld32(addr
, IS_USER(s
));
7118 store_reg(s
, rd
, tmp
);
7120 int label
= gen_new_label();
7121 tmp2
= tcg_temp_local_new();
7122 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7123 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7124 tmp
= load_reg(s
, rs
);
7125 gen_st32(tmp
, addr
, IS_USER(s
));
7126 gen_set_label(label
);
7127 tcg_gen_mov_i32(cpu_R
[rd
], tmp2
);
7128 tcg_temp_free(tmp2
);
7130 tcg_temp_free(addr
);
7131 } else if ((insn
& (1 << 6)) == 0) {
7135 tcg_gen_movi_i32(addr
, s
->pc
);
7137 addr
= load_reg(s
, rn
);
7139 tmp
= load_reg(s
, rm
);
7140 tcg_gen_add_i32(addr
, addr
, tmp
);
7141 if (insn
& (1 << 4)) {
7143 tcg_gen_add_i32(addr
, addr
, tmp
);
7145 tmp
= gen_ld16u(addr
, IS_USER(s
));
7148 tmp
= gen_ld8u(addr
, IS_USER(s
));
7151 tcg_gen_shli_i32(tmp
, tmp
, 1);
7152 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7153 store_reg(s
, 15, tmp
);
7155 /* Load/store exclusive byte/halfword/doubleword. */
7156 /* ??? These are not really atomic. However we know
7157 we never have multiple CPUs running in parallel,
7158 so it is good enough. */
7159 op
= (insn
>> 4) & 0x3;
7160 addr
= tcg_temp_local_new();
7161 tcg_gen_mov_i32(addr
, cpu_R
[rn
]);
7162 if (insn
& (1 << 20)) {
7163 gen_helper_mark_exclusive(cpu_env
, addr
);
7166 tmp
= gen_ld8u(addr
, IS_USER(s
));
7169 tmp
= gen_ld16u(addr
, IS_USER(s
));
7172 tmp
= gen_ld32(addr
, IS_USER(s
));
7173 tcg_gen_addi_i32(addr
, addr
, 4);
7174 tmp2
= gen_ld32(addr
, IS_USER(s
));
7175 store_reg(s
, rd
, tmp2
);
7180 store_reg(s
, rs
, tmp
);
7182 int label
= gen_new_label();
7183 tmp2
= tcg_temp_local_new();
7184 gen_helper_test_exclusive(tmp2
, cpu_env
, addr
);
7185 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp2
, 0, label
);
7186 tmp
= load_reg(s
, rs
);
7189 gen_st8(tmp
, addr
, IS_USER(s
));
7192 gen_st16(tmp
, addr
, IS_USER(s
));
7195 gen_st32(tmp
, addr
, IS_USER(s
));
7196 tcg_gen_addi_i32(addr
, addr
, 4);
7197 tmp
= load_reg(s
, rd
);
7198 gen_st32(tmp
, addr
, IS_USER(s
));
7203 gen_set_label(label
);
7204 tcg_gen_mov_i32(cpu_R
[rm
], tmp2
);
7205 tcg_temp_free(tmp2
);
7207 tcg_temp_free(addr
);
7210 /* Load/store multiple, RFE, SRS. */
7211 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7212 /* Not available in user mode. */
7215 if (insn
& (1 << 20)) {
7217 addr
= load_reg(s
, rn
);
7218 if ((insn
& (1 << 24)) == 0)
7219 tcg_gen_addi_i32(addr
, addr
, -8);
7220 /* Load PC into tmp and CPSR into tmp2. */
7221 tmp
= gen_ld32(addr
, 0);
7222 tcg_gen_addi_i32(addr
, addr
, 4);
7223 tmp2
= gen_ld32(addr
, 0);
7224 if (insn
& (1 << 21)) {
7225 /* Base writeback. */
7226 if (insn
& (1 << 24)) {
7227 tcg_gen_addi_i32(addr
, addr
, 4);
7229 tcg_gen_addi_i32(addr
, addr
, -4);
7231 store_reg(s
, rn
, addr
);
7235 gen_rfe(s
, tmp
, tmp2
);
7239 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7240 addr
= load_reg(s
, 13);
7243 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7245 if ((insn
& (1 << 24)) == 0) {
7246 tcg_gen_addi_i32(addr
, addr
, -8);
7248 tmp
= load_reg(s
, 14);
7249 gen_st32(tmp
, addr
, 0);
7250 tcg_gen_addi_i32(addr
, addr
, 4);
7252 gen_helper_cpsr_read(tmp
);
7253 gen_st32(tmp
, addr
, 0);
7254 if (insn
& (1 << 21)) {
7255 if ((insn
& (1 << 24)) == 0) {
7256 tcg_gen_addi_i32(addr
, addr
, -4);
7258 tcg_gen_addi_i32(addr
, addr
, 4);
7260 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7261 store_reg(s
, 13, addr
);
7263 gen_helper_set_r13_banked(cpu_env
,
7264 tcg_const_i32(op
), addr
);
7272 /* Load/store multiple. */
7273 addr
= load_reg(s
, rn
);
7275 for (i
= 0; i
< 16; i
++) {
7276 if (insn
& (1 << i
))
7279 if (insn
& (1 << 24)) {
7280 tcg_gen_addi_i32(addr
, addr
, -offset
);
7283 for (i
= 0; i
< 16; i
++) {
7284 if ((insn
& (1 << i
)) == 0)
7286 if (insn
& (1 << 20)) {
7288 tmp
= gen_ld32(addr
, IS_USER(s
));
7289 if (i
== 15 && ENABLE_ARCH_5
) {
7292 store_reg(s
, i
, tmp
);
7296 tmp
= load_reg(s
, i
);
7297 gen_st32(tmp
, addr
, IS_USER(s
));
7299 tcg_gen_addi_i32(addr
, addr
, 4);
7301 if (insn
& (1 << 21)) {
7302 /* Base register writeback. */
7303 if (insn
& (1 << 24)) {
7304 tcg_gen_addi_i32(addr
, addr
, -offset
);
7306 /* Fault if writeback register is in register list. */
7307 if (insn
& (1 << rn
))
7309 store_reg(s
, rn
, addr
);
7316 case 5: /* Data processing register constant shift. */
7319 tcg_gen_movi_i32(tmp
, 0);
7321 tmp
= load_reg(s
, rn
);
7323 tmp2
= load_reg(s
, rm
);
7324 op
= (insn
>> 21) & 0xf;
7325 shiftop
= (insn
>> 4) & 3;
7326 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7327 conds
= (insn
& (1 << 20)) != 0;
7328 logic_cc
= (conds
&& thumb2_logic_op(op
));
7329 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7330 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
7334 store_reg(s
, rd
, tmp
);
7339 case 13: /* Misc data processing. */
7340 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7341 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7344 case 0: /* Register controlled shift. */
7345 tmp
= load_reg(s
, rn
);
7346 tmp2
= load_reg(s
, rm
);
7347 if ((insn
& 0x70) != 0)
7349 op
= (insn
>> 21) & 3;
7350 logic_cc
= (insn
& (1 << 20)) != 0;
7351 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7354 store_reg_bx(env
, s
, rd
, tmp
);
7356 case 1: /* Sign/zero extend. */
7357 tmp
= load_reg(s
, rm
);
7358 shift
= (insn
>> 4) & 3;
7359 /* ??? In many cases it's not neccessary to do a
7360 rotate, a shift is sufficient. */
7362 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7363 op
= (insn
>> 20) & 7;
7365 case 0: gen_sxth(tmp
); break;
7366 case 1: gen_uxth(tmp
); break;
7367 case 2: gen_sxtb16(tmp
); break;
7368 case 3: gen_uxtb16(tmp
); break;
7369 case 4: gen_sxtb(tmp
); break;
7370 case 5: gen_uxtb(tmp
); break;
7371 default: goto illegal_op
;
7374 tmp2
= load_reg(s
, rn
);
7375 if ((op
>> 1) == 1) {
7376 gen_add16(tmp
, tmp2
);
7378 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7382 store_reg(s
, rd
, tmp
);
7384 case 2: /* SIMD add/subtract. */
7385 op
= (insn
>> 20) & 7;
7386 shift
= (insn
>> 4) & 7;
7387 if ((op
& 3) == 3 || (shift
& 3) == 3)
7389 tmp
= load_reg(s
, rn
);
7390 tmp2
= load_reg(s
, rm
);
7391 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7393 store_reg(s
, rd
, tmp
);
7395 case 3: /* Other data processing. */
7396 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7398 /* Saturating add/subtract. */
7399 tmp
= load_reg(s
, rn
);
7400 tmp2
= load_reg(s
, rm
);
7402 gen_helper_double_saturate(tmp
, tmp
);
7404 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7406 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7409 tmp
= load_reg(s
, rn
);
7411 case 0x0a: /* rbit */
7412 gen_helper_rbit(tmp
, tmp
);
7414 case 0x08: /* rev */
7415 tcg_gen_bswap32_i32(tmp
, tmp
);
7417 case 0x09: /* rev16 */
7420 case 0x0b: /* revsh */
7423 case 0x10: /* sel */
7424 tmp2
= load_reg(s
, rm
);
7426 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7427 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7431 case 0x18: /* clz */
7432 gen_helper_clz(tmp
, tmp
);
7438 store_reg(s
, rd
, tmp
);
7440 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7441 op
= (insn
>> 4) & 0xf;
7442 tmp
= load_reg(s
, rn
);
7443 tmp2
= load_reg(s
, rm
);
7444 switch ((insn
>> 20) & 7) {
7445 case 0: /* 32 x 32 -> 32 */
7446 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7449 tmp2
= load_reg(s
, rs
);
7451 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7453 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7457 case 1: /* 16 x 16 -> 32 */
7458 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7461 tmp2
= load_reg(s
, rs
);
7462 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7466 case 2: /* Dual multiply add. */
7467 case 4: /* Dual multiply subtract. */
7469 gen_swap_half(tmp2
);
7470 gen_smul_dual(tmp
, tmp2
);
7471 /* This addition cannot overflow. */
7472 if (insn
& (1 << 22)) {
7473 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7475 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7480 tmp2
= load_reg(s
, rs
);
7481 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7485 case 3: /* 32 * 16 -> 32msb */
7487 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7490 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7491 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7493 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7496 tmp2
= load_reg(s
, rs
);
7497 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7501 case 5: case 6: /* 32 * 32 -> 32msb */
7502 gen_imull(tmp
, tmp2
);
7503 if (insn
& (1 << 5)) {
7504 gen_roundqd(tmp
, tmp2
);
7511 tmp2
= load_reg(s
, rs
);
7512 if (insn
& (1 << 21)) {
7513 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7515 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7520 case 7: /* Unsigned sum of absolute differences. */
7521 gen_helper_usad8(tmp
, tmp
, tmp2
);
7524 tmp2
= load_reg(s
, rs
);
7525 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7530 store_reg(s
, rd
, tmp
);
7532 case 6: case 7: /* 64-bit multiply, Divide. */
7533 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7534 tmp
= load_reg(s
, rn
);
7535 tmp2
= load_reg(s
, rm
);
7536 if ((op
& 0x50) == 0x10) {
7538 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7541 gen_helper_udiv(tmp
, tmp
, tmp2
);
7543 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7545 store_reg(s
, rd
, tmp
);
7546 } else if ((op
& 0xe) == 0xc) {
7547 /* Dual multiply accumulate long. */
7549 gen_swap_half(tmp2
);
7550 gen_smul_dual(tmp
, tmp2
);
7552 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7554 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7558 tmp64
= tcg_temp_new_i64();
7559 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7561 gen_addq(s
, tmp64
, rs
, rd
);
7562 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7565 /* Unsigned 64-bit multiply */
7566 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7570 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7572 tmp64
= tcg_temp_new_i64();
7573 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7576 /* Signed 64-bit multiply */
7577 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7582 gen_addq_lo(s
, tmp64
, rs
);
7583 gen_addq_lo(s
, tmp64
, rd
);
7584 } else if (op
& 0x40) {
7585 /* 64-bit accumulate. */
7586 gen_addq(s
, tmp64
, rs
, rd
);
7588 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7593 case 6: case 7: case 14: case 15:
7595 if (((insn
>> 24) & 3) == 3) {
7596 /* Translate into the equivalent ARM encoding. */
7597 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7598 if (disas_neon_data_insn(env
, s
, insn
))
7601 if (insn
& (1 << 28))
7603 if (disas_coproc_insn (env
, s
, insn
))
7607 case 8: case 9: case 10: case 11:
7608 if (insn
& (1 << 15)) {
7609 /* Branches, misc control. */
7610 if (insn
& 0x5000) {
7611 /* Unconditional branch. */
7612 /* signextend(hw1[10:0]) -> offset[:12]. */
7613 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7614 /* hw1[10:0] -> offset[11:1]. */
7615 offset
|= (insn
& 0x7ff) << 1;
7616 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7617 offset[24:22] already have the same value because of the
7618 sign extension above. */
7619 offset
^= ((~insn
) & (1 << 13)) << 10;
7620 offset
^= ((~insn
) & (1 << 11)) << 11;
7622 if (insn
& (1 << 14)) {
7623 /* Branch and link. */
7624 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
7628 if (insn
& (1 << 12)) {
7634 offset
&= ~(uint32_t)2;
7635 gen_bx_im(s
, offset
);
7637 } else if (((insn
>> 23) & 7) == 7) {
7639 if (insn
& (1 << 13))
7642 if (insn
& (1 << 26)) {
7643 /* Secure monitor call (v6Z) */
7644 goto illegal_op
; /* not implemented. */
7646 op
= (insn
>> 20) & 7;
7648 case 0: /* msr cpsr. */
7650 tmp
= load_reg(s
, rn
);
7651 addr
= tcg_const_i32(insn
& 0xff);
7652 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7657 case 1: /* msr spsr. */
7660 tmp
= load_reg(s
, rn
);
7662 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7666 case 2: /* cps, nop-hint. */
7667 if (((insn
>> 8) & 7) == 0) {
7668 gen_nop_hint(s
, insn
& 0xff);
7670 /* Implemented as NOP in user mode. */
7675 if (insn
& (1 << 10)) {
7676 if (insn
& (1 << 7))
7678 if (insn
& (1 << 6))
7680 if (insn
& (1 << 5))
7682 if (insn
& (1 << 9))
7683 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7685 if (insn
& (1 << 8)) {
7687 imm
|= (insn
& 0x1f);
7690 gen_set_psr_im(s
, offset
, 0, imm
);
7693 case 3: /* Special control operations. */
7694 op
= (insn
>> 4) & 0xf;
7697 gen_helper_clrex(cpu_env
);
7702 /* These execute as NOPs. */
7710 /* Trivial implementation equivalent to bx. */
7711 tmp
= load_reg(s
, rn
);
7714 case 5: /* Exception return. */
7715 /* Unpredictable in user mode. */
7717 case 6: /* mrs cpsr. */
7720 addr
= tcg_const_i32(insn
& 0xff);
7721 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7723 gen_helper_cpsr_read(tmp
);
7725 store_reg(s
, rd
, tmp
);
7727 case 7: /* mrs spsr. */
7728 /* Not accessible in user mode. */
7729 if (IS_USER(s
) || IS_M(env
))
7731 tmp
= load_cpu_field(spsr
);
7732 store_reg(s
, rd
, tmp
);
7737 /* Conditional branch. */
7738 op
= (insn
>> 22) & 0xf;
7739 /* Generate a conditional jump to next instruction. */
7740 s
->condlabel
= gen_new_label();
7741 gen_test_cc(op
^ 1, s
->condlabel
);
7744 /* offset[11:1] = insn[10:0] */
7745 offset
= (insn
& 0x7ff) << 1;
7746 /* offset[17:12] = insn[21:16]. */
7747 offset
|= (insn
& 0x003f0000) >> 4;
7748 /* offset[31:20] = insn[26]. */
7749 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7750 /* offset[18] = insn[13]. */
7751 offset
|= (insn
& (1 << 13)) << 5;
7752 /* offset[19] = insn[11]. */
7753 offset
|= (insn
& (1 << 11)) << 8;
7755 /* jump to the offset */
7756 gen_jmp(s
, s
->pc
+ offset
);
7759 /* Data processing immediate. */
7760 if (insn
& (1 << 25)) {
7761 if (insn
& (1 << 24)) {
7762 if (insn
& (1 << 20))
7764 /* Bitfield/Saturate. */
7765 op
= (insn
>> 21) & 7;
7767 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7770 tcg_gen_movi_i32(tmp
, 0);
7772 tmp
= load_reg(s
, rn
);
7775 case 2: /* Signed bitfield extract. */
7777 if (shift
+ imm
> 32)
7780 gen_sbfx(tmp
, shift
, imm
);
7782 case 6: /* Unsigned bitfield extract. */
7784 if (shift
+ imm
> 32)
7787 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7789 case 3: /* Bitfield insert/clear. */
7792 imm
= imm
+ 1 - shift
;
7794 tmp2
= load_reg(s
, rd
);
7795 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7801 default: /* Saturate. */
7804 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7806 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7808 tmp2
= tcg_const_i32(imm
);
7811 if ((op
& 1) && shift
== 0)
7812 gen_helper_usat16(tmp
, tmp
, tmp2
);
7814 gen_helper_usat(tmp
, tmp
, tmp2
);
7817 if ((op
& 1) && shift
== 0)
7818 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7820 gen_helper_ssat(tmp
, tmp
, tmp2
);
7824 store_reg(s
, rd
, tmp
);
7826 imm
= ((insn
& 0x04000000) >> 15)
7827 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7828 if (insn
& (1 << 22)) {
7829 /* 16-bit immediate. */
7830 imm
|= (insn
>> 4) & 0xf000;
7831 if (insn
& (1 << 23)) {
7833 tmp
= load_reg(s
, rd
);
7834 tcg_gen_ext16u_i32(tmp
, tmp
);
7835 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7839 tcg_gen_movi_i32(tmp
, imm
);
7842 /* Add/sub 12-bit immediate. */
7844 offset
= s
->pc
& ~(uint32_t)3;
7845 if (insn
& (1 << 23))
7850 tcg_gen_movi_i32(tmp
, offset
);
7852 tmp
= load_reg(s
, rn
);
7853 if (insn
& (1 << 23))
7854 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7856 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7859 store_reg(s
, rd
, tmp
);
7862 int shifter_out
= 0;
7863 /* modified 12-bit immediate. */
7864 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7865 imm
= (insn
& 0xff);
7868 /* Nothing to do. */
7870 case 1: /* 00XY00XY */
7873 case 2: /* XY00XY00 */
7877 case 3: /* XYXYXYXY */
7881 default: /* Rotated constant. */
7882 shift
= (shift
<< 1) | (imm
>> 7);
7884 imm
= imm
<< (32 - shift
);
7889 tcg_gen_movi_i32(tmp2
, imm
);
7890 rn
= (insn
>> 16) & 0xf;
7893 tcg_gen_movi_i32(tmp
, 0);
7895 tmp
= load_reg(s
, rn
);
7897 op
= (insn
>> 21) & 0xf;
7898 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7899 shifter_out
, tmp
, tmp2
))
7902 rd
= (insn
>> 8) & 0xf;
7904 store_reg(s
, rd
, tmp
);
7911 case 12: /* Load/store single data item. */
7916 if ((insn
& 0x01100000) == 0x01000000) {
7917 if (disas_neon_ls_insn(env
, s
, insn
))
7925 /* s->pc has already been incremented by 4. */
7926 imm
= s
->pc
& 0xfffffffc;
7927 if (insn
& (1 << 23))
7928 imm
+= insn
& 0xfff;
7930 imm
-= insn
& 0xfff;
7931 tcg_gen_movi_i32(addr
, imm
);
7933 addr
= load_reg(s
, rn
);
7934 if (insn
& (1 << 23)) {
7935 /* Positive offset. */
7937 tcg_gen_addi_i32(addr
, addr
, imm
);
7939 op
= (insn
>> 8) & 7;
7942 case 0: case 8: /* Shifted Register. */
7943 shift
= (insn
>> 4) & 0xf;
7946 tmp
= load_reg(s
, rm
);
7948 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7949 tcg_gen_add_i32(addr
, addr
, tmp
);
7952 case 4: /* Negative offset. */
7953 tcg_gen_addi_i32(addr
, addr
, -imm
);
7955 case 6: /* User privilege. */
7956 tcg_gen_addi_i32(addr
, addr
, imm
);
7959 case 1: /* Post-decrement. */
7962 case 3: /* Post-increment. */
7966 case 5: /* Pre-decrement. */
7969 case 7: /* Pre-increment. */
7970 tcg_gen_addi_i32(addr
, addr
, imm
);
7978 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7979 if (insn
& (1 << 20)) {
7981 if (rs
== 15 && op
!= 2) {
7984 /* Memory hint. Implemented as NOP. */
7987 case 0: tmp
= gen_ld8u(addr
, user
); break;
7988 case 4: tmp
= gen_ld8s(addr
, user
); break;
7989 case 1: tmp
= gen_ld16u(addr
, user
); break;
7990 case 5: tmp
= gen_ld16s(addr
, user
); break;
7991 case 2: tmp
= gen_ld32(addr
, user
); break;
7992 default: goto illegal_op
;
7994 if (rs
== 15 && ENABLE_ARCH_5
) {
7997 store_reg(s
, rs
, tmp
);
8004 tmp
= load_reg(s
, rs
);
8006 case 0: gen_st8(tmp
, addr
, user
); break;
8007 case 1: gen_st16(tmp
, addr
, user
); break;
8008 case 2: gen_st32(tmp
, addr
, user
); break;
8009 default: goto illegal_op
;
8013 tcg_gen_addi_i32(addr
, addr
, imm
);
8015 store_reg(s
, rn
, addr
);
8029 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8031 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8039 if (s
->condexec_mask
) {
8040 cond
= s
->condexec_cond
;
8041 s
->condlabel
= gen_new_label();
8042 gen_test_cc(cond
^ 1, s
->condlabel
);
8046 insn
= lduw_code(s
->pc
);
8049 switch (insn
>> 12) {
8053 op
= (insn
>> 11) & 3;
8056 rn
= (insn
>> 3) & 7;
8057 tmp
= load_reg(s
, rn
);
8058 if (insn
& (1 << 10)) {
8061 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
8064 rm
= (insn
>> 6) & 7;
8065 tmp2
= load_reg(s
, rm
);
8067 if (insn
& (1 << 9)) {
8068 if (s
->condexec_mask
)
8069 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8071 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8073 if (s
->condexec_mask
)
8074 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8076 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8079 store_reg(s
, rd
, tmp
);
8081 /* shift immediate */
8082 rm
= (insn
>> 3) & 7;
8083 shift
= (insn
>> 6) & 0x1f;
8084 tmp
= load_reg(s
, rm
);
8085 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8086 if (!s
->condexec_mask
)
8088 store_reg(s
, rd
, tmp
);
8092 /* arithmetic large immediate */
8093 op
= (insn
>> 11) & 3;
8094 rd
= (insn
>> 8) & 0x7;
8095 if (op
== 0) { /* mov */
8097 tcg_gen_movi_i32(tmp
, insn
& 0xff);
8098 if (!s
->condexec_mask
)
8100 store_reg(s
, rd
, tmp
);
8102 tmp
= load_reg(s
, rd
);
8104 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
8107 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8112 if (s
->condexec_mask
)
8113 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8115 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8117 store_reg(s
, rd
, tmp
);
8120 if (s
->condexec_mask
)
8121 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8123 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8125 store_reg(s
, rd
, tmp
);
8131 if (insn
& (1 << 11)) {
8132 rd
= (insn
>> 8) & 7;
8133 /* load pc-relative. Bit 1 of PC is ignored. */
8134 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8135 val
&= ~(uint32_t)2;
8137 tcg_gen_movi_i32(addr
, val
);
8138 tmp
= gen_ld32(addr
, IS_USER(s
));
8140 store_reg(s
, rd
, tmp
);
8143 if (insn
& (1 << 10)) {
8144 /* data processing extended or blx */
8145 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8146 rm
= (insn
>> 3) & 0xf;
8147 op
= (insn
>> 8) & 3;
8150 tmp
= load_reg(s
, rd
);
8151 tmp2
= load_reg(s
, rm
);
8152 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8154 store_reg(s
, rd
, tmp
);
8157 tmp
= load_reg(s
, rd
);
8158 tmp2
= load_reg(s
, rm
);
8159 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8163 case 2: /* mov/cpy */
8164 tmp
= load_reg(s
, rm
);
8165 store_reg(s
, rd
, tmp
);
8167 case 3:/* branch [and link] exchange thumb register */
8168 tmp
= load_reg(s
, rm
);
8169 if (insn
& (1 << 7)) {
8171 val
= (uint32_t)s
->pc
| 1;
8173 tcg_gen_movi_i32(tmp2
, val
);
8174 store_reg(s
, 14, tmp2
);
8182 /* data processing register */
8184 rm
= (insn
>> 3) & 7;
8185 op
= (insn
>> 6) & 0xf;
8186 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8187 /* the shift/rotate ops want the operands backwards */
8196 if (op
== 9) { /* neg */
8198 tcg_gen_movi_i32(tmp
, 0);
8199 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
8200 tmp
= load_reg(s
, rd
);
8205 tmp2
= load_reg(s
, rm
);
8208 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8209 if (!s
->condexec_mask
)
8213 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
8214 if (!s
->condexec_mask
)
8218 if (s
->condexec_mask
) {
8219 gen_helper_shl(tmp2
, tmp2
, tmp
);
8221 gen_helper_shl_cc(tmp2
, tmp2
, tmp
);
8226 if (s
->condexec_mask
) {
8227 gen_helper_shr(tmp2
, tmp2
, tmp
);
8229 gen_helper_shr_cc(tmp2
, tmp2
, tmp
);
8234 if (s
->condexec_mask
) {
8235 gen_helper_sar(tmp2
, tmp2
, tmp
);
8237 gen_helper_sar_cc(tmp2
, tmp2
, tmp
);
8242 if (s
->condexec_mask
)
8243 gen_add_carry(tmp
, tmp
, tmp2
);
8245 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
8248 if (s
->condexec_mask
)
8249 gen_sub_carry(tmp
, tmp
, tmp2
);
8251 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
8254 if (s
->condexec_mask
) {
8255 gen_helper_ror(tmp2
, tmp2
, tmp
);
8257 gen_helper_ror_cc(tmp2
, tmp2
, tmp
);
8262 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
8267 if (s
->condexec_mask
)
8268 tcg_gen_neg_i32(tmp
, tmp2
);
8270 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8273 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
8277 gen_helper_add_cc(tmp
, tmp
, tmp2
);
8281 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8282 if (!s
->condexec_mask
)
8286 gen_mull(tmp
, tmp2
);
8287 if (!s
->condexec_mask
)
8291 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
8292 if (!s
->condexec_mask
)
8296 tcg_gen_not_i32(tmp2
, tmp2
);
8297 if (!s
->condexec_mask
)
8305 store_reg(s
, rm
, tmp2
);
8308 store_reg(s
, rd
, tmp
);
8318 /* load/store register offset. */
8320 rn
= (insn
>> 3) & 7;
8321 rm
= (insn
>> 6) & 7;
8322 op
= (insn
>> 9) & 7;
8323 addr
= load_reg(s
, rn
);
8324 tmp
= load_reg(s
, rm
);
8325 tcg_gen_add_i32(addr
, addr
, tmp
);
8328 if (op
< 3) /* store */
8329 tmp
= load_reg(s
, rd
);
8333 gen_st32(tmp
, addr
, IS_USER(s
));
8336 gen_st16(tmp
, addr
, IS_USER(s
));
8339 gen_st8(tmp
, addr
, IS_USER(s
));
8342 tmp
= gen_ld8s(addr
, IS_USER(s
));
8345 tmp
= gen_ld32(addr
, IS_USER(s
));
8348 tmp
= gen_ld16u(addr
, IS_USER(s
));
8351 tmp
= gen_ld8u(addr
, IS_USER(s
));
8354 tmp
= gen_ld16s(addr
, IS_USER(s
));
8357 if (op
>= 3) /* load */
8358 store_reg(s
, rd
, tmp
);
8363 /* load/store word immediate offset */
8365 rn
= (insn
>> 3) & 7;
8366 addr
= load_reg(s
, rn
);
8367 val
= (insn
>> 4) & 0x7c;
8368 tcg_gen_addi_i32(addr
, addr
, val
);
8370 if (insn
& (1 << 11)) {
8372 tmp
= gen_ld32(addr
, IS_USER(s
));
8373 store_reg(s
, rd
, tmp
);
8376 tmp
= load_reg(s
, rd
);
8377 gen_st32(tmp
, addr
, IS_USER(s
));
8383 /* load/store byte immediate offset */
8385 rn
= (insn
>> 3) & 7;
8386 addr
= load_reg(s
, rn
);
8387 val
= (insn
>> 6) & 0x1f;
8388 tcg_gen_addi_i32(addr
, addr
, val
);
8390 if (insn
& (1 << 11)) {
8392 tmp
= gen_ld8u(addr
, IS_USER(s
));
8393 store_reg(s
, rd
, tmp
);
8396 tmp
= load_reg(s
, rd
);
8397 gen_st8(tmp
, addr
, IS_USER(s
));
8403 /* load/store halfword immediate offset */
8405 rn
= (insn
>> 3) & 7;
8406 addr
= load_reg(s
, rn
);
8407 val
= (insn
>> 5) & 0x3e;
8408 tcg_gen_addi_i32(addr
, addr
, val
);
8410 if (insn
& (1 << 11)) {
8412 tmp
= gen_ld16u(addr
, IS_USER(s
));
8413 store_reg(s
, rd
, tmp
);
8416 tmp
= load_reg(s
, rd
);
8417 gen_st16(tmp
, addr
, IS_USER(s
));
8423 /* load/store from stack */
8424 rd
= (insn
>> 8) & 7;
8425 addr
= load_reg(s
, 13);
8426 val
= (insn
& 0xff) * 4;
8427 tcg_gen_addi_i32(addr
, addr
, val
);
8429 if (insn
& (1 << 11)) {
8431 tmp
= gen_ld32(addr
, IS_USER(s
));
8432 store_reg(s
, rd
, tmp
);
8435 tmp
= load_reg(s
, rd
);
8436 gen_st32(tmp
, addr
, IS_USER(s
));
8442 /* add to high reg */
8443 rd
= (insn
>> 8) & 7;
8444 if (insn
& (1 << 11)) {
8446 tmp
= load_reg(s
, 13);
8448 /* PC. bit 1 is ignored. */
8450 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8452 val
= (insn
& 0xff) * 4;
8453 tcg_gen_addi_i32(tmp
, tmp
, val
);
8454 store_reg(s
, rd
, tmp
);
8459 op
= (insn
>> 8) & 0xf;
8462 /* adjust stack pointer */
8463 tmp
= load_reg(s
, 13);
8464 val
= (insn
& 0x7f) * 4;
8465 if (insn
& (1 << 7))
8466 val
= -(int32_t)val
;
8467 tcg_gen_addi_i32(tmp
, tmp
, val
);
8468 store_reg(s
, 13, tmp
);
8471 case 2: /* sign/zero extend. */
8474 rm
= (insn
>> 3) & 7;
8475 tmp
= load_reg(s
, rm
);
8476 switch ((insn
>> 6) & 3) {
8477 case 0: gen_sxth(tmp
); break;
8478 case 1: gen_sxtb(tmp
); break;
8479 case 2: gen_uxth(tmp
); break;
8480 case 3: gen_uxtb(tmp
); break;
8482 store_reg(s
, rd
, tmp
);
8484 case 4: case 5: case 0xc: case 0xd:
8486 addr
= load_reg(s
, 13);
8487 if (insn
& (1 << 8))
8491 for (i
= 0; i
< 8; i
++) {
8492 if (insn
& (1 << i
))
8495 if ((insn
& (1 << 11)) == 0) {
8496 tcg_gen_addi_i32(addr
, addr
, -offset
);
8498 for (i
= 0; i
< 8; i
++) {
8499 if (insn
& (1 << i
)) {
8500 if (insn
& (1 << 11)) {
8502 tmp
= gen_ld32(addr
, IS_USER(s
));
8503 store_reg(s
, i
, tmp
);
8506 tmp
= load_reg(s
, i
);
8507 gen_st32(tmp
, addr
, IS_USER(s
));
8509 /* advance to the next address. */
8510 tcg_gen_addi_i32(addr
, addr
, 4);
8514 if (insn
& (1 << 8)) {
8515 if (insn
& (1 << 11)) {
8517 tmp
= gen_ld32(addr
, IS_USER(s
));
8518 /* don't set the pc until the rest of the instruction
8522 tmp
= load_reg(s
, 14);
8523 gen_st32(tmp
, addr
, IS_USER(s
));
8525 tcg_gen_addi_i32(addr
, addr
, 4);
8527 if ((insn
& (1 << 11)) == 0) {
8528 tcg_gen_addi_i32(addr
, addr
, -offset
);
8530 /* write back the new stack pointer */
8531 store_reg(s
, 13, addr
);
8532 /* set the new PC value */
8533 if ((insn
& 0x0900) == 0x0900) {
8534 if (ENABLE_ARCH_5
) {
8537 store_reg(s
, 15, tmp
);
8542 case 1: case 3: case 9: case 11: /* czb */
8544 tmp
= load_reg(s
, rm
);
8545 s
->condlabel
= gen_new_label();
8547 if (insn
& (1 << 11))
8548 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8550 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8552 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8553 val
= (uint32_t)s
->pc
+ 2;
8558 case 15: /* IT, nop-hint. */
8559 if ((insn
& 0xf) == 0) {
8560 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8564 s
->condexec_cond
= (insn
>> 4) & 0xe;
8565 s
->condexec_mask
= insn
& 0x1f;
8566 /* No actual code generated for this insn, just setup state. */
8569 case 0xe: /* bkpt */
8570 gen_set_condexec(s
);
8571 gen_set_pc_im(s
->pc
- 2);
8572 gen_exception(EXCP_BKPT
);
8573 s
->is_jmp
= DISAS_JUMP
;
8578 rn
= (insn
>> 3) & 0x7;
8580 tmp
= load_reg(s
, rn
);
8581 switch ((insn
>> 6) & 3) {
8582 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8583 case 1: gen_rev16(tmp
); break;
8584 case 3: gen_revsh(tmp
); break;
8585 default: goto illegal_op
;
8587 store_reg(s
, rd
, tmp
);
8595 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8598 addr
= tcg_const_i32(16);
8599 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8603 addr
= tcg_const_i32(17);
8604 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8608 if (insn
& (1 << 4))
8609 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8612 gen_set_psr_im(s
, shift
, 0, ((insn
& 7) << 6) & shift
);
8622 /* load/store multiple */
8623 rn
= (insn
>> 8) & 0x7;
8624 addr
= load_reg(s
, rn
);
8625 if (arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << rn
)) == 0) {
8626 /* base-updated abort model: update base register
8627 before an abort can happen */
8629 for (i
= 0; i
< 8; i
++) {
8630 if (insn
& (1 << i
)) {
8635 tcg_gen_addi_i32(tmp
, addr
, crement
);
8636 store_reg(s
, rn
, tmp
);
8638 for (i
= 0; i
< 8; i
++) {
8639 if (insn
& (1 << i
)) {
8640 if (insn
& (1 << 11)) {
8642 tmp
= gen_ld32(addr
, IS_USER(s
));
8643 store_reg(s
, i
, tmp
);
8646 tmp
= load_reg(s
, i
);
8647 gen_st32(tmp
, addr
, IS_USER(s
));
8649 /* advance to the next address */
8650 tcg_gen_addi_i32(addr
, addr
, 4);
8653 /* Base register writeback. */
8654 if (!arm_feature(env
, ARM_FEATURE_ABORT_BU
) && (insn
& (1 << rn
)) == 0) {
8655 store_reg(s
, rn
, addr
);
8662 /* conditional branch or swi */
8663 cond
= (insn
>> 8) & 0xf;
8669 gen_set_condexec(s
);
8670 gen_set_pc_im(s
->pc
);
8671 s
->is_jmp
= DISAS_SWI
;
8674 /* generate a conditional jump to next instruction */
8675 s
->condlabel
= gen_new_label();
8676 gen_test_cc(cond
^ 1, s
->condlabel
);
8679 /* jump to the offset */
8680 val
= (uint32_t)s
->pc
+ 2;
8681 offset
= ((int32_t)insn
<< 24) >> 24;
8687 if (insn
& (1 << 11)) {
8688 if (disas_thumb2_insn(env
, s
, insn
))
8692 /* unconditional branch */
8693 val
= (uint32_t)s
->pc
;
8694 offset
= ((int32_t)insn
<< 21) >> 21;
8695 val
+= (offset
<< 1) + 2;
8700 if (disas_thumb2_insn(env
, s
, insn
))
8706 gen_set_condexec(s
);
8707 gen_set_pc_im(s
->pc
- 4);
8708 gen_exception(EXCP_UDEF
);
8709 s
->is_jmp
= DISAS_JUMP
;
8713 gen_set_condexec(s
);
8714 gen_set_pc_im(s
->pc
- 2);
8715 gen_exception(EXCP_UDEF
);
8716 s
->is_jmp
= DISAS_JUMP
;
8719 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8720 basic block 'tb'. If search_pc is TRUE, also generate PC
8721 information for each intermediate instruction. */
8722 static inline void gen_intermediate_code_internal(CPUState
*env
,
8723 TranslationBlock
*tb
,
8726 DisasContext dc1
, *dc
= &dc1
;
8728 uint16_t *gen_opc_end
;
8730 target_ulong pc_start
;
8731 uint32_t next_page_start
;
8735 /* generate intermediate code */
8742 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8744 dc
->is_jmp
= DISAS_NEXT
;
8746 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8748 dc
->thumb
= env
->thumb
;
8749 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8750 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8751 #if !defined(CONFIG_USER_ONLY)
8753 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8755 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8758 cpu_F0s
= tcg_temp_new_i32();
8759 cpu_F1s
= tcg_temp_new_i32();
8760 cpu_F0d
= tcg_temp_new_i64();
8761 cpu_F1d
= tcg_temp_new_i64();
8764 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8765 cpu_M0
= tcg_temp_new_i64();
8766 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8769 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8771 max_insns
= CF_COUNT_MASK
;
8774 /* Reset the conditional execution bits immediately. This avoids
8775 complications trying to do it at the end of the block. */
8776 if (env
->condexec_bits
)
8778 TCGv tmp
= new_tmp();
8779 tcg_gen_movi_i32(tmp
, 0);
8780 store_cpu_field(tmp
, condexec_bits
);
8783 #ifdef CONFIG_USER_ONLY
8784 /* Intercept jump to the magic kernel page. */
8785 if (dc
->pc
>= 0xffff0000) {
8786 /* We always get here via a jump, so know we are not in a
8787 conditional execution block. */
8788 gen_exception(EXCP_KERNEL_TRAP
);
8789 dc
->is_jmp
= DISAS_UPDATE
;
8793 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8794 /* We always get here via a jump, so know we are not in a
8795 conditional execution block. */
8796 gen_exception(EXCP_EXCEPTION_EXIT
);
8797 dc
->is_jmp
= DISAS_UPDATE
;
8802 if (unlikely(!TAILQ_EMPTY(&env
->breakpoints
))) {
8803 TAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8804 if (bp
->pc
== dc
->pc
) {
8805 gen_set_condexec(dc
);
8806 gen_set_pc_im(dc
->pc
);
8807 gen_exception(EXCP_DEBUG
);
8808 dc
->is_jmp
= DISAS_JUMP
;
8809 /* Advance PC so that clearing the breakpoint will
8810 invalidate this TB. */
8812 goto done_generating
;
8818 j
= gen_opc_ptr
- gen_opc_buf
;
8822 gen_opc_instr_start
[lj
++] = 0;
8824 gen_opc_pc
[lj
] = dc
->pc
;
8825 gen_opc_instr_start
[lj
] = 1;
8826 gen_opc_icount
[lj
] = num_insns
;
8829 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8833 disas_thumb_insn(env
, dc
);
8834 if (dc
->condexec_mask
) {
8835 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8836 | ((dc
->condexec_mask
>> 4) & 1);
8837 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8838 if (dc
->condexec_mask
== 0) {
8839 dc
->condexec_cond
= 0;
8843 disas_arm_insn(env
, dc
);
8846 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8850 if (dc
->condjmp
&& !dc
->is_jmp
) {
8851 gen_set_label(dc
->condlabel
);
8854 /* Translation stops when a conditional branch is encountered.
8855 * Otherwise the subsequent code could get translated several times.
8856 * Also stop translation when a page boundary is reached. This
8857 * ensures prefetch aborts occur at the right place. */
8859 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8860 !env
->singlestep_enabled
&&
8862 dc
->pc
< next_page_start
&&
8863 num_insns
< max_insns
);
8865 if (tb
->cflags
& CF_LAST_IO
) {
8867 /* FIXME: This can theoretically happen with self-modifying
8869 cpu_abort(env
, "IO on conditional branch instruction");
8874 /* At this stage dc->condjmp will only be set when the skipped
8875 instruction was a conditional branch or trap, and the PC has
8876 already been written. */
8877 if (unlikely(env
->singlestep_enabled
)) {
8878 /* Make sure the pc is updated, and raise a debug exception. */
8880 gen_set_condexec(dc
);
8881 if (dc
->is_jmp
== DISAS_SWI
) {
8882 gen_exception(EXCP_SWI
);
8884 gen_exception(EXCP_DEBUG
);
8886 gen_set_label(dc
->condlabel
);
8888 if (dc
->condjmp
|| !dc
->is_jmp
) {
8889 gen_set_pc_im(dc
->pc
);
8892 gen_set_condexec(dc
);
8893 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8894 gen_exception(EXCP_SWI
);
8896 /* FIXME: Single stepping a WFI insn will not halt
8898 gen_exception(EXCP_DEBUG
);
8901 /* While branches must always occur at the end of an IT block,
8902 there are a few other things that can cause us to terminate
8903 the TB in the middel of an IT block:
8904 - Exception generating instructions (bkpt, swi, undefined).
8906 - Hardware watchpoints.
8907 Hardware breakpoints have already been handled and skip this code.
8909 gen_set_condexec(dc
);
8910 switch(dc
->is_jmp
) {
8912 gen_goto_tb(dc
, 1, dc
->pc
);
8917 /* indicate that the hash table must be used to find the next TB */
8921 /* nothing more to generate */
8927 gen_exception(EXCP_SWI
);
8931 gen_set_label(dc
->condlabel
);
8932 gen_set_condexec(dc
);
8933 gen_goto_tb(dc
, 1, dc
->pc
);
8939 gen_icount_end(tb
, num_insns
);
8940 *gen_opc_ptr
= INDEX_op_end
;
8943 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8944 qemu_log("----------------\n");
8945 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8946 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8951 j
= gen_opc_ptr
- gen_opc_buf
;
8954 gen_opc_instr_start
[lj
++] = 0;
8956 tb
->size
= dc
->pc
- pc_start
;
8957 tb
->icount
= num_insns
;
8961 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8963 gen_intermediate_code_internal(env
, tb
, 0);
8966 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8968 gen_intermediate_code_internal(env
, tb
, 1);
8971 static const char *cpu_mode_names
[16] = {
8972 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8973 "???", "???", "???", "und", "???", "???", "???", "sys"
8976 void cpu_dump_state(CPUState
*env
, FILE *f
,
8977 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8987 /* ??? This assumes float64 and double have the same layout.
8988 Oh well, it's only debug dumps. */
8997 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8999 cpu_fprintf(f
, "\n");
9001 cpu_fprintf(f
, " ");
9003 psr
= cpsr_read(env
);
9004 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
9006 psr
& (1 << 31) ? 'N' : '-',
9007 psr
& (1 << 30) ? 'Z' : '-',
9008 psr
& (1 << 29) ? 'C' : '-',
9009 psr
& (1 << 28) ? 'V' : '-',
9010 psr
& CPSR_T
? 'T' : 'A',
9011 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
9014 for (i
= 0; i
< 16; i
++) {
9015 d
.d
= env
->vfp
.regs
[i
];
9019 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9020 i
* 2, (int)s0
.i
, s0
.s
,
9021 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9022 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9025 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9029 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9030 unsigned long searched_pc
, int pc_pos
, void *puc
)
9032 env
->regs
[15] = gen_opc_pc
[pc_pos
];