4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext
{
49 /* Nonzero if this instruction has been conditionally skipped. */
51 /* The label that will be jumped to when the instruction is skipped. */
53 /* Thumb-2 condtional execution bits. */
56 struct TranslationBlock
*tb
;
57 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 static TCGv_ptr cpu_env
;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
79 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s
, cpu_F1s
;
82 static TCGv_i64 cpu_F0d
, cpu_F1d
;
84 #define ICOUNT_TEMP cpu_T[0]
85 #include "gen-icount.h"
87 /* initialize TCG globals. */
88 void arm_translate_init(void)
90 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
92 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
93 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
99 /* The code generator doesn't like lots of temporaries, so maintain our own
100 cache for reuse within a function. */
102 static int num_temps
;
103 static TCGv temps
[MAX_TEMPS
];
105 /* Allocate a temporary variable. */
106 static TCGv_i32
new_tmp(void)
109 if (num_temps
== MAX_TEMPS
)
112 if (GET_TCGV_I32(temps
[num_temps
]))
113 return temps
[num_temps
++];
115 tmp
= tcg_temp_new_i32();
116 temps
[num_temps
++] = tmp
;
120 /* Release a temporary variable. */
121 static void dead_tmp(TCGv tmp
)
126 if (TCGV_EQUAL(temps
[i
], tmp
))
129 /* Shuffle this temp to the last slot. */
130 while (!TCGV_EQUAL(temps
[i
], tmp
))
132 while (i
< num_temps
) {
133 temps
[i
] = temps
[i
+ 1];
139 static inline TCGv
load_cpu_offset(int offset
)
141 TCGv tmp
= new_tmp();
142 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
146 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
148 static inline void store_cpu_offset(TCGv var
, int offset
)
150 tcg_gen_st_i32(var
, cpu_env
, offset
);
154 #define store_cpu_field(var, name) \
155 store_cpu_offset(var, offsetof(CPUState, name))
157 /* Set a variable to the value of a CPU register. */
158 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
162 /* normaly, since we updated PC, we need only to add one insn */
164 addr
= (long)s
->pc
+ 2;
166 addr
= (long)s
->pc
+ 4;
167 tcg_gen_movi_i32(var
, addr
);
169 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
173 /* Create a new temporary and set it to the value of a CPU register. */
174 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
176 TCGv tmp
= new_tmp();
177 load_reg_var(s
, tmp
, reg
);
181 /* Set a CPU register. The source must be a temporary and will be
183 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
186 tcg_gen_andi_i32(var
, var
, ~1);
187 s
->is_jmp
= DISAS_JUMP
;
189 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
194 /* Basic operations. */
195 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
196 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
197 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
199 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
200 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
201 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
204 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
205 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
207 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
210 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
214 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
215 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
216 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
218 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
219 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
221 /* Value extensions. */
222 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
223 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
224 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
225 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
227 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
228 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
230 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
232 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
233 /* Set NZCV flags from the high 4 bits of var. */
234 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
236 static void gen_exception(int excp
)
238 TCGv tmp
= new_tmp();
239 tcg_gen_movi_i32(tmp
, excp
);
240 gen_helper_exception(tmp
);
244 static void gen_smul_dual(TCGv a
, TCGv b
)
246 TCGv tmp1
= new_tmp();
247 TCGv tmp2
= new_tmp();
248 tcg_gen_ext16s_i32(tmp1
, a
);
249 tcg_gen_ext16s_i32(tmp2
, b
);
250 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
252 tcg_gen_sari_i32(a
, a
, 16);
253 tcg_gen_sari_i32(b
, b
, 16);
254 tcg_gen_mul_i32(b
, b
, a
);
255 tcg_gen_mov_i32(a
, tmp1
);
259 /* Byteswap each halfword. */
260 static void gen_rev16(TCGv var
)
262 TCGv tmp
= new_tmp();
263 tcg_gen_shri_i32(tmp
, var
, 8);
264 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
265 tcg_gen_shli_i32(var
, var
, 8);
266 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
267 tcg_gen_or_i32(var
, var
, tmp
);
271 /* Byteswap low halfword and sign extend. */
272 static void gen_revsh(TCGv var
)
274 TCGv tmp
= new_tmp();
275 tcg_gen_shri_i32(tmp
, var
, 8);
276 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
277 tcg_gen_shli_i32(var
, var
, 8);
278 tcg_gen_ext8s_i32(var
, var
);
279 tcg_gen_or_i32(var
, var
, tmp
);
283 /* Unsigned bitfield extract. */
284 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
287 tcg_gen_shri_i32(var
, var
, shift
);
288 tcg_gen_andi_i32(var
, var
, mask
);
291 /* Signed bitfield extract. */
292 static void gen_sbfx(TCGv var
, int shift
, int width
)
297 tcg_gen_sari_i32(var
, var
, shift
);
298 if (shift
+ width
< 32) {
299 signbit
= 1u << (width
- 1);
300 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
301 tcg_gen_xori_i32(var
, var
, signbit
);
302 tcg_gen_subi_i32(var
, var
, signbit
);
306 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
307 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
309 tcg_gen_andi_i32(val
, val
, mask
);
310 tcg_gen_shli_i32(val
, val
, shift
);
311 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
312 tcg_gen_or_i32(dest
, base
, val
);
315 /* Round the top 32 bits of a 64-bit value. */
316 static void gen_roundqd(TCGv a
, TCGv b
)
318 tcg_gen_shri_i32(a
, a
, 31);
319 tcg_gen_add_i32(a
, a
, b
);
322 /* FIXME: Most targets have native widening multiplication.
323 It would be good to use that instead of a full wide multiply. */
324 /* 32x32->64 multiply. Marks inputs as dead. */
325 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
327 TCGv_i64 tmp1
= tcg_temp_new_i64();
328 TCGv_i64 tmp2
= tcg_temp_new_i64();
330 tcg_gen_extu_i32_i64(tmp1
, a
);
332 tcg_gen_extu_i32_i64(tmp2
, b
);
334 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
338 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
340 TCGv_i64 tmp1
= tcg_temp_new_i64();
341 TCGv_i64 tmp2
= tcg_temp_new_i64();
343 tcg_gen_ext_i32_i64(tmp1
, a
);
345 tcg_gen_ext_i32_i64(tmp2
, b
);
347 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
351 /* Unsigned 32x32->64 multiply. */
352 static void gen_op_mull_T0_T1(void)
354 TCGv_i64 tmp1
= tcg_temp_new_i64();
355 TCGv_i64 tmp2
= tcg_temp_new_i64();
357 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
358 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
359 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
360 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
361 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
362 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
365 /* Signed 32x32->64 multiply. */
366 static void gen_imull(TCGv a
, TCGv b
)
368 TCGv_i64 tmp1
= tcg_temp_new_i64();
369 TCGv_i64 tmp2
= tcg_temp_new_i64();
371 tcg_gen_ext_i32_i64(tmp1
, a
);
372 tcg_gen_ext_i32_i64(tmp2
, b
);
373 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
374 tcg_gen_trunc_i64_i32(a
, tmp1
);
375 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
376 tcg_gen_trunc_i64_i32(b
, tmp1
);
379 /* Swap low and high halfwords. */
380 static void gen_swap_half(TCGv var
)
382 TCGv tmp
= new_tmp();
383 tcg_gen_shri_i32(tmp
, var
, 16);
384 tcg_gen_shli_i32(var
, var
, 16);
385 tcg_gen_or_i32(var
, var
, tmp
);
389 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
390 tmp = (t0 ^ t1) & 0x8000;
393 t0 = (t0 + t1) ^ tmp;
396 static void gen_add16(TCGv t0
, TCGv t1
)
398 TCGv tmp
= new_tmp();
399 tcg_gen_xor_i32(tmp
, t0
, t1
);
400 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
401 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
402 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
403 tcg_gen_add_i32(t0
, t0
, t1
);
404 tcg_gen_xor_i32(t0
, t0
, tmp
);
409 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
411 /* Set CF to the top bit of var. */
412 static void gen_set_CF_bit31(TCGv var
)
414 TCGv tmp
= new_tmp();
415 tcg_gen_shri_i32(tmp
, var
, 31);
420 /* Set N and Z flags from var. */
421 static inline void gen_logic_CC(TCGv var
)
423 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
424 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
428 static void gen_adc_T0_T1(void)
432 tmp
= load_cpu_field(CF
);
433 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
437 /* dest = T0 + T1 + CF. */
438 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
441 tcg_gen_add_i32(dest
, t0
, t1
);
442 tmp
= load_cpu_field(CF
);
443 tcg_gen_add_i32(dest
, dest
, tmp
);
447 /* dest = T0 - T1 + CF - 1. */
448 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
451 tcg_gen_sub_i32(dest
, t0
, t1
);
452 tmp
= load_cpu_field(CF
);
453 tcg_gen_add_i32(dest
, dest
, tmp
);
454 tcg_gen_subi_i32(dest
, dest
, 1);
458 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
459 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
461 /* T0 &= ~T1. Clobbers T1. */
462 /* FIXME: Implement bic natively. */
463 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
465 TCGv tmp
= new_tmp();
466 tcg_gen_not_i32(tmp
, t1
);
467 tcg_gen_and_i32(dest
, t0
, tmp
);
470 static inline void gen_op_bicl_T0_T1(void)
476 /* FIXME: Implement this natively. */
477 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
479 /* FIXME: Implement this natively. */
480 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
488 tcg_gen_shri_i32(tmp
, t1
, i
);
489 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
490 tcg_gen_or_i32(t0
, t1
, tmp
);
494 static void shifter_out_im(TCGv var
, int shift
)
496 TCGv tmp
= new_tmp();
498 tcg_gen_andi_i32(tmp
, var
, 1);
500 tcg_gen_shri_i32(tmp
, var
, shift
);
502 tcg_gen_andi_i32(tmp
, tmp
, 1);
508 /* Shift by immediate. Includes special handling for shift == 0. */
509 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
515 shifter_out_im(var
, 32 - shift
);
516 tcg_gen_shli_i32(var
, var
, shift
);
522 tcg_gen_shri_i32(var
, var
, 31);
525 tcg_gen_movi_i32(var
, 0);
528 shifter_out_im(var
, shift
- 1);
529 tcg_gen_shri_i32(var
, var
, shift
);
536 shifter_out_im(var
, shift
- 1);
539 tcg_gen_sari_i32(var
, var
, shift
);
541 case 3: /* ROR/RRX */
544 shifter_out_im(var
, shift
- 1);
545 tcg_gen_rori_i32(var
, var
, shift
); break;
547 TCGv tmp
= load_cpu_field(CF
);
549 shifter_out_im(var
, 0);
550 tcg_gen_shri_i32(var
, var
, 1);
551 tcg_gen_shli_i32(tmp
, tmp
, 31);
552 tcg_gen_or_i32(var
, var
, tmp
);
558 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
559 TCGv shift
, int flags
)
563 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
564 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
565 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
566 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
570 case 0: gen_helper_shl(var
, var
, shift
); break;
571 case 1: gen_helper_shr(var
, var
, shift
); break;
572 case 2: gen_helper_sar(var
, var
, shift
); break;
573 case 3: gen_helper_ror(var
, var
, shift
); break;
579 #define PAS_OP(pfx) \
581 case 0: gen_pas_helper(glue(pfx,add16)); break; \
582 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
583 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
584 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
585 case 4: gen_pas_helper(glue(pfx,add8)); break; \
586 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
588 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
593 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
595 tmp
= tcg_temp_new_ptr();
596 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
600 tmp
= tcg_temp_new_ptr();
601 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
604 #undef gen_pas_helper
605 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
618 #undef gen_pas_helper
623 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
624 #define PAS_OP(pfx) \
626 case 0: gen_pas_helper(glue(pfx,add8)); break; \
627 case 1: gen_pas_helper(glue(pfx,add16)); break; \
628 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
629 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
630 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
631 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
633 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
638 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
640 tmp
= tcg_temp_new_ptr();
641 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
645 tmp
= tcg_temp_new_ptr();
646 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
649 #undef gen_pas_helper
650 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
663 #undef gen_pas_helper
668 static void gen_test_cc(int cc
, int label
)
676 tmp
= load_cpu_field(ZF
);
677 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
680 tmp
= load_cpu_field(ZF
);
681 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
684 tmp
= load_cpu_field(CF
);
685 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
688 tmp
= load_cpu_field(CF
);
689 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
692 tmp
= load_cpu_field(NF
);
693 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
696 tmp
= load_cpu_field(NF
);
697 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
700 tmp
= load_cpu_field(VF
);
701 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
704 tmp
= load_cpu_field(VF
);
705 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
707 case 8: /* hi: C && !Z */
708 inv
= gen_new_label();
709 tmp
= load_cpu_field(CF
);
710 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
712 tmp
= load_cpu_field(ZF
);
713 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
716 case 9: /* ls: !C || Z */
717 tmp
= load_cpu_field(CF
);
718 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
720 tmp
= load_cpu_field(ZF
);
721 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
723 case 10: /* ge: N == V -> N ^ V == 0 */
724 tmp
= load_cpu_field(VF
);
725 tmp2
= load_cpu_field(NF
);
726 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
728 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
730 case 11: /* lt: N != V -> N ^ V != 0 */
731 tmp
= load_cpu_field(VF
);
732 tmp2
= load_cpu_field(NF
);
733 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
735 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
737 case 12: /* gt: !Z && N == V */
738 inv
= gen_new_label();
739 tmp
= load_cpu_field(ZF
);
740 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
742 tmp
= load_cpu_field(VF
);
743 tmp2
= load_cpu_field(NF
);
744 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
746 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
749 case 13: /* le: Z || N != V */
750 tmp
= load_cpu_field(ZF
);
751 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
753 tmp
= load_cpu_field(VF
);
754 tmp2
= load_cpu_field(NF
);
755 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
757 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
760 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
766 static const uint8_t table_logic_cc
[16] = {
785 /* Set PC and Thumb state from an immediate address. */
786 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
790 s
->is_jmp
= DISAS_UPDATE
;
792 if (s
->thumb
!= (addr
& 1)) {
793 tcg_gen_movi_i32(tmp
, addr
& 1);
794 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
796 tcg_gen_movi_i32(tmp
, addr
& ~1);
797 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[15]));
801 /* Set PC and Thumb state from var. var is marked as dead. */
802 static inline void gen_bx(DisasContext
*s
, TCGv var
)
806 s
->is_jmp
= DISAS_UPDATE
;
808 tcg_gen_andi_i32(tmp
, var
, 1);
809 store_cpu_field(tmp
, thumb
);
810 tcg_gen_andi_i32(var
, var
, ~1);
811 store_cpu_field(var
, regs
[15]);
814 /* Variant of store_reg which uses branch&exchange logic when storing
815 to r15 in ARM architecture v7 and above. The source must be a temporary
816 and will be marked as dead. */
817 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
820 if (reg
== 15 && ENABLE_ARCH_7
) {
823 store_reg(s
, reg
, var
);
827 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
829 TCGv tmp
= new_tmp();
830 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
833 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
835 TCGv tmp
= new_tmp();
836 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
839 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
841 TCGv tmp
= new_tmp();
842 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
845 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
847 TCGv tmp
= new_tmp();
848 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
851 static inline TCGv
gen_ld32(TCGv addr
, int index
)
853 TCGv tmp
= new_tmp();
854 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
857 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
859 tcg_gen_qemu_st8(val
, addr
, index
);
862 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
864 tcg_gen_qemu_st16(val
, addr
, index
);
867 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
869 tcg_gen_qemu_st32(val
, addr
, index
);
873 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
875 load_reg_var(s
, cpu_T
[0], reg
);
878 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
880 load_reg_var(s
, cpu_T
[1], reg
);
883 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
885 load_reg_var(s
, cpu_T
[2], reg
);
888 static inline void gen_set_pc_im(uint32_t val
)
890 TCGv tmp
= new_tmp();
891 tcg_gen_movi_i32(tmp
, val
);
892 store_cpu_field(tmp
, regs
[15]);
895 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
900 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
904 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
907 s
->is_jmp
= DISAS_JUMP
;
911 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
913 gen_movl_reg_TN(s
, reg
, 0);
916 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
918 gen_movl_reg_TN(s
, reg
, 1);
921 /* Force a TB lookup after an instruction that changes the CPU state. */
922 static inline void gen_lookup_tb(DisasContext
*s
)
924 gen_op_movl_T0_im(s
->pc
);
925 gen_movl_reg_T0(s
, 15);
926 s
->is_jmp
= DISAS_UPDATE
;
929 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
932 int val
, rm
, shift
, shiftop
;
935 if (!(insn
& (1 << 25))) {
938 if (!(insn
& (1 << 23)))
941 tcg_gen_addi_i32(var
, var
, val
);
945 shift
= (insn
>> 7) & 0x1f;
946 shiftop
= (insn
>> 5) & 3;
947 offset
= load_reg(s
, rm
);
948 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
949 if (!(insn
& (1 << 23)))
950 tcg_gen_sub_i32(var
, var
, offset
);
952 tcg_gen_add_i32(var
, var
, offset
);
957 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
963 if (insn
& (1 << 22)) {
965 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
966 if (!(insn
& (1 << 23)))
970 tcg_gen_addi_i32(var
, var
, val
);
974 tcg_gen_addi_i32(var
, var
, extra
);
976 offset
= load_reg(s
, rm
);
977 if (!(insn
& (1 << 23)))
978 tcg_gen_sub_i32(var
, var
, offset
);
980 tcg_gen_add_i32(var
, var
, offset
);
985 #define VFP_OP2(name) \
986 static inline void gen_vfp_##name(int dp) \
989 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
991 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1001 static inline void gen_vfp_abs(int dp
)
1004 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1006 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1009 static inline void gen_vfp_neg(int dp
)
1012 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1014 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1017 static inline void gen_vfp_sqrt(int dp
)
1020 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1022 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1025 static inline void gen_vfp_cmp(int dp
)
1028 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1030 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1033 static inline void gen_vfp_cmpe(int dp
)
1036 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1038 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1041 static inline void gen_vfp_F1_ld0(int dp
)
1044 tcg_gen_movi_i64(cpu_F1d
, 0);
1046 tcg_gen_movi_i32(cpu_F1s
, 0);
1049 static inline void gen_vfp_uito(int dp
)
1052 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1054 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1057 static inline void gen_vfp_sito(int dp
)
1060 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1062 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1065 static inline void gen_vfp_toui(int dp
)
1068 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1070 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1073 static inline void gen_vfp_touiz(int dp
)
1076 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1078 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1081 static inline void gen_vfp_tosi(int dp
)
1084 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1086 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1089 static inline void gen_vfp_tosiz(int dp
)
1092 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1094 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1097 #define VFP_GEN_FIX(name) \
1098 static inline void gen_vfp_##name(int dp, int shift) \
1101 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1103 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1115 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1118 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1120 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1123 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1126 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1128 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1132 vfp_reg_offset (int dp
, int reg
)
1135 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1137 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1138 + offsetof(CPU_DoubleU
, l
.upper
);
1140 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1141 + offsetof(CPU_DoubleU
, l
.lower
);
1145 /* Return the offset of a 32-bit piece of a NEON register.
1146 zero is the least significant end of the register. */
1148 neon_reg_offset (int reg
, int n
)
1152 return vfp_reg_offset(0, sreg
);
1155 /* FIXME: Remove these. */
1156 #define neon_T0 cpu_T[0]
1157 #define neon_T1 cpu_T[1]
1158 #define NEON_GET_REG(T, reg, n) \
1159 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1160 #define NEON_SET_REG(T, reg, n) \
1161 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1163 static TCGv
neon_load_reg(int reg
, int pass
)
1165 TCGv tmp
= new_tmp();
1166 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1170 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1172 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1176 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1178 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1181 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1183 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1186 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1187 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1188 #define tcg_gen_st_f32 tcg_gen_st_i32
1189 #define tcg_gen_st_f64 tcg_gen_st_i64
1191 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1194 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1196 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1199 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1202 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1204 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1207 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1210 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1212 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1215 #define ARM_CP_RW_BIT (1 << 20)
1217 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1219 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1222 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1224 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1227 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1229 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1232 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1234 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1237 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1239 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1242 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1244 iwmmxt_store_reg(cpu_M0
, rn
);
1247 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1249 iwmmxt_load_reg(cpu_M0
, rn
);
1252 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1254 iwmmxt_load_reg(cpu_V1
, rn
);
1255 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1258 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1260 iwmmxt_load_reg(cpu_V1
, rn
);
1261 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1264 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1266 iwmmxt_load_reg(cpu_V1
, rn
);
1267 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1270 #define IWMMXT_OP(name) \
1271 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1273 iwmmxt_load_reg(cpu_V1, rn); \
1274 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1277 #define IWMMXT_OP_ENV(name) \
1278 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1280 iwmmxt_load_reg(cpu_V1, rn); \
1281 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1284 #define IWMMXT_OP_ENV_SIZE(name) \
1285 IWMMXT_OP_ENV(name##b) \
1286 IWMMXT_OP_ENV(name##w) \
1287 IWMMXT_OP_ENV(name##l)
1289 #define IWMMXT_OP_ENV1(name) \
1290 static inline void gen_op_iwmmxt_##name##_M0(void) \
1292 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1306 IWMMXT_OP_ENV_SIZE(unpackl
)
1307 IWMMXT_OP_ENV_SIZE(unpackh
)
1309 IWMMXT_OP_ENV1(unpacklub
)
1310 IWMMXT_OP_ENV1(unpackluw
)
1311 IWMMXT_OP_ENV1(unpacklul
)
1312 IWMMXT_OP_ENV1(unpackhub
)
1313 IWMMXT_OP_ENV1(unpackhuw
)
1314 IWMMXT_OP_ENV1(unpackhul
)
1315 IWMMXT_OP_ENV1(unpacklsb
)
1316 IWMMXT_OP_ENV1(unpacklsw
)
1317 IWMMXT_OP_ENV1(unpacklsl
)
1318 IWMMXT_OP_ENV1(unpackhsb
)
1319 IWMMXT_OP_ENV1(unpackhsw
)
1320 IWMMXT_OP_ENV1(unpackhsl
)
1322 IWMMXT_OP_ENV_SIZE(cmpeq
)
1323 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1324 IWMMXT_OP_ENV_SIZE(cmpgts
)
1326 IWMMXT_OP_ENV_SIZE(mins
)
1327 IWMMXT_OP_ENV_SIZE(minu
)
1328 IWMMXT_OP_ENV_SIZE(maxs
)
1329 IWMMXT_OP_ENV_SIZE(maxu
)
1331 IWMMXT_OP_ENV_SIZE(subn
)
1332 IWMMXT_OP_ENV_SIZE(addn
)
1333 IWMMXT_OP_ENV_SIZE(subu
)
1334 IWMMXT_OP_ENV_SIZE(addu
)
1335 IWMMXT_OP_ENV_SIZE(subs
)
1336 IWMMXT_OP_ENV_SIZE(adds
)
1338 IWMMXT_OP_ENV(avgb0
)
1339 IWMMXT_OP_ENV(avgb1
)
1340 IWMMXT_OP_ENV(avgw0
)
1341 IWMMXT_OP_ENV(avgw1
)
1345 IWMMXT_OP_ENV(packuw
)
1346 IWMMXT_OP_ENV(packul
)
1347 IWMMXT_OP_ENV(packuq
)
1348 IWMMXT_OP_ENV(packsw
)
1349 IWMMXT_OP_ENV(packsl
)
1350 IWMMXT_OP_ENV(packsq
)
1352 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1354 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1357 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1359 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1362 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1364 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1367 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1369 iwmmxt_load_reg(cpu_V1
, rn
);
1370 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1373 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1375 TCGv tmp
= tcg_const_i32(shift
);
1376 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1379 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1381 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1382 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1383 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1386 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1388 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1389 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1390 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1393 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1395 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1396 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1398 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1401 static void gen_op_iwmmxt_set_mup(void)
1404 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1405 tcg_gen_ori_i32(tmp
, tmp
, 2);
1406 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1409 static void gen_op_iwmmxt_set_cup(void)
1412 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1413 tcg_gen_ori_i32(tmp
, tmp
, 1);
1414 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1417 static void gen_op_iwmmxt_setpsr_nz(void)
1419 TCGv tmp
= new_tmp();
1420 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1421 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1424 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1426 iwmmxt_load_reg(cpu_V1
, rn
);
1427 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1428 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1432 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1434 iwmmxt_load_reg(cpu_V0
, rn
);
1435 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1436 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1437 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1440 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1442 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1443 iwmmxt_store_reg(cpu_V0
, rn
);
1446 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1451 rd
= (insn
>> 16) & 0xf;
1452 gen_movl_T1_reg(s
, rd
);
1454 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1455 if (insn
& (1 << 24)) {
1457 if (insn
& (1 << 23))
1458 gen_op_addl_T1_im(offset
);
1460 gen_op_addl_T1_im(-offset
);
1462 if (insn
& (1 << 21))
1463 gen_movl_reg_T1(s
, rd
);
1464 } else if (insn
& (1 << 21)) {
1466 if (insn
& (1 << 23))
1467 gen_op_movl_T0_im(offset
);
1469 gen_op_movl_T0_im(- offset
);
1470 gen_op_addl_T0_T1();
1471 gen_movl_reg_T0(s
, rd
);
1472 } else if (!(insn
& (1 << 23)))
1477 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1479 int rd
= (insn
>> 0) & 0xf;
1481 if (insn
& (1 << 8))
1482 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1485 gen_op_iwmmxt_movl_T0_wCx(rd
);
1487 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1489 gen_op_movl_T1_im(mask
);
1490 gen_op_andl_T0_T1();
1494 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1495 (ie. an undefined instruction). */
1496 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1499 int rdhi
, rdlo
, rd0
, rd1
, i
;
1502 if ((insn
& 0x0e000e00) == 0x0c000000) {
1503 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1505 rdlo
= (insn
>> 12) & 0xf;
1506 rdhi
= (insn
>> 16) & 0xf;
1507 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1508 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1509 gen_movl_reg_T0(s
, rdlo
);
1510 gen_movl_reg_T1(s
, rdhi
);
1511 } else { /* TMCRR */
1512 gen_movl_T0_reg(s
, rdlo
);
1513 gen_movl_T1_reg(s
, rdhi
);
1514 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1515 gen_op_iwmmxt_set_mup();
1520 wrd
= (insn
>> 12) & 0xf;
1521 if (gen_iwmmxt_address(s
, insn
))
1523 if (insn
& ARM_CP_RW_BIT
) {
1524 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1525 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1526 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1528 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1531 if (insn
& (1 << 8)) {
1532 if (insn
& (1 << 22)) { /* WLDRD */
1533 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1535 } else { /* WLDRW wRd */
1536 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1539 if (insn
& (1 << 22)) { /* WLDRH */
1540 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1541 } else { /* WLDRB */
1542 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1546 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1549 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1552 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1553 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1555 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1556 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1558 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1560 if (insn
& (1 << 8)) {
1561 if (insn
& (1 << 22)) { /* WSTRD */
1563 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1564 } else { /* WSTRW wRd */
1565 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1566 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1569 if (insn
& (1 << 22)) { /* WSTRH */
1570 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1571 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1572 } else { /* WSTRB */
1573 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1574 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1582 if ((insn
& 0x0f000000) != 0x0e000000)
1585 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1586 case 0x000: /* WOR */
1587 wrd
= (insn
>> 12) & 0xf;
1588 rd0
= (insn
>> 0) & 0xf;
1589 rd1
= (insn
>> 16) & 0xf;
1590 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1591 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1592 gen_op_iwmmxt_setpsr_nz();
1593 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1594 gen_op_iwmmxt_set_mup();
1595 gen_op_iwmmxt_set_cup();
1597 case 0x011: /* TMCR */
1600 rd
= (insn
>> 12) & 0xf;
1601 wrd
= (insn
>> 16) & 0xf;
1603 case ARM_IWMMXT_wCID
:
1604 case ARM_IWMMXT_wCASF
:
1606 case ARM_IWMMXT_wCon
:
1607 gen_op_iwmmxt_set_cup();
1609 case ARM_IWMMXT_wCSSF
:
1610 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1611 gen_movl_T1_reg(s
, rd
);
1612 gen_op_bicl_T0_T1();
1613 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1615 case ARM_IWMMXT_wCGR0
:
1616 case ARM_IWMMXT_wCGR1
:
1617 case ARM_IWMMXT_wCGR2
:
1618 case ARM_IWMMXT_wCGR3
:
1619 gen_op_iwmmxt_set_cup();
1620 gen_movl_reg_T0(s
, rd
);
1621 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1627 case 0x100: /* WXOR */
1628 wrd
= (insn
>> 12) & 0xf;
1629 rd0
= (insn
>> 0) & 0xf;
1630 rd1
= (insn
>> 16) & 0xf;
1631 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1632 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1633 gen_op_iwmmxt_setpsr_nz();
1634 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1635 gen_op_iwmmxt_set_mup();
1636 gen_op_iwmmxt_set_cup();
1638 case 0x111: /* TMRC */
1641 rd
= (insn
>> 12) & 0xf;
1642 wrd
= (insn
>> 16) & 0xf;
1643 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1644 gen_movl_reg_T0(s
, rd
);
1646 case 0x300: /* WANDN */
1647 wrd
= (insn
>> 12) & 0xf;
1648 rd0
= (insn
>> 0) & 0xf;
1649 rd1
= (insn
>> 16) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1651 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1652 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1653 gen_op_iwmmxt_setpsr_nz();
1654 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1655 gen_op_iwmmxt_set_mup();
1656 gen_op_iwmmxt_set_cup();
1658 case 0x200: /* WAND */
1659 wrd
= (insn
>> 12) & 0xf;
1660 rd0
= (insn
>> 0) & 0xf;
1661 rd1
= (insn
>> 16) & 0xf;
1662 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1663 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1664 gen_op_iwmmxt_setpsr_nz();
1665 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1666 gen_op_iwmmxt_set_mup();
1667 gen_op_iwmmxt_set_cup();
1669 case 0x810: case 0xa10: /* WMADD */
1670 wrd
= (insn
>> 12) & 0xf;
1671 rd0
= (insn
>> 0) & 0xf;
1672 rd1
= (insn
>> 16) & 0xf;
1673 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1674 if (insn
& (1 << 21))
1675 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1677 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1678 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1679 gen_op_iwmmxt_set_mup();
1681 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1682 wrd
= (insn
>> 12) & 0xf;
1683 rd0
= (insn
>> 16) & 0xf;
1684 rd1
= (insn
>> 0) & 0xf;
1685 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1686 switch ((insn
>> 22) & 3) {
1688 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1691 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1694 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1699 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1700 gen_op_iwmmxt_set_mup();
1701 gen_op_iwmmxt_set_cup();
1703 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1704 wrd
= (insn
>> 12) & 0xf;
1705 rd0
= (insn
>> 16) & 0xf;
1706 rd1
= (insn
>> 0) & 0xf;
1707 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1708 switch ((insn
>> 22) & 3) {
1710 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1713 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1716 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1721 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1722 gen_op_iwmmxt_set_mup();
1723 gen_op_iwmmxt_set_cup();
1725 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1726 wrd
= (insn
>> 12) & 0xf;
1727 rd0
= (insn
>> 16) & 0xf;
1728 rd1
= (insn
>> 0) & 0xf;
1729 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1730 if (insn
& (1 << 22))
1731 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1733 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1734 if (!(insn
& (1 << 20)))
1735 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1736 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1737 gen_op_iwmmxt_set_mup();
1739 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1740 wrd
= (insn
>> 12) & 0xf;
1741 rd0
= (insn
>> 16) & 0xf;
1742 rd1
= (insn
>> 0) & 0xf;
1743 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1744 if (insn
& (1 << 21)) {
1745 if (insn
& (1 << 20))
1746 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1748 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1750 if (insn
& (1 << 20))
1751 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1753 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1755 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1756 gen_op_iwmmxt_set_mup();
1758 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1759 wrd
= (insn
>> 12) & 0xf;
1760 rd0
= (insn
>> 16) & 0xf;
1761 rd1
= (insn
>> 0) & 0xf;
1762 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1763 if (insn
& (1 << 21))
1764 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1766 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1767 if (!(insn
& (1 << 20))) {
1768 iwmmxt_load_reg(cpu_V1
, wrd
);
1769 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1771 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1772 gen_op_iwmmxt_set_mup();
1774 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1775 wrd
= (insn
>> 12) & 0xf;
1776 rd0
= (insn
>> 16) & 0xf;
1777 rd1
= (insn
>> 0) & 0xf;
1778 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1779 switch ((insn
>> 22) & 3) {
1781 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1784 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1787 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1792 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1793 gen_op_iwmmxt_set_mup();
1794 gen_op_iwmmxt_set_cup();
1796 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1797 wrd
= (insn
>> 12) & 0xf;
1798 rd0
= (insn
>> 16) & 0xf;
1799 rd1
= (insn
>> 0) & 0xf;
1800 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1801 if (insn
& (1 << 22)) {
1802 if (insn
& (1 << 20))
1803 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1805 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1807 if (insn
& (1 << 20))
1808 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1810 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1812 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1813 gen_op_iwmmxt_set_mup();
1814 gen_op_iwmmxt_set_cup();
1816 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1817 wrd
= (insn
>> 12) & 0xf;
1818 rd0
= (insn
>> 16) & 0xf;
1819 rd1
= (insn
>> 0) & 0xf;
1820 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1821 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1822 gen_op_movl_T1_im(7);
1823 gen_op_andl_T0_T1();
1824 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1825 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1826 gen_op_iwmmxt_set_mup();
1828 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1829 rd
= (insn
>> 12) & 0xf;
1830 wrd
= (insn
>> 16) & 0xf;
1831 gen_movl_T0_reg(s
, rd
);
1832 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1833 switch ((insn
>> 6) & 3) {
1835 gen_op_movl_T1_im(0xff);
1836 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1839 gen_op_movl_T1_im(0xffff);
1840 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1843 gen_op_movl_T1_im(0xffffffff);
1844 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1849 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1850 gen_op_iwmmxt_set_mup();
1852 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1853 rd
= (insn
>> 12) & 0xf;
1854 wrd
= (insn
>> 16) & 0xf;
1857 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1858 switch ((insn
>> 22) & 3) {
1861 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1863 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1868 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1870 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1874 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1879 gen_movl_reg_T0(s
, rd
);
1881 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1882 if ((insn
& 0x000ff008) != 0x0003f000)
1884 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1885 switch ((insn
>> 22) & 3) {
1887 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1890 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1893 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1898 gen_op_shll_T1_im(28);
1899 gen_set_nzcv(cpu_T
[1]);
1901 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1902 rd
= (insn
>> 12) & 0xf;
1903 wrd
= (insn
>> 16) & 0xf;
1904 gen_movl_T0_reg(s
, rd
);
1905 switch ((insn
>> 6) & 3) {
1907 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1910 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1913 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1918 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1919 gen_op_iwmmxt_set_mup();
1921 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1922 if ((insn
& 0x000ff00f) != 0x0003f000)
1924 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1925 switch ((insn
>> 22) & 3) {
1927 for (i
= 0; i
< 7; i
++) {
1928 gen_op_shll_T1_im(4);
1929 gen_op_andl_T0_T1();
1933 for (i
= 0; i
< 3; i
++) {
1934 gen_op_shll_T1_im(8);
1935 gen_op_andl_T0_T1();
1939 gen_op_shll_T1_im(16);
1940 gen_op_andl_T0_T1();
1945 gen_set_nzcv(cpu_T
[0]);
1947 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1948 wrd
= (insn
>> 12) & 0xf;
1949 rd0
= (insn
>> 16) & 0xf;
1950 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1951 switch ((insn
>> 22) & 3) {
1953 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1956 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1959 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1964 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1965 gen_op_iwmmxt_set_mup();
1967 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1968 if ((insn
& 0x000ff00f) != 0x0003f000)
1970 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1971 switch ((insn
>> 22) & 3) {
1973 for (i
= 0; i
< 7; i
++) {
1974 gen_op_shll_T1_im(4);
1979 for (i
= 0; i
< 3; i
++) {
1980 gen_op_shll_T1_im(8);
1985 gen_op_shll_T1_im(16);
1991 gen_set_nzcv(cpu_T
[0]);
1993 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1994 rd
= (insn
>> 12) & 0xf;
1995 rd0
= (insn
>> 16) & 0xf;
1996 if ((insn
& 0xf) != 0)
1998 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1999 switch ((insn
>> 22) & 3) {
2001 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
2004 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
2007 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
2012 gen_movl_reg_T0(s
, rd
);
2014 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2015 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2016 wrd
= (insn
>> 12) & 0xf;
2017 rd0
= (insn
>> 16) & 0xf;
2018 rd1
= (insn
>> 0) & 0xf;
2019 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2020 switch ((insn
>> 22) & 3) {
2022 if (insn
& (1 << 21))
2023 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2025 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2028 if (insn
& (1 << 21))
2029 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2031 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2034 if (insn
& (1 << 21))
2035 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2037 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2042 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2043 gen_op_iwmmxt_set_mup();
2044 gen_op_iwmmxt_set_cup();
2046 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2047 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2048 wrd
= (insn
>> 12) & 0xf;
2049 rd0
= (insn
>> 16) & 0xf;
2050 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2051 switch ((insn
>> 22) & 3) {
2053 if (insn
& (1 << 21))
2054 gen_op_iwmmxt_unpacklsb_M0();
2056 gen_op_iwmmxt_unpacklub_M0();
2059 if (insn
& (1 << 21))
2060 gen_op_iwmmxt_unpacklsw_M0();
2062 gen_op_iwmmxt_unpackluw_M0();
2065 if (insn
& (1 << 21))
2066 gen_op_iwmmxt_unpacklsl_M0();
2068 gen_op_iwmmxt_unpacklul_M0();
2073 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2074 gen_op_iwmmxt_set_mup();
2075 gen_op_iwmmxt_set_cup();
2077 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2078 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2079 wrd
= (insn
>> 12) & 0xf;
2080 rd0
= (insn
>> 16) & 0xf;
2081 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2082 switch ((insn
>> 22) & 3) {
2084 if (insn
& (1 << 21))
2085 gen_op_iwmmxt_unpackhsb_M0();
2087 gen_op_iwmmxt_unpackhub_M0();
2090 if (insn
& (1 << 21))
2091 gen_op_iwmmxt_unpackhsw_M0();
2093 gen_op_iwmmxt_unpackhuw_M0();
2096 if (insn
& (1 << 21))
2097 gen_op_iwmmxt_unpackhsl_M0();
2099 gen_op_iwmmxt_unpackhul_M0();
2104 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2105 gen_op_iwmmxt_set_mup();
2106 gen_op_iwmmxt_set_cup();
2108 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2109 case 0x214: case 0x614: case 0xa14: case 0xe14:
2110 wrd
= (insn
>> 12) & 0xf;
2111 rd0
= (insn
>> 16) & 0xf;
2112 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2113 if (gen_iwmmxt_shift(insn
, 0xff))
2115 switch ((insn
>> 22) & 3) {
2119 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2122 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2125 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2128 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2129 gen_op_iwmmxt_set_mup();
2130 gen_op_iwmmxt_set_cup();
2132 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2133 case 0x014: case 0x414: case 0x814: case 0xc14:
2134 wrd
= (insn
>> 12) & 0xf;
2135 rd0
= (insn
>> 16) & 0xf;
2136 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2137 if (gen_iwmmxt_shift(insn
, 0xff))
2139 switch ((insn
>> 22) & 3) {
2143 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2146 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2149 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2152 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2153 gen_op_iwmmxt_set_mup();
2154 gen_op_iwmmxt_set_cup();
2156 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2157 case 0x114: case 0x514: case 0x914: case 0xd14:
2158 wrd
= (insn
>> 12) & 0xf;
2159 rd0
= (insn
>> 16) & 0xf;
2160 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2161 if (gen_iwmmxt_shift(insn
, 0xff))
2163 switch ((insn
>> 22) & 3) {
2167 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2170 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2173 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2176 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2177 gen_op_iwmmxt_set_mup();
2178 gen_op_iwmmxt_set_cup();
2180 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2181 case 0x314: case 0x714: case 0xb14: case 0xf14:
2182 wrd
= (insn
>> 12) & 0xf;
2183 rd0
= (insn
>> 16) & 0xf;
2184 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2185 switch ((insn
>> 22) & 3) {
2189 if (gen_iwmmxt_shift(insn
, 0xf))
2191 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2194 if (gen_iwmmxt_shift(insn
, 0x1f))
2196 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2199 if (gen_iwmmxt_shift(insn
, 0x3f))
2201 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2204 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2205 gen_op_iwmmxt_set_mup();
2206 gen_op_iwmmxt_set_cup();
2208 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2209 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2210 wrd
= (insn
>> 12) & 0xf;
2211 rd0
= (insn
>> 16) & 0xf;
2212 rd1
= (insn
>> 0) & 0xf;
2213 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2214 switch ((insn
>> 22) & 3) {
2216 if (insn
& (1 << 21))
2217 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2219 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2222 if (insn
& (1 << 21))
2223 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2225 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2228 if (insn
& (1 << 21))
2229 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2231 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2236 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2237 gen_op_iwmmxt_set_mup();
2239 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2240 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2241 wrd
= (insn
>> 12) & 0xf;
2242 rd0
= (insn
>> 16) & 0xf;
2243 rd1
= (insn
>> 0) & 0xf;
2244 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2245 switch ((insn
>> 22) & 3) {
2247 if (insn
& (1 << 21))
2248 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2250 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2253 if (insn
& (1 << 21))
2254 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2256 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2259 if (insn
& (1 << 21))
2260 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2262 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2267 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2268 gen_op_iwmmxt_set_mup();
2270 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2271 case 0x402: case 0x502: case 0x602: case 0x702:
2272 wrd
= (insn
>> 12) & 0xf;
2273 rd0
= (insn
>> 16) & 0xf;
2274 rd1
= (insn
>> 0) & 0xf;
2275 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2276 gen_op_movl_T0_im((insn
>> 20) & 3);
2277 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2278 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2279 gen_op_iwmmxt_set_mup();
2281 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2282 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2283 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2284 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2285 wrd
= (insn
>> 12) & 0xf;
2286 rd0
= (insn
>> 16) & 0xf;
2287 rd1
= (insn
>> 0) & 0xf;
2288 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2289 switch ((insn
>> 20) & 0xf) {
2291 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2294 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2297 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2300 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2303 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2306 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2309 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2312 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2315 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2320 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2321 gen_op_iwmmxt_set_mup();
2322 gen_op_iwmmxt_set_cup();
2324 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2325 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2326 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2327 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2328 wrd
= (insn
>> 12) & 0xf;
2329 rd0
= (insn
>> 16) & 0xf;
2330 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2331 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2332 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2333 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2334 gen_op_iwmmxt_set_mup();
2335 gen_op_iwmmxt_set_cup();
2337 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2338 case 0x418: case 0x518: case 0x618: case 0x718:
2339 case 0x818: case 0x918: case 0xa18: case 0xb18:
2340 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2341 wrd
= (insn
>> 12) & 0xf;
2342 rd0
= (insn
>> 16) & 0xf;
2343 rd1
= (insn
>> 0) & 0xf;
2344 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2345 switch ((insn
>> 20) & 0xf) {
2347 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2350 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2353 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2356 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2359 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2362 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2365 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2368 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2371 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2376 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2377 gen_op_iwmmxt_set_mup();
2378 gen_op_iwmmxt_set_cup();
2380 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2381 case 0x408: case 0x508: case 0x608: case 0x708:
2382 case 0x808: case 0x908: case 0xa08: case 0xb08:
2383 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2384 wrd
= (insn
>> 12) & 0xf;
2385 rd0
= (insn
>> 16) & 0xf;
2386 rd1
= (insn
>> 0) & 0xf;
2387 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2388 if (!(insn
& (1 << 20)))
2390 switch ((insn
>> 22) & 3) {
2394 if (insn
& (1 << 21))
2395 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2397 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2400 if (insn
& (1 << 21))
2401 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2403 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2406 if (insn
& (1 << 21))
2407 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2409 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2412 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2413 gen_op_iwmmxt_set_mup();
2414 gen_op_iwmmxt_set_cup();
2416 case 0x201: case 0x203: case 0x205: case 0x207:
2417 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2418 case 0x211: case 0x213: case 0x215: case 0x217:
2419 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2420 wrd
= (insn
>> 5) & 0xf;
2421 rd0
= (insn
>> 12) & 0xf;
2422 rd1
= (insn
>> 0) & 0xf;
2423 if (rd0
== 0xf || rd1
== 0xf)
2425 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2426 switch ((insn
>> 16) & 0xf) {
2427 case 0x0: /* TMIA */
2428 gen_movl_T0_reg(s
, rd0
);
2429 gen_movl_T1_reg(s
, rd1
);
2430 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2432 case 0x8: /* TMIAPH */
2433 gen_movl_T0_reg(s
, rd0
);
2434 gen_movl_T1_reg(s
, rd1
);
2435 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2437 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2438 gen_movl_T1_reg(s
, rd0
);
2439 if (insn
& (1 << 16))
2440 gen_op_shrl_T1_im(16);
2441 gen_op_movl_T0_T1();
2442 gen_movl_T1_reg(s
, rd1
);
2443 if (insn
& (1 << 17))
2444 gen_op_shrl_T1_im(16);
2445 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2450 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2451 gen_op_iwmmxt_set_mup();
2460 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2461 (ie. an undefined instruction). */
2462 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2464 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2466 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2467 /* Multiply with Internal Accumulate Format */
2468 rd0
= (insn
>> 12) & 0xf;
2470 acc
= (insn
>> 5) & 7;
2475 switch ((insn
>> 16) & 0xf) {
2477 gen_movl_T0_reg(s
, rd0
);
2478 gen_movl_T1_reg(s
, rd1
);
2479 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2481 case 0x8: /* MIAPH */
2482 gen_movl_T0_reg(s
, rd0
);
2483 gen_movl_T1_reg(s
, rd1
);
2484 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2486 case 0xc: /* MIABB */
2487 case 0xd: /* MIABT */
2488 case 0xe: /* MIATB */
2489 case 0xf: /* MIATT */
2490 gen_movl_T1_reg(s
, rd0
);
2491 if (insn
& (1 << 16))
2492 gen_op_shrl_T1_im(16);
2493 gen_op_movl_T0_T1();
2494 gen_movl_T1_reg(s
, rd1
);
2495 if (insn
& (1 << 17))
2496 gen_op_shrl_T1_im(16);
2497 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2503 gen_op_iwmmxt_movq_wRn_M0(acc
);
2507 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2508 /* Internal Accumulator Access Format */
2509 rdhi
= (insn
>> 16) & 0xf;
2510 rdlo
= (insn
>> 12) & 0xf;
2516 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2517 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2518 gen_movl_reg_T0(s
, rdlo
);
2519 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2520 gen_op_andl_T0_T1();
2521 gen_movl_reg_T0(s
, rdhi
);
2523 gen_movl_T0_reg(s
, rdlo
);
2524 gen_movl_T1_reg(s
, rdhi
);
2525 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2533 /* Disassemble system coprocessor instruction. Return nonzero if
2534 instruction is not defined. */
2535 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2538 uint32_t rd
= (insn
>> 12) & 0xf;
2539 uint32_t cp
= (insn
>> 8) & 0xf;
2544 if (insn
& ARM_CP_RW_BIT
) {
2545 if (!env
->cp
[cp
].cp_read
)
2547 gen_set_pc_im(s
->pc
);
2549 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2550 store_reg(s
, rd
, tmp
);
2552 if (!env
->cp
[cp
].cp_write
)
2554 gen_set_pc_im(s
->pc
);
2555 tmp
= load_reg(s
, rd
);
2556 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2562 static int cp15_user_ok(uint32_t insn
)
2564 int cpn
= (insn
>> 16) & 0xf;
2565 int cpm
= insn
& 0xf;
2566 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2568 if (cpn
== 13 && cpm
== 0) {
2570 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2574 /* ISB, DSB, DMB. */
2575 if ((cpm
== 5 && op
== 4)
2576 || (cpm
== 10 && (op
== 4 || op
== 5)))
2582 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2583 instruction is not defined. */
2584 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2589 /* M profile cores use memory mapped registers instead of cp15. */
2590 if (arm_feature(env
, ARM_FEATURE_M
))
2593 if ((insn
& (1 << 25)) == 0) {
2594 if (insn
& (1 << 20)) {
2598 /* mcrr. Used for block cache operations, so implement as no-op. */
2601 if ((insn
& (1 << 4)) == 0) {
2605 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2608 if ((insn
& 0x0fff0fff) == 0x0e070f90
2609 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2610 /* Wait for interrupt. */
2611 gen_set_pc_im(s
->pc
);
2612 s
->is_jmp
= DISAS_WFI
;
2615 rd
= (insn
>> 12) & 0xf;
2616 if (insn
& ARM_CP_RW_BIT
) {
2618 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2619 /* If the destination register is r15 then sets condition codes. */
2621 store_reg(s
, rd
, tmp
);
2625 tmp
= load_reg(s
, rd
);
2626 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2628 /* Normally we would always end the TB here, but Linux
2629 * arch/arm/mach-pxa/sleep.S expects two instructions following
2630 * an MMU enable to execute from cache. Imitate this behaviour. */
2631 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2632 (insn
& 0x0fff0fff) != 0x0e010f10)
2638 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2639 #define VFP_SREG(insn, bigbit, smallbit) \
2640 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2641 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2642 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2643 reg = (((insn) >> (bigbit)) & 0x0f) \
2644 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2646 if (insn & (1 << (smallbit))) \
2648 reg = ((insn) >> (bigbit)) & 0x0f; \
2651 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2652 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2653 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2654 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2655 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2656 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2658 /* Move between integer and VFP cores. */
2659 static TCGv
gen_vfp_mrs(void)
2661 TCGv tmp
= new_tmp();
2662 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2666 static void gen_vfp_msr(TCGv tmp
)
2668 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2673 vfp_enabled(CPUState
* env
)
2675 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2678 static void gen_neon_dup_u8(TCGv var
, int shift
)
2680 TCGv tmp
= new_tmp();
2682 tcg_gen_shri_i32(var
, var
, shift
);
2683 tcg_gen_ext8u_i32(var
, var
);
2684 tcg_gen_shli_i32(tmp
, var
, 8);
2685 tcg_gen_or_i32(var
, var
, tmp
);
2686 tcg_gen_shli_i32(tmp
, var
, 16);
2687 tcg_gen_or_i32(var
, var
, tmp
);
2691 static void gen_neon_dup_low16(TCGv var
)
2693 TCGv tmp
= new_tmp();
2694 tcg_gen_ext16u_i32(var
, var
);
2695 tcg_gen_shli_i32(tmp
, var
, 16);
2696 tcg_gen_or_i32(var
, var
, tmp
);
2700 static void gen_neon_dup_high16(TCGv var
)
2702 TCGv tmp
= new_tmp();
2703 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2704 tcg_gen_shri_i32(tmp
, var
, 16);
2705 tcg_gen_or_i32(var
, var
, tmp
);
2709 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2710 (ie. an undefined instruction). */
2711 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2713 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2718 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2721 if (!vfp_enabled(env
)) {
2722 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2723 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2725 rn
= (insn
>> 16) & 0xf;
2726 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2727 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2730 dp
= ((insn
& 0xf00) == 0xb00);
2731 switch ((insn
>> 24) & 0xf) {
2733 if (insn
& (1 << 4)) {
2734 /* single register transfer */
2735 rd
= (insn
>> 12) & 0xf;
2740 VFP_DREG_N(rn
, insn
);
2743 if (insn
& 0x00c00060
2744 && !arm_feature(env
, ARM_FEATURE_NEON
))
2747 pass
= (insn
>> 21) & 1;
2748 if (insn
& (1 << 22)) {
2750 offset
= ((insn
>> 5) & 3) * 8;
2751 } else if (insn
& (1 << 5)) {
2753 offset
= (insn
& (1 << 6)) ? 16 : 0;
2758 if (insn
& ARM_CP_RW_BIT
) {
2760 tmp
= neon_load_reg(rn
, pass
);
2764 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2765 if (insn
& (1 << 23))
2771 if (insn
& (1 << 23)) {
2773 tcg_gen_shri_i32(tmp
, tmp
, 16);
2779 tcg_gen_sari_i32(tmp
, tmp
, 16);
2788 store_reg(s
, rd
, tmp
);
2791 tmp
= load_reg(s
, rd
);
2792 if (insn
& (1 << 23)) {
2795 gen_neon_dup_u8(tmp
, 0);
2796 } else if (size
== 1) {
2797 gen_neon_dup_low16(tmp
);
2799 for (n
= 0; n
<= pass
* 2; n
++) {
2801 tcg_gen_mov_i32(tmp2
, tmp
);
2802 neon_store_reg(rn
, n
, tmp2
);
2804 neon_store_reg(rn
, n
, tmp
);
2809 tmp2
= neon_load_reg(rn
, pass
);
2810 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2814 tmp2
= neon_load_reg(rn
, pass
);
2815 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2821 neon_store_reg(rn
, pass
, tmp
);
2825 if ((insn
& 0x6f) != 0x00)
2827 rn
= VFP_SREG_N(insn
);
2828 if (insn
& ARM_CP_RW_BIT
) {
2830 if (insn
& (1 << 21)) {
2831 /* system register */
2836 /* VFP2 allows access to FSID from userspace.
2837 VFP3 restricts all id registers to privileged
2840 && arm_feature(env
, ARM_FEATURE_VFP3
))
2842 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2847 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2849 case ARM_VFP_FPINST
:
2850 case ARM_VFP_FPINST2
:
2851 /* Not present in VFP3. */
2853 || arm_feature(env
, ARM_FEATURE_VFP3
))
2855 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2859 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2860 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2863 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2869 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2871 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2877 gen_mov_F0_vreg(0, rn
);
2878 tmp
= gen_vfp_mrs();
2881 /* Set the 4 flag bits in the CPSR. */
2885 store_reg(s
, rd
, tmp
);
2889 tmp
= load_reg(s
, rd
);
2890 if (insn
& (1 << 21)) {
2892 /* system register */
2897 /* Writes are ignored. */
2900 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2907 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2910 case ARM_VFP_FPINST
:
2911 case ARM_VFP_FPINST2
:
2912 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2919 gen_mov_vreg_F0(0, rn
);
2924 /* data processing */
2925 /* The opcode is in bits 23, 21, 20 and 6. */
2926 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2930 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2932 /* rn is register number */
2933 VFP_DREG_N(rn
, insn
);
2936 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2937 /* Integer or single precision destination. */
2938 rd
= VFP_SREG_D(insn
);
2940 VFP_DREG_D(rd
, insn
);
2943 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2944 /* Integer source. */
2945 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2947 VFP_DREG_M(rm
, insn
);
2950 rn
= VFP_SREG_N(insn
);
2951 if (op
== 15 && rn
== 15) {
2952 /* Double precision destination. */
2953 VFP_DREG_D(rd
, insn
);
2955 rd
= VFP_SREG_D(insn
);
2957 rm
= VFP_SREG_M(insn
);
2960 veclen
= env
->vfp
.vec_len
;
2961 if (op
== 15 && rn
> 3)
2964 /* Shut up compiler warnings. */
2975 /* Figure out what type of vector operation this is. */
2976 if ((rd
& bank_mask
) == 0) {
2981 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2983 delta_d
= env
->vfp
.vec_stride
+ 1;
2985 if ((rm
& bank_mask
) == 0) {
2986 /* mixed scalar/vector */
2995 /* Load the initial operands. */
3000 /* Integer source */
3001 gen_mov_F0_vreg(0, rm
);
3006 gen_mov_F0_vreg(dp
, rd
);
3007 gen_mov_F1_vreg(dp
, rm
);
3011 /* Compare with zero */
3012 gen_mov_F0_vreg(dp
, rd
);
3023 /* Source and destination the same. */
3024 gen_mov_F0_vreg(dp
, rd
);
3027 /* One source operand. */
3028 gen_mov_F0_vreg(dp
, rm
);
3032 /* Two source operands. */
3033 gen_mov_F0_vreg(dp
, rn
);
3034 gen_mov_F1_vreg(dp
, rm
);
3038 /* Perform the calculation. */
3040 case 0: /* mac: fd + (fn * fm) */
3042 gen_mov_F1_vreg(dp
, rd
);
3045 case 1: /* nmac: fd - (fn * fm) */
3048 gen_mov_F1_vreg(dp
, rd
);
3051 case 2: /* msc: -fd + (fn * fm) */
3053 gen_mov_F1_vreg(dp
, rd
);
3056 case 3: /* nmsc: -fd - (fn * fm) */
3059 gen_mov_F1_vreg(dp
, rd
);
3062 case 4: /* mul: fn * fm */
3065 case 5: /* nmul: -(fn * fm) */
3069 case 6: /* add: fn + fm */
3072 case 7: /* sub: fn - fm */
3075 case 8: /* div: fn / fm */
3078 case 14: /* fconst */
3079 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3082 n
= (insn
<< 12) & 0x80000000;
3083 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3090 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3097 tcg_gen_movi_i32(cpu_F0s
, n
);
3100 case 15: /* extension space */
3123 case 11: /* cmpez */
3127 case 15: /* single<->double conversion */
3129 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3131 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3133 case 16: /* fuito */
3136 case 17: /* fsito */
3139 case 20: /* fshto */
3140 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3142 gen_vfp_shto(dp
, 16 - rm
);
3144 case 21: /* fslto */
3145 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3147 gen_vfp_slto(dp
, 32 - rm
);
3149 case 22: /* fuhto */
3150 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3152 gen_vfp_uhto(dp
, 16 - rm
);
3154 case 23: /* fulto */
3155 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3157 gen_vfp_ulto(dp
, 32 - rm
);
3159 case 24: /* ftoui */
3162 case 25: /* ftouiz */
3165 case 26: /* ftosi */
3168 case 27: /* ftosiz */
3171 case 28: /* ftosh */
3172 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3174 gen_vfp_tosh(dp
, 16 - rm
);
3176 case 29: /* ftosl */
3177 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3179 gen_vfp_tosl(dp
, 32 - rm
);
3181 case 30: /* ftouh */
3182 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3184 gen_vfp_touh(dp
, 16 - rm
);
3186 case 31: /* ftoul */
3187 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3189 gen_vfp_toul(dp
, 32 - rm
);
3191 default: /* undefined */
3192 printf ("rn:%d\n", rn
);
3196 default: /* undefined */
3197 printf ("op:%d\n", op
);
3201 /* Write back the result. */
3202 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3203 ; /* Comparison, do nothing. */
3204 else if (op
== 15 && rn
> 17)
3205 /* Integer result. */
3206 gen_mov_vreg_F0(0, rd
);
3207 else if (op
== 15 && rn
== 15)
3209 gen_mov_vreg_F0(!dp
, rd
);
3211 gen_mov_vreg_F0(dp
, rd
);
3213 /* break out of the loop if we have finished */
3217 if (op
== 15 && delta_m
== 0) {
3218 /* single source one-many */
3220 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3222 gen_mov_vreg_F0(dp
, rd
);
3226 /* Setup the next operands. */
3228 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3232 /* One source operand. */
3233 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3235 gen_mov_F0_vreg(dp
, rm
);
3237 /* Two source operands. */
3238 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3240 gen_mov_F0_vreg(dp
, rn
);
3242 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3244 gen_mov_F1_vreg(dp
, rm
);
3252 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3253 /* two-register transfer */
3254 rn
= (insn
>> 16) & 0xf;
3255 rd
= (insn
>> 12) & 0xf;
3257 VFP_DREG_M(rm
, insn
);
3259 rm
= VFP_SREG_M(insn
);
3262 if (insn
& ARM_CP_RW_BIT
) {
3265 gen_mov_F0_vreg(0, rm
* 2);
3266 tmp
= gen_vfp_mrs();
3267 store_reg(s
, rd
, tmp
);
3268 gen_mov_F0_vreg(0, rm
* 2 + 1);
3269 tmp
= gen_vfp_mrs();
3270 store_reg(s
, rn
, tmp
);
3272 gen_mov_F0_vreg(0, rm
);
3273 tmp
= gen_vfp_mrs();
3274 store_reg(s
, rn
, tmp
);
3275 gen_mov_F0_vreg(0, rm
+ 1);
3276 tmp
= gen_vfp_mrs();
3277 store_reg(s
, rd
, tmp
);
3282 tmp
= load_reg(s
, rd
);
3284 gen_mov_vreg_F0(0, rm
* 2);
3285 tmp
= load_reg(s
, rn
);
3287 gen_mov_vreg_F0(0, rm
* 2 + 1);
3289 tmp
= load_reg(s
, rn
);
3291 gen_mov_vreg_F0(0, rm
);
3292 tmp
= load_reg(s
, rd
);
3294 gen_mov_vreg_F0(0, rm
+ 1);
3299 rn
= (insn
>> 16) & 0xf;
3301 VFP_DREG_D(rd
, insn
);
3303 rd
= VFP_SREG_D(insn
);
3304 if (s
->thumb
&& rn
== 15) {
3305 gen_op_movl_T1_im(s
->pc
& ~2);
3307 gen_movl_T1_reg(s
, rn
);
3309 if ((insn
& 0x01200000) == 0x01000000) {
3310 /* Single load/store */
3311 offset
= (insn
& 0xff) << 2;
3312 if ((insn
& (1 << 23)) == 0)
3314 gen_op_addl_T1_im(offset
);
3315 if (insn
& (1 << 20)) {
3317 gen_mov_vreg_F0(dp
, rd
);
3319 gen_mov_F0_vreg(dp
, rd
);
3323 /* load/store multiple */
3325 n
= (insn
>> 1) & 0x7f;
3329 if (insn
& (1 << 24)) /* pre-decrement */
3330 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3336 for (i
= 0; i
< n
; i
++) {
3337 if (insn
& ARM_CP_RW_BIT
) {
3340 gen_mov_vreg_F0(dp
, rd
+ i
);
3343 gen_mov_F0_vreg(dp
, rd
+ i
);
3346 gen_op_addl_T1_im(offset
);
3348 if (insn
& (1 << 21)) {
3350 if (insn
& (1 << 24))
3351 offset
= -offset
* n
;
3352 else if (dp
&& (insn
& 1))
3358 gen_op_addl_T1_im(offset
);
3359 gen_movl_reg_T1(s
, rn
);
3365 /* Should never happen. */
3371 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3373 TranslationBlock
*tb
;
3376 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3378 gen_set_pc_im(dest
);
3379 tcg_gen_exit_tb((long)tb
+ n
);
3381 gen_set_pc_im(dest
);
3386 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3388 if (unlikely(s
->singlestep_enabled
)) {
3389 /* An indirect jump so that we still trigger the debug exception. */
3394 gen_goto_tb(s
, 0, dest
);
3395 s
->is_jmp
= DISAS_TB_JUMP
;
3399 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3402 tcg_gen_sari_i32(t0
, t0
, 16);
3406 tcg_gen_sari_i32(t1
, t1
, 16);
3409 tcg_gen_mul_i32(t0
, t0
, t1
);
3412 /* Return the mask of PSR bits set by a MSR instruction. */
3413 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3417 if (flags
& (1 << 0))
3419 if (flags
& (1 << 1))
3421 if (flags
& (1 << 2))
3423 if (flags
& (1 << 3))
3426 /* Mask out undefined bits. */
3427 mask
&= ~CPSR_RESERVED
;
3428 if (!arm_feature(env
, ARM_FEATURE_V6
))
3429 mask
&= ~(CPSR_E
| CPSR_GE
);
3430 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3432 /* Mask out execution state bits. */
3435 /* Mask out privileged bits. */
3441 /* Returns nonzero if access to the PSR is not permitted. */
3442 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3446 /* ??? This is also undefined in system mode. */
3450 tmp
= load_cpu_field(spsr
);
3451 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3452 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3453 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3454 store_cpu_field(tmp
, spsr
);
3456 gen_set_cpsr(cpu_T
[0], mask
);
3462 /* Generate an old-style exception return. Marks pc as dead. */
3463 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3466 store_reg(s
, 15, pc
);
3467 tmp
= load_cpu_field(spsr
);
3468 gen_set_cpsr(tmp
, 0xffffffff);
3470 s
->is_jmp
= DISAS_UPDATE
;
3473 /* Generate a v6 exception return. Marks both values as dead. */
3474 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3476 gen_set_cpsr(cpsr
, 0xffffffff);
3478 store_reg(s
, 15, pc
);
3479 s
->is_jmp
= DISAS_UPDATE
;
3483 gen_set_condexec (DisasContext
*s
)
3485 if (s
->condexec_mask
) {
3486 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3487 TCGv tmp
= new_tmp();
3488 tcg_gen_movi_i32(tmp
, val
);
3489 store_cpu_field(tmp
, condexec_bits
);
3493 static void gen_nop_hint(DisasContext
*s
, int val
)
3497 gen_set_pc_im(s
->pc
);
3498 s
->is_jmp
= DISAS_WFI
;
3502 /* TODO: Implement SEV and WFE. May help SMP performance. */
3508 /* These macros help make the code more readable when migrating from the
3509 old dyngen helpers. They should probably be removed when
3510 T0/T1 are removed. */
3511 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3512 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3514 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3516 static inline int gen_neon_add(int size
)
3519 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3520 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3521 case 2: gen_op_addl_T0_T1(); break;
3527 static inline void gen_neon_rsb(int size
)
3530 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3531 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3532 case 2: gen_op_rsbl_T0_T1(); break;
3537 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3538 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3539 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3540 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3541 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3543 /* FIXME: This is wrong. They set the wrong overflow bit. */
3544 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3545 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3546 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3547 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3549 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3550 switch ((size << 1) | u) { \
3552 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3555 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3558 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3561 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3564 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3567 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3569 default: return 1; \
3572 #define GEN_NEON_INTEGER_OP(name) do { \
3573 switch ((size << 1) | u) { \
3575 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3578 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3581 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3584 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3587 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3590 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3592 default: return 1; \
3596 gen_neon_movl_scratch_T0(int scratch
)
3600 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3601 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3605 gen_neon_movl_scratch_T1(int scratch
)
3609 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3610 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3614 gen_neon_movl_T0_scratch(int scratch
)
3618 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3619 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3623 gen_neon_movl_T1_scratch(int scratch
)
3627 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3628 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3631 static inline void gen_neon_get_scalar(int size
, int reg
)
3634 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3636 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3638 gen_neon_dup_low16(cpu_T
[0]);
3640 gen_neon_dup_high16(cpu_T
[0]);
3644 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3648 for (n
= 0; n
< q
+ 1; n
+= 2) {
3649 NEON_GET_REG(T0
, reg
, n
);
3650 NEON_GET_REG(T0
, reg
, n
+ n
);
3652 case 0: gen_helper_neon_unzip_u8(); break;
3653 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3654 case 2: /* no-op */; break;
3657 gen_neon_movl_scratch_T0(tmp
+ n
);
3658 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3666 } neon_ls_element_type
[11] = {
3680 /* Translate a NEON load/store element instruction. Return nonzero if the
3681 instruction is invalid. */
3682 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3698 if (!vfp_enabled(env
))
3700 VFP_DREG_D(rd
, insn
);
3701 rn
= (insn
>> 16) & 0xf;
3703 load
= (insn
& (1 << 21)) != 0;
3704 if ((insn
& (1 << 23)) == 0) {
3705 /* Load store all elements. */
3706 op
= (insn
>> 8) & 0xf;
3707 size
= (insn
>> 6) & 3;
3708 if (op
> 10 || size
== 3)
3710 nregs
= neon_ls_element_type
[op
].nregs
;
3711 interleave
= neon_ls_element_type
[op
].interleave
;
3712 gen_movl_T1_reg(s
, rn
);
3713 stride
= (1 << size
) * interleave
;
3714 for (reg
= 0; reg
< nregs
; reg
++) {
3715 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3716 gen_movl_T1_reg(s
, rn
);
3717 gen_op_addl_T1_im((1 << size
) * reg
);
3718 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3719 gen_movl_T1_reg(s
, rn
);
3720 gen_op_addl_T1_im(1 << size
);
3722 for (pass
= 0; pass
< 2; pass
++) {
3725 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3726 neon_store_reg(rd
, pass
, tmp
);
3728 tmp
= neon_load_reg(rd
, pass
);
3729 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3731 gen_op_addl_T1_im(stride
);
3732 } else if (size
== 1) {
3734 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3735 gen_op_addl_T1_im(stride
);
3736 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3737 gen_op_addl_T1_im(stride
);
3738 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3740 neon_store_reg(rd
, pass
, tmp
);
3742 tmp
= neon_load_reg(rd
, pass
);
3744 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3745 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3746 gen_op_addl_T1_im(stride
);
3747 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3748 gen_op_addl_T1_im(stride
);
3750 } else /* size == 0 */ {
3753 for (n
= 0; n
< 4; n
++) {
3754 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3755 gen_op_addl_T1_im(stride
);
3759 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3763 neon_store_reg(rd
, pass
, tmp2
);
3765 tmp2
= neon_load_reg(rd
, pass
);
3766 for (n
= 0; n
< 4; n
++) {
3769 tcg_gen_mov_i32(tmp
, tmp2
);
3771 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3773 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3774 gen_op_addl_T1_im(stride
);
3780 rd
+= neon_ls_element_type
[op
].spacing
;
3784 size
= (insn
>> 10) & 3;
3786 /* Load single element to all lanes. */
3789 size
= (insn
>> 6) & 3;
3790 nregs
= ((insn
>> 8) & 3) + 1;
3791 stride
= (insn
& (1 << 5)) ? 2 : 1;
3792 gen_movl_T1_reg(s
, rn
);
3793 for (reg
= 0; reg
< nregs
; reg
++) {
3796 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3797 gen_neon_dup_u8(tmp
, 0);
3800 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3801 gen_neon_dup_low16(tmp
);
3804 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3808 default: /* Avoid compiler warnings. */
3811 gen_op_addl_T1_im(1 << size
);
3813 tcg_gen_mov_i32(tmp2
, tmp
);
3814 neon_store_reg(rd
, 0, tmp2
);
3815 neon_store_reg(rd
, 1, tmp
);
3818 stride
= (1 << size
) * nregs
;
3820 /* Single element. */
3821 pass
= (insn
>> 7) & 1;
3824 shift
= ((insn
>> 5) & 3) * 8;
3828 shift
= ((insn
>> 6) & 1) * 16;
3829 stride
= (insn
& (1 << 5)) ? 2 : 1;
3833 stride
= (insn
& (1 << 6)) ? 2 : 1;
3838 nregs
= ((insn
>> 8) & 3) + 1;
3839 gen_movl_T1_reg(s
, rn
);
3840 for (reg
= 0; reg
< nregs
; reg
++) {
3844 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3847 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3850 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3852 default: /* Avoid compiler warnings. */
3856 tmp2
= neon_load_reg(rd
, pass
);
3857 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3860 neon_store_reg(rd
, pass
, tmp
);
3861 } else { /* Store */
3862 tmp
= neon_load_reg(rd
, pass
);
3864 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3867 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3870 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3873 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3878 gen_op_addl_T1_im(1 << size
);
3880 stride
= nregs
* (1 << size
);
3886 base
= load_reg(s
, rn
);
3888 tcg_gen_addi_i32(base
, base
, stride
);
3891 index
= load_reg(s
, rm
);
3892 tcg_gen_add_i32(base
, base
, index
);
3895 store_reg(s
, rn
, base
);
3900 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3901 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3903 tcg_gen_and_i32(t
, t
, c
);
3904 tcg_gen_bic_i32(f
, f
, c
);
3905 tcg_gen_or_i32(dest
, t
, f
);
3908 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3911 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3912 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3913 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3918 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3921 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3922 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3923 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3928 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3931 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3932 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3933 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3938 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3944 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3945 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3950 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3951 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3958 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3959 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3964 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3965 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3972 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3976 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3977 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3978 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3983 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3984 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3985 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3992 static inline void gen_neon_addl(int size
)
3995 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3996 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3997 case 2: tcg_gen_add_i64(CPU_V001
); break;
4002 static inline void gen_neon_subl(int size
)
4005 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4006 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4007 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4012 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4015 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4016 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4017 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4022 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4025 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4026 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4031 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4035 switch ((size
<< 1) | u
) {
4036 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4037 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4038 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4039 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4041 tmp
= gen_muls_i64_i32(a
, b
);
4042 tcg_gen_mov_i64(dest
, tmp
);
4045 tmp
= gen_mulu_i64_i32(a
, b
);
4046 tcg_gen_mov_i64(dest
, tmp
);
4056 /* Translate a NEON data processing instruction. Return nonzero if the
4057 instruction is invalid.
4058 We process data in a mixture of 32-bit and 64-bit chunks.
4059 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4061 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4079 if (!vfp_enabled(env
))
4081 q
= (insn
& (1 << 6)) != 0;
4082 u
= (insn
>> 24) & 1;
4083 VFP_DREG_D(rd
, insn
);
4084 VFP_DREG_N(rn
, insn
);
4085 VFP_DREG_M(rm
, insn
);
4086 size
= (insn
>> 20) & 3;
4087 if ((insn
& (1 << 23)) == 0) {
4088 /* Three register same length. */
4089 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4090 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4091 || op
== 10 || op
== 11 || op
== 16)) {
4092 /* 64-bit element instructions. */
4093 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4094 neon_load_reg64(cpu_V0
, rn
+ pass
);
4095 neon_load_reg64(cpu_V1
, rm
+ pass
);
4099 gen_helper_neon_add_saturate_u64(CPU_V001
);
4101 gen_helper_neon_add_saturate_s64(CPU_V001
);
4106 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4108 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4113 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4115 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4120 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4123 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4127 case 10: /* VRSHL */
4129 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4131 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4134 case 11: /* VQRSHL */
4136 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4139 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4145 tcg_gen_sub_i64(CPU_V001
);
4147 tcg_gen_add_i64(CPU_V001
);
4153 neon_store_reg64(cpu_V0
, rd
+ pass
);
4160 case 10: /* VRSHL */
4161 case 11: /* VQRSHL */
4164 /* Shift instruction operands are reversed. */
4171 case 20: /* VPMAX */
4172 case 21: /* VPMIN */
4173 case 23: /* VPADD */
4176 case 26: /* VPADD (float) */
4177 pairwise
= (u
&& size
< 2);
4179 case 30: /* VPMIN/VPMAX (float) */
4186 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4195 NEON_GET_REG(T0
, rn
, n
);
4196 NEON_GET_REG(T1
, rn
, n
+ 1);
4198 NEON_GET_REG(T0
, rm
, n
);
4199 NEON_GET_REG(T1
, rm
, n
+ 1);
4203 NEON_GET_REG(T0
, rn
, pass
);
4204 NEON_GET_REG(T1
, rm
, pass
);
4208 GEN_NEON_INTEGER_OP(hadd
);
4211 GEN_NEON_INTEGER_OP_ENV(qadd
);
4213 case 2: /* VRHADD */
4214 GEN_NEON_INTEGER_OP(rhadd
);
4216 case 3: /* Logic ops. */
4217 switch ((u
<< 2) | size
) {
4219 gen_op_andl_T0_T1();
4222 gen_op_bicl_T0_T1();
4232 gen_op_xorl_T0_T1();
4235 tmp
= neon_load_reg(rd
, pass
);
4236 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4240 tmp
= neon_load_reg(rd
, pass
);
4241 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4245 tmp
= neon_load_reg(rd
, pass
);
4246 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4252 GEN_NEON_INTEGER_OP(hsub
);
4255 GEN_NEON_INTEGER_OP_ENV(qsub
);
4258 GEN_NEON_INTEGER_OP(cgt
);
4261 GEN_NEON_INTEGER_OP(cge
);
4264 GEN_NEON_INTEGER_OP(shl
);
4267 GEN_NEON_INTEGER_OP_ENV(qshl
);
4269 case 10: /* VRSHL */
4270 GEN_NEON_INTEGER_OP(rshl
);
4272 case 11: /* VQRSHL */
4273 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4276 GEN_NEON_INTEGER_OP(max
);
4279 GEN_NEON_INTEGER_OP(min
);
4282 GEN_NEON_INTEGER_OP(abd
);
4285 GEN_NEON_INTEGER_OP(abd
);
4286 NEON_GET_REG(T1
, rd
, pass
);
4290 if (!u
) { /* VADD */
4291 if (gen_neon_add(size
))
4295 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4296 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4297 case 2: gen_op_subl_T0_T1(); break;
4303 if (!u
) { /* VTST */
4305 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4306 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4307 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4312 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4313 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4314 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4319 case 18: /* Multiply. */
4321 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4322 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4323 case 2: gen_op_mul_T0_T1(); break;
4326 NEON_GET_REG(T1
, rd
, pass
);
4334 if (u
) { /* polynomial */
4335 gen_helper_neon_mul_p8(CPU_T001
);
4336 } else { /* Integer */
4338 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4339 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4340 case 2: gen_op_mul_T0_T1(); break;
4345 case 20: /* VPMAX */
4346 GEN_NEON_INTEGER_OP(pmax
);
4348 case 21: /* VPMIN */
4349 GEN_NEON_INTEGER_OP(pmin
);
4351 case 22: /* Hultiply high. */
4352 if (!u
) { /* VQDMULH */
4354 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4355 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4358 } else { /* VQRDHMUL */
4360 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4361 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4366 case 23: /* VPADD */
4370 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4371 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4372 case 2: gen_op_addl_T0_T1(); break;
4376 case 26: /* Floating point arithnetic. */
4377 switch ((u
<< 2) | size
) {
4379 gen_helper_neon_add_f32(CPU_T001
);
4382 gen_helper_neon_sub_f32(CPU_T001
);
4385 gen_helper_neon_add_f32(CPU_T001
);
4388 gen_helper_neon_abd_f32(CPU_T001
);
4394 case 27: /* Float multiply. */
4395 gen_helper_neon_mul_f32(CPU_T001
);
4397 NEON_GET_REG(T1
, rd
, pass
);
4399 gen_helper_neon_add_f32(CPU_T001
);
4401 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4405 case 28: /* Float compare. */
4407 gen_helper_neon_ceq_f32(CPU_T001
);
4410 gen_helper_neon_cge_f32(CPU_T001
);
4412 gen_helper_neon_cgt_f32(CPU_T001
);
4415 case 29: /* Float compare absolute. */
4419 gen_helper_neon_acge_f32(CPU_T001
);
4421 gen_helper_neon_acgt_f32(CPU_T001
);
4423 case 30: /* Float min/max. */
4425 gen_helper_neon_max_f32(CPU_T001
);
4427 gen_helper_neon_min_f32(CPU_T001
);
4431 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4433 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4438 /* Save the result. For elementwise operations we can put it
4439 straight into the destination register. For pairwise operations
4440 we have to be careful to avoid clobbering the source operands. */
4441 if (pairwise
&& rd
== rm
) {
4442 gen_neon_movl_scratch_T0(pass
);
4444 NEON_SET_REG(T0
, rd
, pass
);
4448 if (pairwise
&& rd
== rm
) {
4449 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4450 gen_neon_movl_T0_scratch(pass
);
4451 NEON_SET_REG(T0
, rd
, pass
);
4454 /* End of 3 register same size operations. */
4455 } else if (insn
& (1 << 4)) {
4456 if ((insn
& 0x00380080) != 0) {
4457 /* Two registers and shift. */
4458 op
= (insn
>> 8) & 0xf;
4459 if (insn
& (1 << 7)) {
4464 while ((insn
& (1 << (size
+ 19))) == 0)
4467 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4468 /* To avoid excessive dumplication of ops we implement shift
4469 by immediate using the variable shift operations. */
4471 /* Shift by immediate:
4472 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4473 /* Right shifts are encoded as N - shift, where N is the
4474 element size in bits. */
4476 shift
= shift
- (1 << (size
+ 3));
4484 imm
= (uint8_t) shift
;
4489 imm
= (uint16_t) shift
;
4500 for (pass
= 0; pass
< count
; pass
++) {
4502 neon_load_reg64(cpu_V0
, rm
+ pass
);
4503 tcg_gen_movi_i64(cpu_V1
, imm
);
4508 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4510 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4515 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4517 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4522 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4524 case 5: /* VSHL, VSLI */
4525 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4529 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4531 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4533 case 7: /* VQSHLU */
4534 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4537 if (op
== 1 || op
== 3) {
4539 neon_load_reg64(cpu_V0
, rd
+ pass
);
4540 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4541 } else if (op
== 4 || (op
== 5 && u
)) {
4543 cpu_abort(env
, "VS[LR]I.64 not implemented");
4545 neon_store_reg64(cpu_V0
, rd
+ pass
);
4546 } else { /* size < 3 */
4547 /* Operands in T0 and T1. */
4548 gen_op_movl_T1_im(imm
);
4549 NEON_GET_REG(T0
, rm
, pass
);
4553 GEN_NEON_INTEGER_OP(shl
);
4557 GEN_NEON_INTEGER_OP(rshl
);
4562 GEN_NEON_INTEGER_OP(shl
);
4564 case 5: /* VSHL, VSLI */
4566 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4567 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4568 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4573 GEN_NEON_INTEGER_OP_ENV(qshl
);
4575 case 7: /* VQSHLU */
4577 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4578 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4579 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4585 if (op
== 1 || op
== 3) {
4587 NEON_GET_REG(T1
, rd
, pass
);
4589 } else if (op
== 4 || (op
== 5 && u
)) {
4594 imm
= 0xff >> -shift
;
4596 imm
= (uint8_t)(0xff << shift
);
4602 imm
= 0xffff >> -shift
;
4604 imm
= (uint16_t)(0xffff << shift
);
4609 imm
= 0xffffffffu
>> -shift
;
4611 imm
= 0xffffffffu
<< shift
;
4616 tmp
= neon_load_reg(rd
, pass
);
4617 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4618 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4619 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4621 NEON_SET_REG(T0
, rd
, pass
);
4624 } else if (op
< 10) {
4625 /* Shift by immediate and narrow:
4626 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4627 shift
= shift
- (1 << (size
+ 3));
4631 imm
= (uint16_t)shift
;
4633 tmp2
= tcg_const_i32(imm
);
4634 TCGV_UNUSED_I64(tmp64
);
4637 imm
= (uint32_t)shift
;
4638 tmp2
= tcg_const_i32(imm
);
4639 TCGV_UNUSED_I64(tmp64
);
4642 tmp64
= tcg_const_i64(shift
);
4649 for (pass
= 0; pass
< 2; pass
++) {
4651 neon_load_reg64(cpu_V0
, rm
+ pass
);
4654 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4656 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4659 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4661 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4664 tmp
= neon_load_reg(rm
+ pass
, 0);
4665 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4666 tmp3
= neon_load_reg(rm
+ pass
, 1);
4667 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4668 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4673 if (op
== 8 && !u
) {
4674 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4677 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4679 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4684 neon_store_reg(rd
, 0, tmp2
);
4685 neon_store_reg(rd
, 1, tmp
);
4688 } else if (op
== 10) {
4692 tmp
= neon_load_reg(rm
, 0);
4693 tmp2
= neon_load_reg(rm
, 1);
4694 for (pass
= 0; pass
< 2; pass
++) {
4698 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4701 /* The shift is less than the width of the source
4702 type, so we can just shift the whole register. */
4703 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4704 if (size
< 2 || !u
) {
4707 imm
= (0xffu
>> (8 - shift
));
4710 imm
= 0xffff >> (16 - shift
);
4712 imm64
= imm
| (((uint64_t)imm
) << 32);
4713 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4716 neon_store_reg64(cpu_V0
, rd
+ pass
);
4718 } else if (op
== 15 || op
== 16) {
4719 /* VCVT fixed-point. */
4720 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4721 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4724 gen_vfp_ulto(0, shift
);
4726 gen_vfp_slto(0, shift
);
4729 gen_vfp_toul(0, shift
);
4731 gen_vfp_tosl(0, shift
);
4733 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4738 } else { /* (insn & 0x00380080) == 0 */
4741 op
= (insn
>> 8) & 0xf;
4742 /* One register and immediate. */
4743 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4744 invert
= (insn
& (1 << 5)) != 0;
4762 imm
= (imm
<< 8) | (imm
<< 24);
4765 imm
= (imm
< 8) | 0xff;
4768 imm
= (imm
<< 16) | 0xffff;
4771 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4776 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4777 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4783 if (op
!= 14 || !invert
)
4784 gen_op_movl_T1_im(imm
);
4786 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4787 if (op
& 1 && op
< 12) {
4788 tmp
= neon_load_reg(rd
, pass
);
4790 /* The immediate value has already been inverted, so
4792 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4794 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4799 if (op
== 14 && invert
) {
4802 for (n
= 0; n
< 4; n
++) {
4803 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4804 val
|= 0xff << (n
* 8);
4806 tcg_gen_movi_i32(tmp
, val
);
4808 tcg_gen_movi_i32(tmp
, imm
);
4811 neon_store_reg(rd
, pass
, tmp
);
4814 } else { /* (insn & 0x00800010 == 0x00800000) */
4816 op
= (insn
>> 8) & 0xf;
4817 if ((insn
& (1 << 6)) == 0) {
4818 /* Three registers of different lengths. */
4822 /* prewiden, src1_wide, src2_wide */
4823 static const int neon_3reg_wide
[16][3] = {
4824 {1, 0, 0}, /* VADDL */
4825 {1, 1, 0}, /* VADDW */
4826 {1, 0, 0}, /* VSUBL */
4827 {1, 1, 0}, /* VSUBW */
4828 {0, 1, 1}, /* VADDHN */
4829 {0, 0, 0}, /* VABAL */
4830 {0, 1, 1}, /* VSUBHN */
4831 {0, 0, 0}, /* VABDL */
4832 {0, 0, 0}, /* VMLAL */
4833 {0, 0, 0}, /* VQDMLAL */
4834 {0, 0, 0}, /* VMLSL */
4835 {0, 0, 0}, /* VQDMLSL */
4836 {0, 0, 0}, /* Integer VMULL */
4837 {0, 0, 0}, /* VQDMULL */
4838 {0, 0, 0} /* Polynomial VMULL */
4841 prewiden
= neon_3reg_wide
[op
][0];
4842 src1_wide
= neon_3reg_wide
[op
][1];
4843 src2_wide
= neon_3reg_wide
[op
][2];
4845 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4848 /* Avoid overlapping operands. Wide source operands are
4849 always aligned so will never overlap with wide
4850 destinations in problematic ways. */
4851 if (rd
== rm
&& !src2_wide
) {
4852 NEON_GET_REG(T0
, rm
, 1);
4853 gen_neon_movl_scratch_T0(2);
4854 } else if (rd
== rn
&& !src1_wide
) {
4855 NEON_GET_REG(T0
, rn
, 1);
4856 gen_neon_movl_scratch_T0(2);
4859 for (pass
= 0; pass
< 2; pass
++) {
4861 neon_load_reg64(cpu_V0
, rn
+ pass
);
4864 if (pass
== 1 && rd
== rn
) {
4865 gen_neon_movl_T0_scratch(2);
4867 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4869 tmp
= neon_load_reg(rn
, pass
);
4872 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4876 neon_load_reg64(cpu_V1
, rm
+ pass
);
4879 if (pass
== 1 && rd
== rm
) {
4880 gen_neon_movl_T0_scratch(2);
4882 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4884 tmp2
= neon_load_reg(rm
, pass
);
4887 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4891 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4892 gen_neon_addl(size
);
4894 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4895 gen_neon_subl(size
);
4897 case 5: case 7: /* VABAL, VABDL */
4898 switch ((size
<< 1) | u
) {
4900 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4903 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4906 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4909 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4912 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4915 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4922 case 8: case 9: case 10: case 11: case 12: case 13:
4923 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4924 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4926 case 14: /* Polynomial VMULL */
4927 cpu_abort(env
, "Polynomial VMULL not implemented");
4929 default: /* 15 is RESERVED. */
4932 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4934 if (op
== 10 || op
== 11) {
4935 gen_neon_negl(cpu_V0
, size
);
4939 neon_load_reg64(cpu_V1
, rd
+ pass
);
4943 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4944 gen_neon_addl(size
);
4946 case 9: case 11: /* VQDMLAL, VQDMLSL */
4947 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4948 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4951 case 13: /* VQDMULL */
4952 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4957 neon_store_reg64(cpu_V0
, rd
+ pass
);
4958 } else if (op
== 4 || op
== 6) {
4959 /* Narrowing operation. */
4964 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4967 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4970 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4971 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4978 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4981 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4984 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4985 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4986 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4994 neon_store_reg(rd
, 0, tmp3
);
4995 neon_store_reg(rd
, 1, tmp
);
4998 /* Write back the result. */
4999 neon_store_reg64(cpu_V0
, rd
+ pass
);
5003 /* Two registers and a scalar. */
5005 case 0: /* Integer VMLA scalar */
5006 case 1: /* Float VMLA scalar */
5007 case 4: /* Integer VMLS scalar */
5008 case 5: /* Floating point VMLS scalar */
5009 case 8: /* Integer VMUL scalar */
5010 case 9: /* Floating point VMUL scalar */
5011 case 12: /* VQDMULH scalar */
5012 case 13: /* VQRDMULH scalar */
5013 gen_neon_get_scalar(size
, rm
);
5014 gen_neon_movl_scratch_T0(0);
5015 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5017 gen_neon_movl_T0_scratch(0);
5018 NEON_GET_REG(T1
, rn
, pass
);
5021 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5023 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5025 } else if (op
== 13) {
5027 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5029 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5031 } else if (op
& 1) {
5032 gen_helper_neon_mul_f32(CPU_T001
);
5035 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5036 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5037 case 2: gen_op_mul_T0_T1(); break;
5043 NEON_GET_REG(T1
, rd
, pass
);
5049 gen_helper_neon_add_f32(CPU_T001
);
5055 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5061 NEON_SET_REG(T0
, rd
, pass
);
5064 case 2: /* VMLAL sclar */
5065 case 3: /* VQDMLAL scalar */
5066 case 6: /* VMLSL scalar */
5067 case 7: /* VQDMLSL scalar */
5068 case 10: /* VMULL scalar */
5069 case 11: /* VQDMULL scalar */
5070 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5073 gen_neon_get_scalar(size
, rm
);
5074 NEON_GET_REG(T1
, rn
, 1);
5076 for (pass
= 0; pass
< 2; pass
++) {
5078 tmp
= neon_load_reg(rn
, 0);
5081 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5084 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5085 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5086 if (op
== 6 || op
== 7) {
5087 gen_neon_negl(cpu_V0
, size
);
5090 neon_load_reg64(cpu_V1
, rd
+ pass
);
5094 gen_neon_addl(size
);
5097 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5098 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5104 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5109 neon_store_reg64(cpu_V0
, rd
+ pass
);
5112 default: /* 14 and 15 are RESERVED */
5116 } else { /* size == 3 */
5119 imm
= (insn
>> 8) & 0xf;
5126 neon_load_reg64(cpu_V0
, rn
);
5128 neon_load_reg64(cpu_V1
, rn
+ 1);
5130 } else if (imm
== 8) {
5131 neon_load_reg64(cpu_V0
, rn
+ 1);
5133 neon_load_reg64(cpu_V1
, rm
);
5136 tmp64
= tcg_temp_new_i64();
5138 neon_load_reg64(cpu_V0
, rn
);
5139 neon_load_reg64(tmp64
, rn
+ 1);
5141 neon_load_reg64(cpu_V0
, rn
+ 1);
5142 neon_load_reg64(tmp64
, rm
);
5144 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5145 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5146 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5148 neon_load_reg64(cpu_V1
, rm
);
5150 neon_load_reg64(cpu_V1
, rm
+ 1);
5153 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5154 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5155 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5158 neon_load_reg64(cpu_V0
, rn
);
5159 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5160 neon_load_reg64(cpu_V1
, rm
);
5161 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5162 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5164 neon_store_reg64(cpu_V0
, rd
);
5166 neon_store_reg64(cpu_V1
, rd
+ 1);
5168 } else if ((insn
& (1 << 11)) == 0) {
5169 /* Two register misc. */
5170 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5171 size
= (insn
>> 18) & 3;
5173 case 0: /* VREV64 */
5176 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5177 NEON_GET_REG(T0
, rm
, pass
* 2);
5178 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5180 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5181 case 1: gen_swap_half(cpu_T
[0]); break;
5182 case 2: /* no-op */ break;
5185 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5187 NEON_SET_REG(T1
, rd
, pass
* 2);
5189 gen_op_movl_T0_T1();
5191 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5192 case 1: gen_swap_half(cpu_T
[0]); break;
5195 NEON_SET_REG(T0
, rd
, pass
* 2);
5199 case 4: case 5: /* VPADDL */
5200 case 12: case 13: /* VPADAL */
5203 for (pass
= 0; pass
< q
+ 1; pass
++) {
5204 tmp
= neon_load_reg(rm
, pass
* 2);
5205 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5206 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5207 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5209 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5210 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5211 case 2: tcg_gen_add_i64(CPU_V001
); break;
5216 neon_load_reg64(cpu_V1
, rd
+ pass
);
5217 gen_neon_addl(size
);
5219 neon_store_reg64(cpu_V0
, rd
+ pass
);
5224 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5225 NEON_GET_REG(T0
, rm
, n
);
5226 NEON_GET_REG(T1
, rd
, n
+ 1);
5227 NEON_SET_REG(T1
, rm
, n
);
5228 NEON_SET_REG(T0
, rd
, n
+ 1);
5236 Rd A3 A2 A1 A0 B2 B0 A2 A0
5237 Rm B3 B2 B1 B0 B3 B1 A3 A1
5241 gen_neon_unzip(rd
, q
, 0, size
);
5242 gen_neon_unzip(rm
, q
, 4, size
);
5244 static int unzip_order_q
[8] =
5245 {0, 2, 4, 6, 1, 3, 5, 7};
5246 for (n
= 0; n
< 8; n
++) {
5247 int reg
= (n
< 4) ? rd
: rm
;
5248 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5249 NEON_SET_REG(T0
, reg
, n
% 4);
5252 static int unzip_order
[4] =
5254 for (n
= 0; n
< 4; n
++) {
5255 int reg
= (n
< 2) ? rd
: rm
;
5256 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5257 NEON_SET_REG(T0
, reg
, n
% 2);
5263 Rd A3 A2 A1 A0 B1 A1 B0 A0
5264 Rm B3 B2 B1 B0 B3 A3 B2 A2
5268 count
= (q
? 4 : 2);
5269 for (n
= 0; n
< count
; n
++) {
5270 NEON_GET_REG(T0
, rd
, n
);
5271 NEON_GET_REG(T1
, rd
, n
);
5273 case 0: gen_helper_neon_zip_u8(); break;
5274 case 1: gen_helper_neon_zip_u16(); break;
5275 case 2: /* no-op */; break;
5278 gen_neon_movl_scratch_T0(n
* 2);
5279 gen_neon_movl_scratch_T1(n
* 2 + 1);
5281 for (n
= 0; n
< count
* 2; n
++) {
5282 int reg
= (n
< count
) ? rd
: rm
;
5283 gen_neon_movl_T0_scratch(n
);
5284 NEON_SET_REG(T0
, reg
, n
% count
);
5287 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5291 for (pass
= 0; pass
< 2; pass
++) {
5292 neon_load_reg64(cpu_V0
, rm
+ pass
);
5294 if (op
== 36 && q
== 0) {
5295 gen_neon_narrow(size
, tmp
, cpu_V0
);
5297 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5299 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5304 neon_store_reg(rd
, 0, tmp2
);
5305 neon_store_reg(rd
, 1, tmp
);
5309 case 38: /* VSHLL */
5312 tmp
= neon_load_reg(rm
, 0);
5313 tmp2
= neon_load_reg(rm
, 1);
5314 for (pass
= 0; pass
< 2; pass
++) {
5317 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5318 neon_store_reg64(cpu_V0
, rd
+ pass
);
5323 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5324 if (op
== 30 || op
== 31 || op
>= 58) {
5325 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5326 neon_reg_offset(rm
, pass
));
5328 NEON_GET_REG(T0
, rm
, pass
);
5331 case 1: /* VREV32 */
5333 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5334 case 1: gen_swap_half(cpu_T
[0]); break;
5338 case 2: /* VREV16 */
5341 gen_rev16(cpu_T
[0]);
5345 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5346 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5347 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5353 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5354 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5355 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5362 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5369 case 14: /* VQABS */
5371 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5372 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5373 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5377 case 15: /* VQNEG */
5379 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5380 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5381 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5385 case 16: case 19: /* VCGT #0, VCLE #0 */
5386 gen_op_movl_T1_im(0);
5388 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5389 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5390 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5396 case 17: case 20: /* VCGE #0, VCLT #0 */
5397 gen_op_movl_T1_im(0);
5399 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5400 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5401 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5407 case 18: /* VCEQ #0 */
5408 gen_op_movl_T1_im(0);
5410 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5411 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5412 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5418 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5419 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5420 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5425 gen_op_movl_T1_im(0);
5430 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5431 gen_op_movl_T1_im(0);
5432 gen_helper_neon_cgt_f32(CPU_T001
);
5436 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5437 gen_op_movl_T1_im(0);
5438 gen_helper_neon_cge_f32(CPU_T001
);
5442 case 26: /* Float VCEQ #0 */
5443 gen_op_movl_T1_im(0);
5444 gen_helper_neon_ceq_f32(CPU_T001
);
5446 case 30: /* Float VABS */
5449 case 31: /* Float VNEG */
5453 NEON_GET_REG(T1
, rd
, pass
);
5454 NEON_SET_REG(T1
, rm
, pass
);
5457 NEON_GET_REG(T1
, rd
, pass
);
5459 case 0: gen_helper_neon_trn_u8(); break;
5460 case 1: gen_helper_neon_trn_u16(); break;
5464 NEON_SET_REG(T1
, rm
, pass
);
5466 case 56: /* Integer VRECPE */
5467 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5469 case 57: /* Integer VRSQRTE */
5470 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5472 case 58: /* Float VRECPE */
5473 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5475 case 59: /* Float VRSQRTE */
5476 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5478 case 60: /* VCVT.F32.S32 */
5481 case 61: /* VCVT.F32.U32 */
5484 case 62: /* VCVT.S32.F32 */
5487 case 63: /* VCVT.U32.F32 */
5491 /* Reserved: 21, 29, 39-56 */
5494 if (op
== 30 || op
== 31 || op
>= 58) {
5495 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5496 neon_reg_offset(rd
, pass
));
5498 NEON_SET_REG(T0
, rd
, pass
);
5503 } else if ((insn
& (1 << 10)) == 0) {
5505 n
= ((insn
>> 5) & 0x18) + 8;
5506 if (insn
& (1 << 6)) {
5507 tmp
= neon_load_reg(rd
, 0);
5510 tcg_gen_movi_i32(tmp
, 0);
5512 tmp2
= neon_load_reg(rm
, 0);
5513 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5516 if (insn
& (1 << 6)) {
5517 tmp
= neon_load_reg(rd
, 1);
5520 tcg_gen_movi_i32(tmp
, 0);
5522 tmp3
= neon_load_reg(rm
, 1);
5523 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5525 neon_store_reg(rd
, 0, tmp2
);
5526 neon_store_reg(rd
, 1, tmp3
);
5528 } else if ((insn
& 0x380) == 0) {
5530 if (insn
& (1 << 19)) {
5531 NEON_SET_REG(T0
, rm
, 1);
5533 NEON_SET_REG(T0
, rm
, 0);
5535 if (insn
& (1 << 16)) {
5536 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5537 } else if (insn
& (1 << 17)) {
5538 if ((insn
>> 18) & 1)
5539 gen_neon_dup_high16(cpu_T
[0]);
5541 gen_neon_dup_low16(cpu_T
[0]);
5543 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5544 NEON_SET_REG(T0
, rd
, pass
);
5554 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5556 int crn
= (insn
>> 16) & 0xf;
5557 int crm
= insn
& 0xf;
5558 int op1
= (insn
>> 21) & 7;
5559 int op2
= (insn
>> 5) & 7;
5560 int rt
= (insn
>> 12) & 0xf;
5563 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5564 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5568 tmp
= load_cpu_field(teecr
);
5569 store_reg(s
, rt
, tmp
);
5572 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5574 if (IS_USER(s
) && (env
->teecr
& 1))
5576 tmp
= load_cpu_field(teehbr
);
5577 store_reg(s
, rt
, tmp
);
5581 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5582 op1
, crn
, crm
, op2
);
5586 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5588 int crn
= (insn
>> 16) & 0xf;
5589 int crm
= insn
& 0xf;
5590 int op1
= (insn
>> 21) & 7;
5591 int op2
= (insn
>> 5) & 7;
5592 int rt
= (insn
>> 12) & 0xf;
5595 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5596 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5600 tmp
= load_reg(s
, rt
);
5601 gen_helper_set_teecr(cpu_env
, tmp
);
5605 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5607 if (IS_USER(s
) && (env
->teecr
& 1))
5609 tmp
= load_reg(s
, rt
);
5610 store_cpu_field(tmp
, teehbr
);
5614 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5615 op1
, crn
, crm
, op2
);
5619 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5623 cpnum
= (insn
>> 8) & 0xf;
5624 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5625 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5631 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5632 return disas_iwmmxt_insn(env
, s
, insn
);
5633 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5634 return disas_dsp_insn(env
, s
, insn
);
5639 return disas_vfp_insn (env
, s
, insn
);
5641 /* Coprocessors 7-15 are architecturally reserved by ARM.
5642 Unfortunately Intel decided to ignore this. */
5643 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5645 if (insn
& (1 << 20))
5646 return disas_cp14_read(env
, s
, insn
);
5648 return disas_cp14_write(env
, s
, insn
);
5650 return disas_cp15_insn (env
, s
, insn
);
5653 /* Unknown coprocessor. See if the board has hooked it. */
5654 return disas_cp_insn (env
, s
, insn
);
5659 /* Store a 64-bit value to a register pair. Clobbers val. */
5660 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5664 tcg_gen_trunc_i64_i32(tmp
, val
);
5665 store_reg(s
, rlow
, tmp
);
5667 tcg_gen_shri_i64(val
, val
, 32);
5668 tcg_gen_trunc_i64_i32(tmp
, val
);
5669 store_reg(s
, rhigh
, tmp
);
5672 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5673 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5678 /* Load value and extend to 64 bits. */
5679 tmp
= tcg_temp_new_i64();
5680 tmp2
= load_reg(s
, rlow
);
5681 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5683 tcg_gen_add_i64(val
, val
, tmp
);
5686 /* load and add a 64-bit value from a register pair. */
5687 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5693 /* Load 64-bit value rd:rn. */
5694 tmpl
= load_reg(s
, rlow
);
5695 tmph
= load_reg(s
, rhigh
);
5696 tmp
= tcg_temp_new_i64();
5697 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5700 tcg_gen_add_i64(val
, val
, tmp
);
5703 /* Set N and Z flags from a 64-bit value. */
5704 static void gen_logicq_cc(TCGv_i64 val
)
5706 TCGv tmp
= new_tmp();
5707 gen_helper_logicq_cc(tmp
, val
);
5712 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5714 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5721 insn
= ldl_code(s
->pc
);
5724 /* M variants do not implement ARM mode. */
5729 /* Unconditional instructions. */
5730 if (((insn
>> 25) & 7) == 1) {
5731 /* NEON Data processing. */
5732 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5735 if (disas_neon_data_insn(env
, s
, insn
))
5739 if ((insn
& 0x0f100000) == 0x04000000) {
5740 /* NEON load/store. */
5741 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5744 if (disas_neon_ls_insn(env
, s
, insn
))
5748 if ((insn
& 0x0d70f000) == 0x0550f000)
5750 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5753 if (insn
& (1 << 9)) {
5754 /* BE8 mode not implemented. */
5758 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5759 switch ((insn
>> 4) & 0xf) {
5762 gen_helper_clrex(cpu_env
);
5768 /* We don't emulate caches so these are a no-op. */
5773 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5779 op1
= (insn
& 0x1f);
5780 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5781 addr
= load_reg(s
, 13);
5784 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5786 i
= (insn
>> 23) & 3;
5788 case 0: offset
= -4; break; /* DA */
5789 case 1: offset
= -8; break; /* DB */
5790 case 2: offset
= 0; break; /* IA */
5791 case 3: offset
= 4; break; /* IB */
5795 tcg_gen_addi_i32(addr
, addr
, offset
);
5796 tmp
= load_reg(s
, 14);
5797 gen_st32(tmp
, addr
, 0);
5799 gen_helper_cpsr_read(tmp
);
5800 tcg_gen_addi_i32(addr
, addr
, 4);
5801 gen_st32(tmp
, addr
, 0);
5802 if (insn
& (1 << 21)) {
5803 /* Base writeback. */
5805 case 0: offset
= -8; break;
5806 case 1: offset
= -4; break;
5807 case 2: offset
= 4; break;
5808 case 3: offset
= 0; break;
5812 tcg_gen_addi_i32(addr
, tmp
, offset
);
5813 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5814 gen_movl_reg_T1(s
, 13);
5816 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5821 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5827 rn
= (insn
>> 16) & 0xf;
5828 addr
= load_reg(s
, rn
);
5829 i
= (insn
>> 23) & 3;
5831 case 0: offset
= -4; break; /* DA */
5832 case 1: offset
= -8; break; /* DB */
5833 case 2: offset
= 0; break; /* IA */
5834 case 3: offset
= 4; break; /* IB */
5838 tcg_gen_addi_i32(addr
, addr
, offset
);
5839 /* Load PC into tmp and CPSR into tmp2. */
5840 tmp
= gen_ld32(addr
, 0);
5841 tcg_gen_addi_i32(addr
, addr
, 4);
5842 tmp2
= gen_ld32(addr
, 0);
5843 if (insn
& (1 << 21)) {
5844 /* Base writeback. */
5846 case 0: offset
= -8; break;
5847 case 1: offset
= -4; break;
5848 case 2: offset
= 4; break;
5849 case 3: offset
= 0; break;
5853 tcg_gen_addi_i32(addr
, addr
, offset
);
5854 store_reg(s
, rn
, addr
);
5858 gen_rfe(s
, tmp
, tmp2
);
5859 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5860 /* branch link and change to thumb (blx <offset>) */
5863 val
= (uint32_t)s
->pc
;
5865 tcg_gen_movi_i32(tmp
, val
);
5866 store_reg(s
, 14, tmp
);
5867 /* Sign-extend the 24-bit offset */
5868 offset
= (((int32_t)insn
) << 8) >> 8;
5869 /* offset * 4 + bit24 * 2 + (thumb bit) */
5870 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5871 /* pipeline offset */
5875 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5876 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5877 /* iWMMXt register transfer. */
5878 if (env
->cp15
.c15_cpar
& (1 << 1))
5879 if (!disas_iwmmxt_insn(env
, s
, insn
))
5882 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5883 /* Coprocessor double register transfer. */
5884 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5885 /* Additional coprocessor register transfer. */
5886 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5889 /* cps (privileged) */
5893 if (insn
& (1 << 19)) {
5894 if (insn
& (1 << 8))
5896 if (insn
& (1 << 7))
5898 if (insn
& (1 << 6))
5900 if (insn
& (1 << 18))
5903 if (insn
& (1 << 17)) {
5905 val
|= (insn
& 0x1f);
5908 gen_op_movl_T0_im(val
);
5909 gen_set_psr_T0(s
, mask
, 0);
5916 /* if not always execute, we generate a conditional jump to
5918 s
->condlabel
= gen_new_label();
5919 gen_test_cc(cond
^ 1, s
->condlabel
);
5922 if ((insn
& 0x0f900000) == 0x03000000) {
5923 if ((insn
& (1 << 21)) == 0) {
5925 rd
= (insn
>> 12) & 0xf;
5926 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5927 if ((insn
& (1 << 22)) == 0) {
5930 tcg_gen_movi_i32(tmp
, val
);
5933 tmp
= load_reg(s
, rd
);
5934 tcg_gen_ext16u_i32(tmp
, tmp
);
5935 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5937 store_reg(s
, rd
, tmp
);
5939 if (((insn
>> 12) & 0xf) != 0xf)
5941 if (((insn
>> 16) & 0xf) == 0) {
5942 gen_nop_hint(s
, insn
& 0xff);
5944 /* CPSR = immediate */
5946 shift
= ((insn
>> 8) & 0xf) * 2;
5948 val
= (val
>> shift
) | (val
<< (32 - shift
));
5949 gen_op_movl_T0_im(val
);
5950 i
= ((insn
& (1 << 22)) != 0);
5951 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5955 } else if ((insn
& 0x0f900000) == 0x01000000
5956 && (insn
& 0x00000090) != 0x00000090) {
5957 /* miscellaneous instructions */
5958 op1
= (insn
>> 21) & 3;
5959 sh
= (insn
>> 4) & 0xf;
5962 case 0x0: /* move program status register */
5965 gen_movl_T0_reg(s
, rm
);
5966 i
= ((op1
& 2) != 0);
5967 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5971 rd
= (insn
>> 12) & 0xf;
5975 tmp
= load_cpu_field(spsr
);
5978 gen_helper_cpsr_read(tmp
);
5980 store_reg(s
, rd
, tmp
);
5985 /* branch/exchange thumb (bx). */
5986 tmp
= load_reg(s
, rm
);
5988 } else if (op1
== 3) {
5990 rd
= (insn
>> 12) & 0xf;
5991 tmp
= load_reg(s
, rm
);
5992 gen_helper_clz(tmp
, tmp
);
5993 store_reg(s
, rd
, tmp
);
6001 /* Trivial implementation equivalent to bx. */
6002 tmp
= load_reg(s
, rm
);
6012 /* branch link/exchange thumb (blx) */
6013 tmp
= load_reg(s
, rm
);
6015 tcg_gen_movi_i32(tmp2
, s
->pc
);
6016 store_reg(s
, 14, tmp2
);
6019 case 0x5: /* saturating add/subtract */
6020 rd
= (insn
>> 12) & 0xf;
6021 rn
= (insn
>> 16) & 0xf;
6022 tmp
= load_reg(s
, rm
);
6023 tmp2
= load_reg(s
, rn
);
6025 gen_helper_double_saturate(tmp2
, tmp2
);
6027 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6029 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6031 store_reg(s
, rd
, tmp
);
6034 gen_set_condexec(s
);
6035 gen_set_pc_im(s
->pc
- 4);
6036 gen_exception(EXCP_BKPT
);
6037 s
->is_jmp
= DISAS_JUMP
;
6039 case 0x8: /* signed multiply */
6043 rs
= (insn
>> 8) & 0xf;
6044 rn
= (insn
>> 12) & 0xf;
6045 rd
= (insn
>> 16) & 0xf;
6047 /* (32 * 16) >> 16 */
6048 tmp
= load_reg(s
, rm
);
6049 tmp2
= load_reg(s
, rs
);
6051 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6054 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6055 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6057 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6058 if ((sh
& 2) == 0) {
6059 tmp2
= load_reg(s
, rn
);
6060 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6063 store_reg(s
, rd
, tmp
);
6066 tmp
= load_reg(s
, rm
);
6067 tmp2
= load_reg(s
, rs
);
6068 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6071 tmp64
= tcg_temp_new_i64();
6072 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6074 gen_addq(s
, tmp64
, rn
, rd
);
6075 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6078 tmp2
= load_reg(s
, rn
);
6079 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6082 store_reg(s
, rd
, tmp
);
6089 } else if (((insn
& 0x0e000000) == 0 &&
6090 (insn
& 0x00000090) != 0x90) ||
6091 ((insn
& 0x0e000000) == (1 << 25))) {
6092 int set_cc
, logic_cc
, shiftop
;
6094 op1
= (insn
>> 21) & 0xf;
6095 set_cc
= (insn
>> 20) & 1;
6096 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6098 /* data processing instruction */
6099 if (insn
& (1 << 25)) {
6100 /* immediate operand */
6102 shift
= ((insn
>> 8) & 0xf) * 2;
6104 val
= (val
>> shift
) | (val
<< (32 - shift
));
6107 tcg_gen_movi_i32(tmp2
, val
);
6108 if (logic_cc
&& shift
) {
6109 gen_set_CF_bit31(tmp2
);
6114 tmp2
= load_reg(s
, rm
);
6115 shiftop
= (insn
>> 5) & 3;
6116 if (!(insn
& (1 << 4))) {
6117 shift
= (insn
>> 7) & 0x1f;
6118 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6120 rs
= (insn
>> 8) & 0xf;
6121 tmp
= load_reg(s
, rs
);
6122 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6125 if (op1
!= 0x0f && op1
!= 0x0d) {
6126 rn
= (insn
>> 16) & 0xf;
6127 tmp
= load_reg(s
, rn
);
6131 rd
= (insn
>> 12) & 0xf;
6134 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6138 store_reg_bx(env
, s
, rd
, tmp
);
6141 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6145 store_reg_bx(env
, s
, rd
, tmp
);
6148 if (set_cc
&& rd
== 15) {
6149 /* SUBS r15, ... is used for exception return. */
6153 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6154 gen_exception_return(s
, tmp
);
6157 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6159 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6161 store_reg_bx(env
, s
, rd
, tmp
);
6166 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6168 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6170 store_reg_bx(env
, s
, rd
, tmp
);
6174 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6176 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6178 store_reg_bx(env
, s
, rd
, tmp
);
6182 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6184 gen_add_carry(tmp
, tmp
, tmp2
);
6186 store_reg_bx(env
, s
, rd
, tmp
);
6190 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6192 gen_sub_carry(tmp
, tmp
, tmp2
);
6194 store_reg_bx(env
, s
, rd
, tmp
);
6198 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6200 gen_sub_carry(tmp
, tmp2
, tmp
);
6202 store_reg_bx(env
, s
, rd
, tmp
);
6206 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6213 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6220 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6226 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6231 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6235 store_reg_bx(env
, s
, rd
, tmp
);
6238 if (logic_cc
&& rd
== 15) {
6239 /* MOVS r15, ... is used for exception return. */
6243 gen_exception_return(s
, tmp2
);
6248 store_reg_bx(env
, s
, rd
, tmp2
);
6252 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6256 store_reg_bx(env
, s
, rd
, tmp
);
6260 tcg_gen_not_i32(tmp2
, tmp2
);
6264 store_reg_bx(env
, s
, rd
, tmp2
);
6267 if (op1
!= 0x0f && op1
!= 0x0d) {
6271 /* other instructions */
6272 op1
= (insn
>> 24) & 0xf;
6276 /* multiplies, extra load/stores */
6277 sh
= (insn
>> 5) & 3;
6280 rd
= (insn
>> 16) & 0xf;
6281 rn
= (insn
>> 12) & 0xf;
6282 rs
= (insn
>> 8) & 0xf;
6284 op1
= (insn
>> 20) & 0xf;
6286 case 0: case 1: case 2: case 3: case 6:
6288 tmp
= load_reg(s
, rs
);
6289 tmp2
= load_reg(s
, rm
);
6290 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6292 if (insn
& (1 << 22)) {
6293 /* Subtract (mls) */
6295 tmp2
= load_reg(s
, rn
);
6296 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6298 } else if (insn
& (1 << 21)) {
6300 tmp2
= load_reg(s
, rn
);
6301 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6304 if (insn
& (1 << 20))
6306 store_reg(s
, rd
, tmp
);
6310 tmp
= load_reg(s
, rs
);
6311 tmp2
= load_reg(s
, rm
);
6312 if (insn
& (1 << 22))
6313 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6315 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6316 if (insn
& (1 << 21)) /* mult accumulate */
6317 gen_addq(s
, tmp64
, rn
, rd
);
6318 if (!(insn
& (1 << 23))) { /* double accumulate */
6320 gen_addq_lo(s
, tmp64
, rn
);
6321 gen_addq_lo(s
, tmp64
, rd
);
6323 if (insn
& (1 << 20))
6324 gen_logicq_cc(tmp64
);
6325 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6329 rn
= (insn
>> 16) & 0xf;
6330 rd
= (insn
>> 12) & 0xf;
6331 if (insn
& (1 << 23)) {
6332 /* load/store exclusive */
6333 op1
= (insn
>> 21) & 0x3;
6338 gen_movl_T1_reg(s
, rn
);
6340 if (insn
& (1 << 20)) {
6341 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6344 tmp
= gen_ld32(addr
, IS_USER(s
));
6346 case 1: /* ldrexd */
6347 tmp
= gen_ld32(addr
, IS_USER(s
));
6348 store_reg(s
, rd
, tmp
);
6349 tcg_gen_addi_i32(addr
, addr
, 4);
6350 tmp
= gen_ld32(addr
, IS_USER(s
));
6353 case 2: /* ldrexb */
6354 tmp
= gen_ld8u(addr
, IS_USER(s
));
6356 case 3: /* ldrexh */
6357 tmp
= gen_ld16u(addr
, IS_USER(s
));
6362 store_reg(s
, rd
, tmp
);
6364 int label
= gen_new_label();
6366 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6367 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6369 tmp
= load_reg(s
,rm
);
6372 gen_st32(tmp
, addr
, IS_USER(s
));
6374 case 1: /* strexd */
6375 gen_st32(tmp
, addr
, IS_USER(s
));
6376 tcg_gen_addi_i32(addr
, addr
, 4);
6377 tmp
= load_reg(s
, rm
+ 1);
6378 gen_st32(tmp
, addr
, IS_USER(s
));
6380 case 2: /* strexb */
6381 gen_st8(tmp
, addr
, IS_USER(s
));
6383 case 3: /* strexh */
6384 gen_st16(tmp
, addr
, IS_USER(s
));
6389 gen_set_label(label
);
6390 gen_movl_reg_T0(s
, rd
);
6393 /* SWP instruction */
6396 /* ??? This is not really atomic. However we know
6397 we never have multiple CPUs running in parallel,
6398 so it is good enough. */
6399 addr
= load_reg(s
, rn
);
6400 tmp
= load_reg(s
, rm
);
6401 if (insn
& (1 << 22)) {
6402 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6403 gen_st8(tmp
, addr
, IS_USER(s
));
6405 tmp2
= gen_ld32(addr
, IS_USER(s
));
6406 gen_st32(tmp
, addr
, IS_USER(s
));
6409 store_reg(s
, rd
, tmp2
);
6415 /* Misc load/store */
6416 rn
= (insn
>> 16) & 0xf;
6417 rd
= (insn
>> 12) & 0xf;
6418 addr
= load_reg(s
, rn
);
6419 if (insn
& (1 << 24))
6420 gen_add_datah_offset(s
, insn
, 0, addr
);
6422 if (insn
& (1 << 20)) {
6426 tmp
= gen_ld16u(addr
, IS_USER(s
));
6429 tmp
= gen_ld8s(addr
, IS_USER(s
));
6433 tmp
= gen_ld16s(addr
, IS_USER(s
));
6437 } else if (sh
& 2) {
6441 tmp
= load_reg(s
, rd
);
6442 gen_st32(tmp
, addr
, IS_USER(s
));
6443 tcg_gen_addi_i32(addr
, addr
, 4);
6444 tmp
= load_reg(s
, rd
+ 1);
6445 gen_st32(tmp
, addr
, IS_USER(s
));
6449 tmp
= gen_ld32(addr
, IS_USER(s
));
6450 store_reg(s
, rd
, tmp
);
6451 tcg_gen_addi_i32(addr
, addr
, 4);
6452 tmp
= gen_ld32(addr
, IS_USER(s
));
6456 address_offset
= -4;
6459 tmp
= load_reg(s
, rd
);
6460 gen_st16(tmp
, addr
, IS_USER(s
));
6463 /* Perform base writeback before the loaded value to
6464 ensure correct behavior with overlapping index registers.
6465 ldrd with base writeback is is undefined if the
6466 destination and index registers overlap. */
6467 if (!(insn
& (1 << 24))) {
6468 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6469 store_reg(s
, rn
, addr
);
6470 } else if (insn
& (1 << 21)) {
6472 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6473 store_reg(s
, rn
, addr
);
6478 /* Complete the load. */
6479 store_reg(s
, rd
, tmp
);
6488 if (insn
& (1 << 4)) {
6490 /* Armv6 Media instructions. */
6492 rn
= (insn
>> 16) & 0xf;
6493 rd
= (insn
>> 12) & 0xf;
6494 rs
= (insn
>> 8) & 0xf;
6495 switch ((insn
>> 23) & 3) {
6496 case 0: /* Parallel add/subtract. */
6497 op1
= (insn
>> 20) & 7;
6498 tmp
= load_reg(s
, rn
);
6499 tmp2
= load_reg(s
, rm
);
6500 sh
= (insn
>> 5) & 7;
6501 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6503 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6505 store_reg(s
, rd
, tmp
);
6508 if ((insn
& 0x00700020) == 0) {
6509 /* Halfword pack. */
6510 tmp
= load_reg(s
, rn
);
6511 tmp2
= load_reg(s
, rm
);
6512 shift
= (insn
>> 7) & 0x1f;
6513 if (insn
& (1 << 6)) {
6517 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6518 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6519 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6523 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6524 tcg_gen_ext16u_i32(tmp
, tmp
);
6525 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6527 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6529 store_reg(s
, rd
, tmp
);
6530 } else if ((insn
& 0x00200020) == 0x00200000) {
6532 tmp
= load_reg(s
, rm
);
6533 shift
= (insn
>> 7) & 0x1f;
6534 if (insn
& (1 << 6)) {
6537 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6539 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6541 sh
= (insn
>> 16) & 0x1f;
6543 if (insn
& (1 << 22))
6544 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6546 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6548 store_reg(s
, rd
, tmp
);
6549 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6551 tmp
= load_reg(s
, rm
);
6552 sh
= (insn
>> 16) & 0x1f;
6554 if (insn
& (1 << 22))
6555 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6557 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6559 store_reg(s
, rd
, tmp
);
6560 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6562 tmp
= load_reg(s
, rn
);
6563 tmp2
= load_reg(s
, rm
);
6565 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6566 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6569 store_reg(s
, rd
, tmp
);
6570 } else if ((insn
& 0x000003e0) == 0x00000060) {
6571 tmp
= load_reg(s
, rm
);
6572 shift
= (insn
>> 10) & 3;
6573 /* ??? In many cases it's not neccessary to do a
6574 rotate, a shift is sufficient. */
6576 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6577 op1
= (insn
>> 20) & 7;
6579 case 0: gen_sxtb16(tmp
); break;
6580 case 2: gen_sxtb(tmp
); break;
6581 case 3: gen_sxth(tmp
); break;
6582 case 4: gen_uxtb16(tmp
); break;
6583 case 6: gen_uxtb(tmp
); break;
6584 case 7: gen_uxth(tmp
); break;
6585 default: goto illegal_op
;
6588 tmp2
= load_reg(s
, rn
);
6589 if ((op1
& 3) == 0) {
6590 gen_add16(tmp
, tmp2
);
6592 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6596 store_reg(s
, rd
, tmp
);
6597 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6599 tmp
= load_reg(s
, rm
);
6600 if (insn
& (1 << 22)) {
6601 if (insn
& (1 << 7)) {
6605 gen_helper_rbit(tmp
, tmp
);
6608 if (insn
& (1 << 7))
6611 tcg_gen_bswap32_i32(tmp
, tmp
);
6613 store_reg(s
, rd
, tmp
);
6618 case 2: /* Multiplies (Type 3). */
6619 tmp
= load_reg(s
, rm
);
6620 tmp2
= load_reg(s
, rs
);
6621 if (insn
& (1 << 20)) {
6622 /* Signed multiply most significant [accumulate]. */
6623 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6624 if (insn
& (1 << 5))
6625 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6626 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6628 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6630 tmp2
= load_reg(s
, rd
);
6631 if (insn
& (1 << 6)) {
6632 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6634 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6638 store_reg(s
, rn
, tmp
);
6640 if (insn
& (1 << 5))
6641 gen_swap_half(tmp2
);
6642 gen_smul_dual(tmp
, tmp2
);
6643 /* This addition cannot overflow. */
6644 if (insn
& (1 << 6)) {
6645 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6647 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6650 if (insn
& (1 << 22)) {
6651 /* smlald, smlsld */
6652 tmp64
= tcg_temp_new_i64();
6653 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6655 gen_addq(s
, tmp64
, rd
, rn
);
6656 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6658 /* smuad, smusd, smlad, smlsd */
6661 tmp2
= load_reg(s
, rd
);
6662 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6665 store_reg(s
, rn
, tmp
);
6670 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6672 case 0: /* Unsigned sum of absolute differences. */
6674 tmp
= load_reg(s
, rm
);
6675 tmp2
= load_reg(s
, rs
);
6676 gen_helper_usad8(tmp
, tmp
, tmp2
);
6679 tmp2
= load_reg(s
, rd
);
6680 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6683 store_reg(s
, rn
, tmp
);
6685 case 0x20: case 0x24: case 0x28: case 0x2c:
6686 /* Bitfield insert/clear. */
6688 shift
= (insn
>> 7) & 0x1f;
6689 i
= (insn
>> 16) & 0x1f;
6693 tcg_gen_movi_i32(tmp
, 0);
6695 tmp
= load_reg(s
, rm
);
6698 tmp2
= load_reg(s
, rd
);
6699 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6702 store_reg(s
, rd
, tmp
);
6704 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6705 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6707 tmp
= load_reg(s
, rm
);
6708 shift
= (insn
>> 7) & 0x1f;
6709 i
= ((insn
>> 16) & 0x1f) + 1;
6714 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6716 gen_sbfx(tmp
, shift
, i
);
6719 store_reg(s
, rd
, tmp
);
6729 /* Check for undefined extension instructions
6730 * per the ARM Bible IE:
6731 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6733 sh
= (0xf << 20) | (0xf << 4);
6734 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6738 /* load/store byte/word */
6739 rn
= (insn
>> 16) & 0xf;
6740 rd
= (insn
>> 12) & 0xf;
6741 tmp2
= load_reg(s
, rn
);
6742 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6743 if (insn
& (1 << 24))
6744 gen_add_data_offset(s
, insn
, tmp2
);
6745 if (insn
& (1 << 20)) {
6747 if (insn
& (1 << 22)) {
6748 tmp
= gen_ld8u(tmp2
, i
);
6750 tmp
= gen_ld32(tmp2
, i
);
6754 tmp
= load_reg(s
, rd
);
6755 if (insn
& (1 << 22))
6756 gen_st8(tmp
, tmp2
, i
);
6758 gen_st32(tmp
, tmp2
, i
);
6760 if (!(insn
& (1 << 24))) {
6761 gen_add_data_offset(s
, insn
, tmp2
);
6762 store_reg(s
, rn
, tmp2
);
6763 } else if (insn
& (1 << 21)) {
6764 store_reg(s
, rn
, tmp2
);
6768 if (insn
& (1 << 20)) {
6769 /* Complete the load. */
6773 store_reg(s
, rd
, tmp
);
6779 int j
, n
, user
, loaded_base
;
6781 /* load/store multiple words */
6782 /* XXX: store correct base if write back */
6784 if (insn
& (1 << 22)) {
6786 goto illegal_op
; /* only usable in supervisor mode */
6788 if ((insn
& (1 << 15)) == 0)
6791 rn
= (insn
>> 16) & 0xf;
6792 addr
= load_reg(s
, rn
);
6794 /* compute total size */
6796 TCGV_UNUSED(loaded_var
);
6799 if (insn
& (1 << i
))
6802 /* XXX: test invalid n == 0 case ? */
6803 if (insn
& (1 << 23)) {
6804 if (insn
& (1 << 24)) {
6806 tcg_gen_addi_i32(addr
, addr
, 4);
6808 /* post increment */
6811 if (insn
& (1 << 24)) {
6813 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6815 /* post decrement */
6817 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6822 if (insn
& (1 << i
)) {
6823 if (insn
& (1 << 20)) {
6825 tmp
= gen_ld32(addr
, IS_USER(s
));
6829 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6831 } else if (i
== rn
) {
6835 store_reg(s
, i
, tmp
);
6840 /* special case: r15 = PC + 8 */
6841 val
= (long)s
->pc
+ 4;
6843 tcg_gen_movi_i32(tmp
, val
);
6846 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6848 tmp
= load_reg(s
, i
);
6850 gen_st32(tmp
, addr
, IS_USER(s
));
6853 /* no need to add after the last transfer */
6855 tcg_gen_addi_i32(addr
, addr
, 4);
6858 if (insn
& (1 << 21)) {
6860 if (insn
& (1 << 23)) {
6861 if (insn
& (1 << 24)) {
6864 /* post increment */
6865 tcg_gen_addi_i32(addr
, addr
, 4);
6868 if (insn
& (1 << 24)) {
6871 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6873 /* post decrement */
6874 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6877 store_reg(s
, rn
, addr
);
6882 store_reg(s
, rn
, loaded_var
);
6884 if ((insn
& (1 << 22)) && !user
) {
6885 /* Restore CPSR from SPSR. */
6886 tmp
= load_cpu_field(spsr
);
6887 gen_set_cpsr(tmp
, 0xffffffff);
6889 s
->is_jmp
= DISAS_UPDATE
;
6898 /* branch (and link) */
6899 val
= (int32_t)s
->pc
;
6900 if (insn
& (1 << 24)) {
6902 tcg_gen_movi_i32(tmp
, val
);
6903 store_reg(s
, 14, tmp
);
6905 offset
= (((int32_t)insn
<< 8) >> 8);
6906 val
+= (offset
<< 2) + 4;
6914 if (disas_coproc_insn(env
, s
, insn
))
6919 gen_set_pc_im(s
->pc
);
6920 s
->is_jmp
= DISAS_SWI
;
6924 gen_set_condexec(s
);
6925 gen_set_pc_im(s
->pc
- 4);
6926 gen_exception(EXCP_UDEF
);
6927 s
->is_jmp
= DISAS_JUMP
;
6933 /* Return true if this is a Thumb-2 logical op. */
6935 thumb2_logic_op(int op
)
6940 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6941 then set condition code flags based on the result of the operation.
6942 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6943 to the high bit of T1.
6944 Returns zero if the opcode is valid. */
6947 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6954 gen_op_andl_T0_T1();
6958 gen_op_bicl_T0_T1();
6971 gen_op_xorl_T0_T1();
6976 gen_op_addl_T0_T1_cc();
6978 gen_op_addl_T0_T1();
6982 gen_op_adcl_T0_T1_cc();
6988 gen_op_sbcl_T0_T1_cc();
6994 gen_op_subl_T0_T1_cc();
6996 gen_op_subl_T0_T1();
7000 gen_op_rsbl_T0_T1_cc();
7002 gen_op_rsbl_T0_T1();
7004 default: /* 5, 6, 7, 9, 12, 15. */
7008 gen_op_logic_T0_cc();
7010 gen_set_CF_bit31(cpu_T
[1]);
7015 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7017 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7019 uint32_t insn
, imm
, shift
, offset
;
7020 uint32_t rd
, rn
, rm
, rs
;
7031 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7032 || arm_feature (env
, ARM_FEATURE_M
))) {
7033 /* Thumb-1 cores may need to treat bl and blx as a pair of
7034 16-bit instructions to get correct prefetch abort behavior. */
7036 if ((insn
& (1 << 12)) == 0) {
7037 /* Second half of blx. */
7038 offset
= ((insn
& 0x7ff) << 1);
7039 tmp
= load_reg(s
, 14);
7040 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7041 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7044 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7045 store_reg(s
, 14, tmp2
);
7049 if (insn
& (1 << 11)) {
7050 /* Second half of bl. */
7051 offset
= ((insn
& 0x7ff) << 1) | 1;
7052 tmp
= load_reg(s
, 14);
7053 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7056 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7057 store_reg(s
, 14, tmp2
);
7061 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7062 /* Instruction spans a page boundary. Implement it as two
7063 16-bit instructions in case the second half causes an
7065 offset
= ((int32_t)insn
<< 21) >> 9;
7066 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
7067 gen_movl_reg_T0(s
, 14);
7070 /* Fall through to 32-bit decode. */
7073 insn
= lduw_code(s
->pc
);
7075 insn
|= (uint32_t)insn_hw1
<< 16;
7077 if ((insn
& 0xf800e800) != 0xf000e800) {
7081 rn
= (insn
>> 16) & 0xf;
7082 rs
= (insn
>> 12) & 0xf;
7083 rd
= (insn
>> 8) & 0xf;
7085 switch ((insn
>> 25) & 0xf) {
7086 case 0: case 1: case 2: case 3:
7087 /* 16-bit instructions. Should never happen. */
7090 if (insn
& (1 << 22)) {
7091 /* Other load/store, table branch. */
7092 if (insn
& 0x01200000) {
7093 /* Load/store doubleword. */
7096 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7098 addr
= load_reg(s
, rn
);
7100 offset
= (insn
& 0xff) * 4;
7101 if ((insn
& (1 << 23)) == 0)
7103 if (insn
& (1 << 24)) {
7104 tcg_gen_addi_i32(addr
, addr
, offset
);
7107 if (insn
& (1 << 20)) {
7109 tmp
= gen_ld32(addr
, IS_USER(s
));
7110 store_reg(s
, rs
, tmp
);
7111 tcg_gen_addi_i32(addr
, addr
, 4);
7112 tmp
= gen_ld32(addr
, IS_USER(s
));
7113 store_reg(s
, rd
, tmp
);
7116 tmp
= load_reg(s
, rs
);
7117 gen_st32(tmp
, addr
, IS_USER(s
));
7118 tcg_gen_addi_i32(addr
, addr
, 4);
7119 tmp
= load_reg(s
, rd
);
7120 gen_st32(tmp
, addr
, IS_USER(s
));
7122 if (insn
& (1 << 21)) {
7123 /* Base writeback. */
7126 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7127 store_reg(s
, rn
, addr
);
7131 } else if ((insn
& (1 << 23)) == 0) {
7132 /* Load/store exclusive word. */
7133 gen_movl_T1_reg(s
, rn
);
7135 if (insn
& (1 << 20)) {
7136 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
7137 tmp
= gen_ld32(addr
, IS_USER(s
));
7138 store_reg(s
, rd
, tmp
);
7140 int label
= gen_new_label();
7141 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7142 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
7144 tmp
= load_reg(s
, rs
);
7145 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7146 gen_set_label(label
);
7147 gen_movl_reg_T0(s
, rd
);
7149 } else if ((insn
& (1 << 6)) == 0) {
7153 tcg_gen_movi_i32(addr
, s
->pc
);
7155 addr
= load_reg(s
, rn
);
7157 tmp
= load_reg(s
, rm
);
7158 tcg_gen_add_i32(addr
, addr
, tmp
);
7159 if (insn
& (1 << 4)) {
7161 tcg_gen_add_i32(addr
, addr
, tmp
);
7163 tmp
= gen_ld16u(addr
, IS_USER(s
));
7166 tmp
= gen_ld8u(addr
, IS_USER(s
));
7169 tcg_gen_shli_i32(tmp
, tmp
, 1);
7170 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7171 store_reg(s
, 15, tmp
);
7173 /* Load/store exclusive byte/halfword/doubleword. */
7174 /* ??? These are not really atomic. However we know
7175 we never have multiple CPUs running in parallel,
7176 so it is good enough. */
7177 op
= (insn
>> 4) & 0x3;
7178 /* Must use a global reg for the address because we have
7179 a conditional branch in the store instruction. */
7180 gen_movl_T1_reg(s
, rn
);
7182 if (insn
& (1 << 20)) {
7183 gen_helper_mark_exclusive(cpu_env
, addr
);
7186 tmp
= gen_ld8u(addr
, IS_USER(s
));
7189 tmp
= gen_ld16u(addr
, IS_USER(s
));
7192 tmp
= gen_ld32(addr
, IS_USER(s
));
7193 tcg_gen_addi_i32(addr
, addr
, 4);
7194 tmp2
= gen_ld32(addr
, IS_USER(s
));
7195 store_reg(s
, rd
, tmp2
);
7200 store_reg(s
, rs
, tmp
);
7202 int label
= gen_new_label();
7203 /* Must use a global that is not killed by the branch. */
7204 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7205 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7206 tmp
= load_reg(s
, rs
);
7209 gen_st8(tmp
, addr
, IS_USER(s
));
7212 gen_st16(tmp
, addr
, IS_USER(s
));
7215 gen_st32(tmp
, addr
, IS_USER(s
));
7216 tcg_gen_addi_i32(addr
, addr
, 4);
7217 tmp
= load_reg(s
, rd
);
7218 gen_st32(tmp
, addr
, IS_USER(s
));
7223 gen_set_label(label
);
7224 gen_movl_reg_T0(s
, rm
);
7228 /* Load/store multiple, RFE, SRS. */
7229 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7230 /* Not available in user mode. */
7233 if (insn
& (1 << 20)) {
7235 addr
= load_reg(s
, rn
);
7236 if ((insn
& (1 << 24)) == 0)
7237 tcg_gen_addi_i32(addr
, addr
, -8);
7238 /* Load PC into tmp and CPSR into tmp2. */
7239 tmp
= gen_ld32(addr
, 0);
7240 tcg_gen_addi_i32(addr
, addr
, 4);
7241 tmp2
= gen_ld32(addr
, 0);
7242 if (insn
& (1 << 21)) {
7243 /* Base writeback. */
7244 if (insn
& (1 << 24)) {
7245 tcg_gen_addi_i32(addr
, addr
, 4);
7247 tcg_gen_addi_i32(addr
, addr
, -4);
7249 store_reg(s
, rn
, addr
);
7253 gen_rfe(s
, tmp
, tmp2
);
7257 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7258 addr
= load_reg(s
, 13);
7261 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7263 if ((insn
& (1 << 24)) == 0) {
7264 tcg_gen_addi_i32(addr
, addr
, -8);
7266 tmp
= load_reg(s
, 14);
7267 gen_st32(tmp
, addr
, 0);
7268 tcg_gen_addi_i32(addr
, addr
, 4);
7270 gen_helper_cpsr_read(tmp
);
7271 gen_st32(tmp
, addr
, 0);
7272 if (insn
& (1 << 21)) {
7273 if ((insn
& (1 << 24)) == 0) {
7274 tcg_gen_addi_i32(addr
, addr
, -4);
7276 tcg_gen_addi_i32(addr
, addr
, 4);
7278 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7279 store_reg(s
, 13, addr
);
7281 gen_helper_set_r13_banked(cpu_env
,
7282 tcg_const_i32(op
), addr
);
7290 /* Load/store multiple. */
7291 addr
= load_reg(s
, rn
);
7293 for (i
= 0; i
< 16; i
++) {
7294 if (insn
& (1 << i
))
7297 if (insn
& (1 << 24)) {
7298 tcg_gen_addi_i32(addr
, addr
, -offset
);
7301 for (i
= 0; i
< 16; i
++) {
7302 if ((insn
& (1 << i
)) == 0)
7304 if (insn
& (1 << 20)) {
7306 tmp
= gen_ld32(addr
, IS_USER(s
));
7310 store_reg(s
, i
, tmp
);
7314 tmp
= load_reg(s
, i
);
7315 gen_st32(tmp
, addr
, IS_USER(s
));
7317 tcg_gen_addi_i32(addr
, addr
, 4);
7319 if (insn
& (1 << 21)) {
7320 /* Base register writeback. */
7321 if (insn
& (1 << 24)) {
7322 tcg_gen_addi_i32(addr
, addr
, -offset
);
7324 /* Fault if writeback register is in register list. */
7325 if (insn
& (1 << rn
))
7327 store_reg(s
, rn
, addr
);
7334 case 5: /* Data processing register constant shift. */
7336 gen_op_movl_T0_im(0);
7338 gen_movl_T0_reg(s
, rn
);
7339 gen_movl_T1_reg(s
, rm
);
7340 op
= (insn
>> 21) & 0xf;
7341 shiftop
= (insn
>> 4) & 3;
7342 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7343 conds
= (insn
& (1 << 20)) != 0;
7344 logic_cc
= (conds
&& thumb2_logic_op(op
));
7345 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7346 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7349 gen_movl_reg_T0(s
, rd
);
7351 case 13: /* Misc data processing. */
7352 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7353 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7356 case 0: /* Register controlled shift. */
7357 tmp
= load_reg(s
, rn
);
7358 tmp2
= load_reg(s
, rm
);
7359 if ((insn
& 0x70) != 0)
7361 op
= (insn
>> 21) & 3;
7362 logic_cc
= (insn
& (1 << 20)) != 0;
7363 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7366 store_reg_bx(env
, s
, rd
, tmp
);
7368 case 1: /* Sign/zero extend. */
7369 tmp
= load_reg(s
, rm
);
7370 shift
= (insn
>> 4) & 3;
7371 /* ??? In many cases it's not neccessary to do a
7372 rotate, a shift is sufficient. */
7374 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7375 op
= (insn
>> 20) & 7;
7377 case 0: gen_sxth(tmp
); break;
7378 case 1: gen_uxth(tmp
); break;
7379 case 2: gen_sxtb16(tmp
); break;
7380 case 3: gen_uxtb16(tmp
); break;
7381 case 4: gen_sxtb(tmp
); break;
7382 case 5: gen_uxtb(tmp
); break;
7383 default: goto illegal_op
;
7386 tmp2
= load_reg(s
, rn
);
7387 if ((op
>> 1) == 1) {
7388 gen_add16(tmp
, tmp2
);
7390 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7394 store_reg(s
, rd
, tmp
);
7396 case 2: /* SIMD add/subtract. */
7397 op
= (insn
>> 20) & 7;
7398 shift
= (insn
>> 4) & 7;
7399 if ((op
& 3) == 3 || (shift
& 3) == 3)
7401 tmp
= load_reg(s
, rn
);
7402 tmp2
= load_reg(s
, rm
);
7403 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7405 store_reg(s
, rd
, tmp
);
7407 case 3: /* Other data processing. */
7408 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7410 /* Saturating add/subtract. */
7411 tmp
= load_reg(s
, rn
);
7412 tmp2
= load_reg(s
, rm
);
7414 gen_helper_double_saturate(tmp
, tmp
);
7416 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7418 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7421 tmp
= load_reg(s
, rn
);
7423 case 0x0a: /* rbit */
7424 gen_helper_rbit(tmp
, tmp
);
7426 case 0x08: /* rev */
7427 tcg_gen_bswap32_i32(tmp
, tmp
);
7429 case 0x09: /* rev16 */
7432 case 0x0b: /* revsh */
7435 case 0x10: /* sel */
7436 tmp2
= load_reg(s
, rm
);
7438 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7439 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7443 case 0x18: /* clz */
7444 gen_helper_clz(tmp
, tmp
);
7450 store_reg(s
, rd
, tmp
);
7452 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7453 op
= (insn
>> 4) & 0xf;
7454 tmp
= load_reg(s
, rn
);
7455 tmp2
= load_reg(s
, rm
);
7456 switch ((insn
>> 20) & 7) {
7457 case 0: /* 32 x 32 -> 32 */
7458 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7461 tmp2
= load_reg(s
, rs
);
7463 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7465 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7469 case 1: /* 16 x 16 -> 32 */
7470 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7473 tmp2
= load_reg(s
, rs
);
7474 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7478 case 2: /* Dual multiply add. */
7479 case 4: /* Dual multiply subtract. */
7481 gen_swap_half(tmp2
);
7482 gen_smul_dual(tmp
, tmp2
);
7483 /* This addition cannot overflow. */
7484 if (insn
& (1 << 22)) {
7485 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7487 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7492 tmp2
= load_reg(s
, rs
);
7493 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7497 case 3: /* 32 * 16 -> 32msb */
7499 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7502 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7503 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7505 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7508 tmp2
= load_reg(s
, rs
);
7509 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7513 case 5: case 6: /* 32 * 32 -> 32msb */
7514 gen_imull(tmp
, tmp2
);
7515 if (insn
& (1 << 5)) {
7516 gen_roundqd(tmp
, tmp2
);
7523 tmp2
= load_reg(s
, rs
);
7524 if (insn
& (1 << 21)) {
7525 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7527 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7532 case 7: /* Unsigned sum of absolute differences. */
7533 gen_helper_usad8(tmp
, tmp
, tmp2
);
7536 tmp2
= load_reg(s
, rs
);
7537 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7542 store_reg(s
, rd
, tmp
);
7544 case 6: case 7: /* 64-bit multiply, Divide. */
7545 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7546 tmp
= load_reg(s
, rn
);
7547 tmp2
= load_reg(s
, rm
);
7548 if ((op
& 0x50) == 0x10) {
7550 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7553 gen_helper_udiv(tmp
, tmp
, tmp2
);
7555 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7557 store_reg(s
, rd
, tmp
);
7558 } else if ((op
& 0xe) == 0xc) {
7559 /* Dual multiply accumulate long. */
7561 gen_swap_half(tmp2
);
7562 gen_smul_dual(tmp
, tmp2
);
7564 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7566 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7570 tmp64
= tcg_temp_new_i64();
7571 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7573 gen_addq(s
, tmp64
, rs
, rd
);
7574 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7577 /* Unsigned 64-bit multiply */
7578 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7582 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7584 tmp64
= tcg_temp_new_i64();
7585 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7588 /* Signed 64-bit multiply */
7589 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7594 gen_addq_lo(s
, tmp64
, rs
);
7595 gen_addq_lo(s
, tmp64
, rd
);
7596 } else if (op
& 0x40) {
7597 /* 64-bit accumulate. */
7598 gen_addq(s
, tmp64
, rs
, rd
);
7600 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7605 case 6: case 7: case 14: case 15:
7607 if (((insn
>> 24) & 3) == 3) {
7608 /* Translate into the equivalent ARM encoding. */
7609 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7610 if (disas_neon_data_insn(env
, s
, insn
))
7613 if (insn
& (1 << 28))
7615 if (disas_coproc_insn (env
, s
, insn
))
7619 case 8: case 9: case 10: case 11:
7620 if (insn
& (1 << 15)) {
7621 /* Branches, misc control. */
7622 if (insn
& 0x5000) {
7623 /* Unconditional branch. */
7624 /* signextend(hw1[10:0]) -> offset[:12]. */
7625 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7626 /* hw1[10:0] -> offset[11:1]. */
7627 offset
|= (insn
& 0x7ff) << 1;
7628 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7629 offset[24:22] already have the same value because of the
7630 sign extension above. */
7631 offset
^= ((~insn
) & (1 << 13)) << 10;
7632 offset
^= ((~insn
) & (1 << 11)) << 11;
7634 if (insn
& (1 << 14)) {
7635 /* Branch and link. */
7636 gen_op_movl_T1_im(s
->pc
| 1);
7637 gen_movl_reg_T1(s
, 14);
7641 if (insn
& (1 << 12)) {
7646 offset
&= ~(uint32_t)2;
7647 gen_bx_im(s
, offset
);
7649 } else if (((insn
>> 23) & 7) == 7) {
7651 if (insn
& (1 << 13))
7654 if (insn
& (1 << 26)) {
7655 /* Secure monitor call (v6Z) */
7656 goto illegal_op
; /* not implemented. */
7658 op
= (insn
>> 20) & 7;
7660 case 0: /* msr cpsr. */
7662 tmp
= load_reg(s
, rn
);
7663 addr
= tcg_const_i32(insn
& 0xff);
7664 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7669 case 1: /* msr spsr. */
7672 gen_movl_T0_reg(s
, rn
);
7673 if (gen_set_psr_T0(s
,
7674 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7678 case 2: /* cps, nop-hint. */
7679 if (((insn
>> 8) & 7) == 0) {
7680 gen_nop_hint(s
, insn
& 0xff);
7682 /* Implemented as NOP in user mode. */
7687 if (insn
& (1 << 10)) {
7688 if (insn
& (1 << 7))
7690 if (insn
& (1 << 6))
7692 if (insn
& (1 << 5))
7694 if (insn
& (1 << 9))
7695 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7697 if (insn
& (1 << 8)) {
7699 imm
|= (insn
& 0x1f);
7702 gen_op_movl_T0_im(imm
);
7703 gen_set_psr_T0(s
, offset
, 0);
7706 case 3: /* Special control operations. */
7707 op
= (insn
>> 4) & 0xf;
7710 gen_helper_clrex(cpu_env
);
7715 /* These execute as NOPs. */
7723 /* Trivial implementation equivalent to bx. */
7724 tmp
= load_reg(s
, rn
);
7727 case 5: /* Exception return. */
7728 /* Unpredictable in user mode. */
7730 case 6: /* mrs cpsr. */
7733 addr
= tcg_const_i32(insn
& 0xff);
7734 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7736 gen_helper_cpsr_read(tmp
);
7738 store_reg(s
, rd
, tmp
);
7740 case 7: /* mrs spsr. */
7741 /* Not accessible in user mode. */
7742 if (IS_USER(s
) || IS_M(env
))
7744 tmp
= load_cpu_field(spsr
);
7745 store_reg(s
, rd
, tmp
);
7750 /* Conditional branch. */
7751 op
= (insn
>> 22) & 0xf;
7752 /* Generate a conditional jump to next instruction. */
7753 s
->condlabel
= gen_new_label();
7754 gen_test_cc(op
^ 1, s
->condlabel
);
7757 /* offset[11:1] = insn[10:0] */
7758 offset
= (insn
& 0x7ff) << 1;
7759 /* offset[17:12] = insn[21:16]. */
7760 offset
|= (insn
& 0x003f0000) >> 4;
7761 /* offset[31:20] = insn[26]. */
7762 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7763 /* offset[18] = insn[13]. */
7764 offset
|= (insn
& (1 << 13)) << 5;
7765 /* offset[19] = insn[11]. */
7766 offset
|= (insn
& (1 << 11)) << 8;
7768 /* jump to the offset */
7769 gen_jmp(s
, s
->pc
+ offset
);
7772 /* Data processing immediate. */
7773 if (insn
& (1 << 25)) {
7774 if (insn
& (1 << 24)) {
7775 if (insn
& (1 << 20))
7777 /* Bitfield/Saturate. */
7778 op
= (insn
>> 21) & 7;
7780 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7783 tcg_gen_movi_i32(tmp
, 0);
7785 tmp
= load_reg(s
, rn
);
7788 case 2: /* Signed bitfield extract. */
7790 if (shift
+ imm
> 32)
7793 gen_sbfx(tmp
, shift
, imm
);
7795 case 6: /* Unsigned bitfield extract. */
7797 if (shift
+ imm
> 32)
7800 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7802 case 3: /* Bitfield insert/clear. */
7805 imm
= imm
+ 1 - shift
;
7807 tmp2
= load_reg(s
, rd
);
7808 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7814 default: /* Saturate. */
7817 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7819 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7821 tmp2
= tcg_const_i32(imm
);
7824 if ((op
& 1) && shift
== 0)
7825 gen_helper_usat16(tmp
, tmp
, tmp2
);
7827 gen_helper_usat(tmp
, tmp
, tmp2
);
7830 if ((op
& 1) && shift
== 0)
7831 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7833 gen_helper_ssat(tmp
, tmp
, tmp2
);
7837 store_reg(s
, rd
, tmp
);
7839 imm
= ((insn
& 0x04000000) >> 15)
7840 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7841 if (insn
& (1 << 22)) {
7842 /* 16-bit immediate. */
7843 imm
|= (insn
>> 4) & 0xf000;
7844 if (insn
& (1 << 23)) {
7846 tmp
= load_reg(s
, rd
);
7847 tcg_gen_ext16u_i32(tmp
, tmp
);
7848 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7852 tcg_gen_movi_i32(tmp
, imm
);
7855 /* Add/sub 12-bit immediate. */
7857 offset
= s
->pc
& ~(uint32_t)3;
7858 if (insn
& (1 << 23))
7863 tcg_gen_movi_i32(tmp
, offset
);
7865 tmp
= load_reg(s
, rn
);
7866 if (insn
& (1 << 23))
7867 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7869 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7872 store_reg(s
, rd
, tmp
);
7875 int shifter_out
= 0;
7876 /* modified 12-bit immediate. */
7877 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7878 imm
= (insn
& 0xff);
7881 /* Nothing to do. */
7883 case 1: /* 00XY00XY */
7886 case 2: /* XY00XY00 */
7890 case 3: /* XYXYXYXY */
7894 default: /* Rotated constant. */
7895 shift
= (shift
<< 1) | (imm
>> 7);
7897 imm
= imm
<< (32 - shift
);
7901 gen_op_movl_T1_im(imm
);
7902 rn
= (insn
>> 16) & 0xf;
7904 gen_op_movl_T0_im(0);
7906 gen_movl_T0_reg(s
, rn
);
7907 op
= (insn
>> 21) & 0xf;
7908 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7911 rd
= (insn
>> 8) & 0xf;
7913 gen_movl_reg_T0(s
, rd
);
7918 case 12: /* Load/store single data item. */
7923 if ((insn
& 0x01100000) == 0x01000000) {
7924 if (disas_neon_ls_insn(env
, s
, insn
))
7932 /* s->pc has already been incremented by 4. */
7933 imm
= s
->pc
& 0xfffffffc;
7934 if (insn
& (1 << 23))
7935 imm
+= insn
& 0xfff;
7937 imm
-= insn
& 0xfff;
7938 tcg_gen_movi_i32(addr
, imm
);
7940 addr
= load_reg(s
, rn
);
7941 if (insn
& (1 << 23)) {
7942 /* Positive offset. */
7944 tcg_gen_addi_i32(addr
, addr
, imm
);
7946 op
= (insn
>> 8) & 7;
7949 case 0: case 8: /* Shifted Register. */
7950 shift
= (insn
>> 4) & 0xf;
7953 tmp
= load_reg(s
, rm
);
7955 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7956 tcg_gen_add_i32(addr
, addr
, tmp
);
7959 case 4: /* Negative offset. */
7960 tcg_gen_addi_i32(addr
, addr
, -imm
);
7962 case 6: /* User privilege. */
7963 tcg_gen_addi_i32(addr
, addr
, imm
);
7966 case 1: /* Post-decrement. */
7969 case 3: /* Post-increment. */
7973 case 5: /* Pre-decrement. */
7976 case 7: /* Pre-increment. */
7977 tcg_gen_addi_i32(addr
, addr
, imm
);
7985 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7986 if (insn
& (1 << 20)) {
7988 if (rs
== 15 && op
!= 2) {
7991 /* Memory hint. Implemented as NOP. */
7994 case 0: tmp
= gen_ld8u(addr
, user
); break;
7995 case 4: tmp
= gen_ld8s(addr
, user
); break;
7996 case 1: tmp
= gen_ld16u(addr
, user
); break;
7997 case 5: tmp
= gen_ld16s(addr
, user
); break;
7998 case 2: tmp
= gen_ld32(addr
, user
); break;
7999 default: goto illegal_op
;
8004 store_reg(s
, rs
, tmp
);
8011 tmp
= load_reg(s
, rs
);
8013 case 0: gen_st8(tmp
, addr
, user
); break;
8014 case 1: gen_st16(tmp
, addr
, user
); break;
8015 case 2: gen_st32(tmp
, addr
, user
); break;
8016 default: goto illegal_op
;
8020 tcg_gen_addi_i32(addr
, addr
, imm
);
8022 store_reg(s
, rn
, addr
);
8036 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8038 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8045 if (s
->condexec_mask
) {
8046 cond
= s
->condexec_cond
;
8047 s
->condlabel
= gen_new_label();
8048 gen_test_cc(cond
^ 1, s
->condlabel
);
8052 insn
= lduw_code(s
->pc
);
8055 switch (insn
>> 12) {
8058 op
= (insn
>> 11) & 3;
8061 rn
= (insn
>> 3) & 7;
8062 gen_movl_T0_reg(s
, rn
);
8063 if (insn
& (1 << 10)) {
8065 gen_op_movl_T1_im((insn
>> 6) & 7);
8068 rm
= (insn
>> 6) & 7;
8069 gen_movl_T1_reg(s
, rm
);
8071 if (insn
& (1 << 9)) {
8072 if (s
->condexec_mask
)
8073 gen_op_subl_T0_T1();
8075 gen_op_subl_T0_T1_cc();
8077 if (s
->condexec_mask
)
8078 gen_op_addl_T0_T1();
8080 gen_op_addl_T0_T1_cc();
8082 gen_movl_reg_T0(s
, rd
);
8084 /* shift immediate */
8085 rm
= (insn
>> 3) & 7;
8086 shift
= (insn
>> 6) & 0x1f;
8087 tmp
= load_reg(s
, rm
);
8088 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8089 if (!s
->condexec_mask
)
8091 store_reg(s
, rd
, tmp
);
8095 /* arithmetic large immediate */
8096 op
= (insn
>> 11) & 3;
8097 rd
= (insn
>> 8) & 0x7;
8099 gen_op_movl_T0_im(insn
& 0xff);
8101 gen_movl_T0_reg(s
, rd
);
8102 gen_op_movl_T1_im(insn
& 0xff);
8106 if (!s
->condexec_mask
)
8107 gen_op_logic_T0_cc();
8110 gen_op_subl_T0_T1_cc();
8113 if (s
->condexec_mask
)
8114 gen_op_addl_T0_T1();
8116 gen_op_addl_T0_T1_cc();
8119 if (s
->condexec_mask
)
8120 gen_op_subl_T0_T1();
8122 gen_op_subl_T0_T1_cc();
8126 gen_movl_reg_T0(s
, rd
);
8129 if (insn
& (1 << 11)) {
8130 rd
= (insn
>> 8) & 7;
8131 /* load pc-relative. Bit 1 of PC is ignored. */
8132 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8133 val
&= ~(uint32_t)2;
8135 tcg_gen_movi_i32(addr
, val
);
8136 tmp
= gen_ld32(addr
, IS_USER(s
));
8138 store_reg(s
, rd
, tmp
);
8141 if (insn
& (1 << 10)) {
8142 /* data processing extended or blx */
8143 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8144 rm
= (insn
>> 3) & 0xf;
8145 op
= (insn
>> 8) & 3;
8148 gen_movl_T0_reg(s
, rd
);
8149 gen_movl_T1_reg(s
, rm
);
8150 gen_op_addl_T0_T1();
8151 gen_movl_reg_T0(s
, rd
);
8154 gen_movl_T0_reg(s
, rd
);
8155 gen_movl_T1_reg(s
, rm
);
8156 gen_op_subl_T0_T1_cc();
8158 case 2: /* mov/cpy */
8159 gen_movl_T0_reg(s
, rm
);
8160 gen_movl_reg_T0(s
, rd
);
8162 case 3:/* branch [and link] exchange thumb register */
8163 tmp
= load_reg(s
, rm
);
8164 if (insn
& (1 << 7)) {
8165 val
= (uint32_t)s
->pc
| 1;
8167 tcg_gen_movi_i32(tmp2
, val
);
8168 store_reg(s
, 14, tmp2
);
8176 /* data processing register */
8178 rm
= (insn
>> 3) & 7;
8179 op
= (insn
>> 6) & 0xf;
8180 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8181 /* the shift/rotate ops want the operands backwards */
8190 if (op
== 9) /* neg */
8191 gen_op_movl_T0_im(0);
8192 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8193 gen_movl_T0_reg(s
, rd
);
8195 gen_movl_T1_reg(s
, rm
);
8198 gen_op_andl_T0_T1();
8199 if (!s
->condexec_mask
)
8200 gen_op_logic_T0_cc();
8203 gen_op_xorl_T0_T1();
8204 if (!s
->condexec_mask
)
8205 gen_op_logic_T0_cc();
8208 if (s
->condexec_mask
) {
8209 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8211 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8212 gen_op_logic_T1_cc();
8216 if (s
->condexec_mask
) {
8217 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8219 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8220 gen_op_logic_T1_cc();
8224 if (s
->condexec_mask
) {
8225 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8227 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8228 gen_op_logic_T1_cc();
8232 if (s
->condexec_mask
)
8235 gen_op_adcl_T0_T1_cc();
8238 if (s
->condexec_mask
)
8241 gen_op_sbcl_T0_T1_cc();
8244 if (s
->condexec_mask
) {
8245 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8247 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8248 gen_op_logic_T1_cc();
8252 gen_op_andl_T0_T1();
8253 gen_op_logic_T0_cc();
8257 if (s
->condexec_mask
)
8258 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8260 gen_op_subl_T0_T1_cc();
8263 gen_op_subl_T0_T1_cc();
8267 gen_op_addl_T0_T1_cc();
8272 if (!s
->condexec_mask
)
8273 gen_op_logic_T0_cc();
8276 gen_op_mull_T0_T1();
8277 if (!s
->condexec_mask
)
8278 gen_op_logic_T0_cc();
8281 gen_op_bicl_T0_T1();
8282 if (!s
->condexec_mask
)
8283 gen_op_logic_T0_cc();
8287 if (!s
->condexec_mask
)
8288 gen_op_logic_T1_cc();
8295 gen_movl_reg_T1(s
, rm
);
8297 gen_movl_reg_T0(s
, rd
);
8302 /* load/store register offset. */
8304 rn
= (insn
>> 3) & 7;
8305 rm
= (insn
>> 6) & 7;
8306 op
= (insn
>> 9) & 7;
8307 addr
= load_reg(s
, rn
);
8308 tmp
= load_reg(s
, rm
);
8309 tcg_gen_add_i32(addr
, addr
, tmp
);
8312 if (op
< 3) /* store */
8313 tmp
= load_reg(s
, rd
);
8317 gen_st32(tmp
, addr
, IS_USER(s
));
8320 gen_st16(tmp
, addr
, IS_USER(s
));
8323 gen_st8(tmp
, addr
, IS_USER(s
));
8326 tmp
= gen_ld8s(addr
, IS_USER(s
));
8329 tmp
= gen_ld32(addr
, IS_USER(s
));
8332 tmp
= gen_ld16u(addr
, IS_USER(s
));
8335 tmp
= gen_ld8u(addr
, IS_USER(s
));
8338 tmp
= gen_ld16s(addr
, IS_USER(s
));
8341 if (op
>= 3) /* load */
8342 store_reg(s
, rd
, tmp
);
8347 /* load/store word immediate offset */
8349 rn
= (insn
>> 3) & 7;
8350 addr
= load_reg(s
, rn
);
8351 val
= (insn
>> 4) & 0x7c;
8352 tcg_gen_addi_i32(addr
, addr
, val
);
8354 if (insn
& (1 << 11)) {
8356 tmp
= gen_ld32(addr
, IS_USER(s
));
8357 store_reg(s
, rd
, tmp
);
8360 tmp
= load_reg(s
, rd
);
8361 gen_st32(tmp
, addr
, IS_USER(s
));
8367 /* load/store byte immediate offset */
8369 rn
= (insn
>> 3) & 7;
8370 addr
= load_reg(s
, rn
);
8371 val
= (insn
>> 6) & 0x1f;
8372 tcg_gen_addi_i32(addr
, addr
, val
);
8374 if (insn
& (1 << 11)) {
8376 tmp
= gen_ld8u(addr
, IS_USER(s
));
8377 store_reg(s
, rd
, tmp
);
8380 tmp
= load_reg(s
, rd
);
8381 gen_st8(tmp
, addr
, IS_USER(s
));
8387 /* load/store halfword immediate offset */
8389 rn
= (insn
>> 3) & 7;
8390 addr
= load_reg(s
, rn
);
8391 val
= (insn
>> 5) & 0x3e;
8392 tcg_gen_addi_i32(addr
, addr
, val
);
8394 if (insn
& (1 << 11)) {
8396 tmp
= gen_ld16u(addr
, IS_USER(s
));
8397 store_reg(s
, rd
, tmp
);
8400 tmp
= load_reg(s
, rd
);
8401 gen_st16(tmp
, addr
, IS_USER(s
));
8407 /* load/store from stack */
8408 rd
= (insn
>> 8) & 7;
8409 addr
= load_reg(s
, 13);
8410 val
= (insn
& 0xff) * 4;
8411 tcg_gen_addi_i32(addr
, addr
, val
);
8413 if (insn
& (1 << 11)) {
8415 tmp
= gen_ld32(addr
, IS_USER(s
));
8416 store_reg(s
, rd
, tmp
);
8419 tmp
= load_reg(s
, rd
);
8420 gen_st32(tmp
, addr
, IS_USER(s
));
8426 /* add to high reg */
8427 rd
= (insn
>> 8) & 7;
8428 if (insn
& (1 << 11)) {
8430 tmp
= load_reg(s
, 13);
8432 /* PC. bit 1 is ignored. */
8434 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8436 val
= (insn
& 0xff) * 4;
8437 tcg_gen_addi_i32(tmp
, tmp
, val
);
8438 store_reg(s
, rd
, tmp
);
8443 op
= (insn
>> 8) & 0xf;
8446 /* adjust stack pointer */
8447 tmp
= load_reg(s
, 13);
8448 val
= (insn
& 0x7f) * 4;
8449 if (insn
& (1 << 7))
8450 val
= -(int32_t)val
;
8451 tcg_gen_addi_i32(tmp
, tmp
, val
);
8452 store_reg(s
, 13, tmp
);
8455 case 2: /* sign/zero extend. */
8458 rm
= (insn
>> 3) & 7;
8459 tmp
= load_reg(s
, rm
);
8460 switch ((insn
>> 6) & 3) {
8461 case 0: gen_sxth(tmp
); break;
8462 case 1: gen_sxtb(tmp
); break;
8463 case 2: gen_uxth(tmp
); break;
8464 case 3: gen_uxtb(tmp
); break;
8466 store_reg(s
, rd
, tmp
);
8468 case 4: case 5: case 0xc: case 0xd:
8470 addr
= load_reg(s
, 13);
8471 if (insn
& (1 << 8))
8475 for (i
= 0; i
< 8; i
++) {
8476 if (insn
& (1 << i
))
8479 if ((insn
& (1 << 11)) == 0) {
8480 tcg_gen_addi_i32(addr
, addr
, -offset
);
8482 for (i
= 0; i
< 8; i
++) {
8483 if (insn
& (1 << i
)) {
8484 if (insn
& (1 << 11)) {
8486 tmp
= gen_ld32(addr
, IS_USER(s
));
8487 store_reg(s
, i
, tmp
);
8490 tmp
= load_reg(s
, i
);
8491 gen_st32(tmp
, addr
, IS_USER(s
));
8493 /* advance to the next address. */
8494 tcg_gen_addi_i32(addr
, addr
, 4);
8498 if (insn
& (1 << 8)) {
8499 if (insn
& (1 << 11)) {
8501 tmp
= gen_ld32(addr
, IS_USER(s
));
8502 /* don't set the pc until the rest of the instruction
8506 tmp
= load_reg(s
, 14);
8507 gen_st32(tmp
, addr
, IS_USER(s
));
8509 tcg_gen_addi_i32(addr
, addr
, 4);
8511 if ((insn
& (1 << 11)) == 0) {
8512 tcg_gen_addi_i32(addr
, addr
, -offset
);
8514 /* write back the new stack pointer */
8515 store_reg(s
, 13, addr
);
8516 /* set the new PC value */
8517 if ((insn
& 0x0900) == 0x0900)
8521 case 1: case 3: case 9: case 11: /* czb */
8523 tmp
= load_reg(s
, rm
);
8524 s
->condlabel
= gen_new_label();
8526 if (insn
& (1 << 11))
8527 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8529 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8531 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8532 val
= (uint32_t)s
->pc
+ 2;
8537 case 15: /* IT, nop-hint. */
8538 if ((insn
& 0xf) == 0) {
8539 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8543 s
->condexec_cond
= (insn
>> 4) & 0xe;
8544 s
->condexec_mask
= insn
& 0x1f;
8545 /* No actual code generated for this insn, just setup state. */
8548 case 0xe: /* bkpt */
8549 gen_set_condexec(s
);
8550 gen_set_pc_im(s
->pc
- 2);
8551 gen_exception(EXCP_BKPT
);
8552 s
->is_jmp
= DISAS_JUMP
;
8557 rn
= (insn
>> 3) & 0x7;
8559 tmp
= load_reg(s
, rn
);
8560 switch ((insn
>> 6) & 3) {
8561 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8562 case 1: gen_rev16(tmp
); break;
8563 case 3: gen_revsh(tmp
); break;
8564 default: goto illegal_op
;
8566 store_reg(s
, rd
, tmp
);
8574 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8577 addr
= tcg_const_i32(16);
8578 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8582 addr
= tcg_const_i32(17);
8583 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8587 if (insn
& (1 << 4))
8588 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8592 val
= ((insn
& 7) << 6) & shift
;
8593 gen_op_movl_T0_im(val
);
8594 gen_set_psr_T0(s
, shift
, 0);
8604 /* load/store multiple */
8605 rn
= (insn
>> 8) & 0x7;
8606 addr
= load_reg(s
, rn
);
8607 for (i
= 0; i
< 8; i
++) {
8608 if (insn
& (1 << i
)) {
8609 if (insn
& (1 << 11)) {
8611 tmp
= gen_ld32(addr
, IS_USER(s
));
8612 store_reg(s
, i
, tmp
);
8615 tmp
= load_reg(s
, i
);
8616 gen_st32(tmp
, addr
, IS_USER(s
));
8618 /* advance to the next address */
8619 tcg_gen_addi_i32(addr
, addr
, 4);
8622 /* Base register writeback. */
8623 if ((insn
& (1 << rn
)) == 0) {
8624 store_reg(s
, rn
, addr
);
8631 /* conditional branch or swi */
8632 cond
= (insn
>> 8) & 0xf;
8638 gen_set_condexec(s
);
8639 gen_set_pc_im(s
->pc
);
8640 s
->is_jmp
= DISAS_SWI
;
8643 /* generate a conditional jump to next instruction */
8644 s
->condlabel
= gen_new_label();
8645 gen_test_cc(cond
^ 1, s
->condlabel
);
8647 gen_movl_T1_reg(s
, 15);
8649 /* jump to the offset */
8650 val
= (uint32_t)s
->pc
+ 2;
8651 offset
= ((int32_t)insn
<< 24) >> 24;
8657 if (insn
& (1 << 11)) {
8658 if (disas_thumb2_insn(env
, s
, insn
))
8662 /* unconditional branch */
8663 val
= (uint32_t)s
->pc
;
8664 offset
= ((int32_t)insn
<< 21) >> 21;
8665 val
+= (offset
<< 1) + 2;
8670 if (disas_thumb2_insn(env
, s
, insn
))
8676 gen_set_condexec(s
);
8677 gen_set_pc_im(s
->pc
- 4);
8678 gen_exception(EXCP_UDEF
);
8679 s
->is_jmp
= DISAS_JUMP
;
8683 gen_set_condexec(s
);
8684 gen_set_pc_im(s
->pc
- 2);
8685 gen_exception(EXCP_UDEF
);
8686 s
->is_jmp
= DISAS_JUMP
;
8689 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8690 basic block 'tb'. If search_pc is TRUE, also generate PC
8691 information for each intermediate instruction. */
8692 static inline void gen_intermediate_code_internal(CPUState
*env
,
8693 TranslationBlock
*tb
,
8696 DisasContext dc1
, *dc
= &dc1
;
8698 uint16_t *gen_opc_end
;
8700 target_ulong pc_start
;
8701 uint32_t next_page_start
;
8705 /* generate intermediate code */
8707 memset(temps
, 0, sizeof(temps
));
8713 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8715 dc
->is_jmp
= DISAS_NEXT
;
8717 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8719 dc
->thumb
= env
->thumb
;
8720 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8721 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8722 #if !defined(CONFIG_USER_ONLY)
8724 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8726 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8729 cpu_F0s
= tcg_temp_new_i32();
8730 cpu_F1s
= tcg_temp_new_i32();
8731 cpu_F0d
= tcg_temp_new_i64();
8732 cpu_F1d
= tcg_temp_new_i64();
8735 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8736 cpu_M0
= tcg_temp_new_i64();
8737 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8740 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8742 max_insns
= CF_COUNT_MASK
;
8745 /* Reset the conditional execution bits immediately. This avoids
8746 complications trying to do it at the end of the block. */
8747 if (env
->condexec_bits
)
8749 TCGv tmp
= new_tmp();
8750 tcg_gen_movi_i32(tmp
, 0);
8751 store_cpu_field(tmp
, condexec_bits
);
8754 #ifdef CONFIG_USER_ONLY
8755 /* Intercept jump to the magic kernel page. */
8756 if (dc
->pc
>= 0xffff0000) {
8757 /* We always get here via a jump, so know we are not in a
8758 conditional execution block. */
8759 gen_exception(EXCP_KERNEL_TRAP
);
8760 dc
->is_jmp
= DISAS_UPDATE
;
8764 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8765 /* We always get here via a jump, so know we are not in a
8766 conditional execution block. */
8767 gen_exception(EXCP_EXCEPTION_EXIT
);
8768 dc
->is_jmp
= DISAS_UPDATE
;
8773 if (unlikely(!TAILQ_EMPTY(&env
->breakpoints
))) {
8774 TAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8775 if (bp
->pc
== dc
->pc
) {
8776 gen_set_condexec(dc
);
8777 gen_set_pc_im(dc
->pc
);
8778 gen_exception(EXCP_DEBUG
);
8779 dc
->is_jmp
= DISAS_JUMP
;
8780 /* Advance PC so that clearing the breakpoint will
8781 invalidate this TB. */
8783 goto done_generating
;
8789 j
= gen_opc_ptr
- gen_opc_buf
;
8793 gen_opc_instr_start
[lj
++] = 0;
8795 gen_opc_pc
[lj
] = dc
->pc
;
8796 gen_opc_instr_start
[lj
] = 1;
8797 gen_opc_icount
[lj
] = num_insns
;
8800 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8804 disas_thumb_insn(env
, dc
);
8805 if (dc
->condexec_mask
) {
8806 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8807 | ((dc
->condexec_mask
>> 4) & 1);
8808 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8809 if (dc
->condexec_mask
== 0) {
8810 dc
->condexec_cond
= 0;
8814 disas_arm_insn(env
, dc
);
8817 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8821 if (dc
->condjmp
&& !dc
->is_jmp
) {
8822 gen_set_label(dc
->condlabel
);
8825 /* Translation stops when a conditional branch is encountered.
8826 * Otherwise the subsequent code could get translated several times.
8827 * Also stop translation when a page boundary is reached. This
8828 * ensures prefetch aborts occur at the right place. */
8830 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8831 !env
->singlestep_enabled
&&
8833 dc
->pc
< next_page_start
&&
8834 num_insns
< max_insns
);
8836 if (tb
->cflags
& CF_LAST_IO
) {
8838 /* FIXME: This can theoretically happen with self-modifying
8840 cpu_abort(env
, "IO on conditional branch instruction");
8845 /* At this stage dc->condjmp will only be set when the skipped
8846 instruction was a conditional branch or trap, and the PC has
8847 already been written. */
8848 if (unlikely(env
->singlestep_enabled
)) {
8849 /* Make sure the pc is updated, and raise a debug exception. */
8851 gen_set_condexec(dc
);
8852 if (dc
->is_jmp
== DISAS_SWI
) {
8853 gen_exception(EXCP_SWI
);
8855 gen_exception(EXCP_DEBUG
);
8857 gen_set_label(dc
->condlabel
);
8859 if (dc
->condjmp
|| !dc
->is_jmp
) {
8860 gen_set_pc_im(dc
->pc
);
8863 gen_set_condexec(dc
);
8864 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8865 gen_exception(EXCP_SWI
);
8867 /* FIXME: Single stepping a WFI insn will not halt
8869 gen_exception(EXCP_DEBUG
);
8872 /* While branches must always occur at the end of an IT block,
8873 there are a few other things that can cause us to terminate
8874 the TB in the middel of an IT block:
8875 - Exception generating instructions (bkpt, swi, undefined).
8877 - Hardware watchpoints.
8878 Hardware breakpoints have already been handled and skip this code.
8880 gen_set_condexec(dc
);
8881 switch(dc
->is_jmp
) {
8883 gen_goto_tb(dc
, 1, dc
->pc
);
8888 /* indicate that the hash table must be used to find the next TB */
8892 /* nothing more to generate */
8898 gen_exception(EXCP_SWI
);
8902 gen_set_label(dc
->condlabel
);
8903 gen_set_condexec(dc
);
8904 gen_goto_tb(dc
, 1, dc
->pc
);
8910 gen_icount_end(tb
, num_insns
);
8911 *gen_opc_ptr
= INDEX_op_end
;
8914 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8915 qemu_log("----------------\n");
8916 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8917 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8922 j
= gen_opc_ptr
- gen_opc_buf
;
8925 gen_opc_instr_start
[lj
++] = 0;
8927 tb
->size
= dc
->pc
- pc_start
;
8928 tb
->icount
= num_insns
;
8932 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8934 gen_intermediate_code_internal(env
, tb
, 0);
8937 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8939 gen_intermediate_code_internal(env
, tb
, 1);
8942 static const char *cpu_mode_names
[16] = {
8943 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8944 "???", "???", "???", "und", "???", "???", "???", "sys"
8947 void cpu_dump_state(CPUState
*env
, FILE *f
,
8948 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8958 /* ??? This assumes float64 and double have the same layout.
8959 Oh well, it's only debug dumps. */
8968 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8970 cpu_fprintf(f
, "\n");
8972 cpu_fprintf(f
, " ");
8974 psr
= cpsr_read(env
);
8975 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8977 psr
& (1 << 31) ? 'N' : '-',
8978 psr
& (1 << 30) ? 'Z' : '-',
8979 psr
& (1 << 29) ? 'C' : '-',
8980 psr
& (1 << 28) ? 'V' : '-',
8981 psr
& CPSR_T
? 'T' : 'A',
8982 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8985 for (i
= 0; i
< 16; i
++) {
8986 d
.d
= env
->vfp
.regs
[i
];
8990 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8991 i
* 2, (int)s0
.i
, s0
.s
,
8992 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8993 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8996 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9000 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9001 unsigned long searched_pc
, int pc_pos
, void *puc
)
9003 env
->regs
[15] = gen_opc_pc
[pc_pos
];