]>
git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
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, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #define ENABLE_ARCH_5J 0
37 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
38 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
39 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
40 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
42 #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
44 /* internal defines */
45 typedef struct DisasContext
{
48 /* Nonzero if this instruction has been conditionally skipped. */
50 /* The label that will be jumped to when the instruction is skipped. */
52 /* Thumb-2 condtional execution bits. */
55 struct TranslationBlock
*tb
;
56 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 /* XXX: move that elsewhere */
80 /* We reuse the same 64-bit temporaries for efficiency. */
81 static TCGv cpu_V0
, cpu_V1
, cpu_M0
;
83 /* FIXME: These should be removed. */
85 static TCGv cpu_F0s
, cpu_F1s
, cpu_F0d
, cpu_F1d
;
87 /* initialize TCG globals. */
88 void arm_translate_init(void)
90 cpu_env
= tcg_global_reg_new(TCG_TYPE_PTR
, TCG_AREG0
, "env");
92 cpu_T
[0] = tcg_global_reg_new(TCG_TYPE_I32
, TCG_AREG1
, "T0");
93 cpu_T
[1] = tcg_global_reg_new(TCG_TYPE_I32
, TCG_AREG2
, "T1");
96 /* The code generator doesn't like lots of temporaries, so maintain our own
97 cache for reuse within a function. */
100 static TCGv temps
[MAX_TEMPS
];
102 /* Allocate a temporary variable. */
103 static TCGv
new_tmp(void)
106 if (num_temps
== MAX_TEMPS
)
109 if (GET_TCGV(temps
[num_temps
]))
110 return temps
[num_temps
++];
112 tmp
= tcg_temp_new(TCG_TYPE_I32
);
113 temps
[num_temps
++] = tmp
;
117 /* Release a temporary variable. */
118 static void dead_tmp(TCGv tmp
)
123 if (GET_TCGV(temps
[i
]) == GET_TCGV(tmp
))
126 /* Shuffle this temp to the last slot. */
127 while (GET_TCGV(temps
[i
]) != GET_TCGV(tmp
))
129 while (i
< num_temps
) {
130 temps
[i
] = temps
[i
+ 1];
136 static inline TCGv
load_cpu_offset(int offset
)
138 TCGv tmp
= new_tmp();
139 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
143 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
145 static inline void store_cpu_offset(TCGv var
, int offset
)
147 tcg_gen_st_i32(var
, cpu_env
, offset
);
151 #define store_cpu_field(var, name) \
152 store_cpu_offset(var, offsetof(CPUState, name))
154 /* Set a variable to the value of a CPU register. */
155 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
159 /* normaly, since we updated PC, we need only to add one insn */
161 addr
= (long)s
->pc
+ 2;
163 addr
= (long)s
->pc
+ 4;
164 tcg_gen_movi_i32(var
, addr
);
166 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
170 /* Create a new temporary and set it to the value of a CPU register. */
171 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
173 TCGv tmp
= new_tmp();
174 load_reg_var(s
, tmp
, reg
);
178 /* Set a CPU register. The source must be a temporary and will be
180 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
183 tcg_gen_andi_i32(var
, var
, ~1);
184 s
->is_jmp
= DISAS_JUMP
;
186 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
191 /* Basic operations. */
192 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
193 #define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
194 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
195 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
197 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
198 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
199 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
200 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
202 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
203 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
204 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
205 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
207 #define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
209 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
210 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
213 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
214 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
215 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
217 #define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
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)
220 #define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
221 #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
223 /* Value extensions. */
224 #define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
225 #define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
226 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
227 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
229 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
230 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
232 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
234 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
235 /* Set NZCV flags from the high 4 bits of var. */
236 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
238 static void gen_exception(int excp
)
240 TCGv tmp
= new_tmp();
241 tcg_gen_movi_i32(tmp
, excp
);
242 gen_helper_exception(tmp
);
246 static void gen_smul_dual(TCGv a
, TCGv b
)
248 TCGv tmp1
= new_tmp();
249 TCGv tmp2
= new_tmp();
250 tcg_gen_ext8s_i32(tmp1
, a
);
251 tcg_gen_ext8s_i32(tmp2
, b
);
252 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
254 tcg_gen_sari_i32(a
, a
, 16);
255 tcg_gen_sari_i32(b
, b
, 16);
256 tcg_gen_mul_i32(b
, b
, a
);
257 tcg_gen_mov_i32(a
, tmp1
);
261 /* Byteswap each halfword. */
262 static void gen_rev16(TCGv var
)
264 TCGv tmp
= new_tmp();
265 tcg_gen_shri_i32(tmp
, var
, 8);
266 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
267 tcg_gen_shli_i32(var
, var
, 8);
268 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
269 tcg_gen_or_i32(var
, var
, tmp
);
273 /* Byteswap low halfword and sign extend. */
274 static void gen_revsh(TCGv var
)
276 TCGv tmp
= new_tmp();
277 tcg_gen_shri_i32(tmp
, var
, 8);
278 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
279 tcg_gen_shli_i32(var
, var
, 8);
280 tcg_gen_ext8s_i32(var
, var
);
281 tcg_gen_or_i32(var
, var
, tmp
);
285 /* Unsigned bitfield extract. */
286 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
289 tcg_gen_shri_i32(var
, var
, shift
);
290 tcg_gen_andi_i32(var
, var
, mask
);
293 /* Signed bitfield extract. */
294 static void gen_sbfx(TCGv var
, int shift
, int width
)
299 tcg_gen_sari_i32(var
, var
, shift
);
300 if (shift
+ width
< 32) {
301 signbit
= 1u << (width
- 1);
302 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
303 tcg_gen_xori_i32(var
, var
, signbit
);
304 tcg_gen_subi_i32(var
, var
, signbit
);
308 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
309 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
311 tcg_gen_andi_i32(val
, val
, mask
);
312 tcg_gen_shli_i32(val
, val
, shift
);
313 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
314 tcg_gen_or_i32(dest
, base
, val
);
317 /* Round the top 32 bits of a 64-bit value. */
318 static void gen_roundqd(TCGv a
, TCGv b
)
320 tcg_gen_shri_i32(a
, a
, 31);
321 tcg_gen_add_i32(a
, a
, b
);
324 /* FIXME: Most targets have native widening multiplication.
325 It would be good to use that instead of a full wide multiply. */
326 /* 32x32->64 multiply. Marks inputs as dead. */
327 static TCGv
gen_mulu_i64_i32(TCGv a
, TCGv b
)
329 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
330 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
332 tcg_gen_extu_i32_i64(tmp1
, a
);
334 tcg_gen_extu_i32_i64(tmp2
, b
);
336 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
340 static TCGv
gen_muls_i64_i32(TCGv a
, TCGv b
)
342 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
343 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
345 tcg_gen_ext_i32_i64(tmp1
, a
);
347 tcg_gen_ext_i32_i64(tmp2
, b
);
349 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
353 /* Unsigned 32x32->64 multiply. */
354 static void gen_op_mull_T0_T1(void)
356 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
357 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
359 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
360 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
361 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
362 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
363 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
364 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
367 /* Signed 32x32->64 multiply. */
368 static void gen_imull(TCGv a
, TCGv b
)
370 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
371 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
373 tcg_gen_ext_i32_i64(tmp1
, a
);
374 tcg_gen_ext_i32_i64(tmp2
, b
);
375 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
376 tcg_gen_trunc_i64_i32(a
, tmp1
);
377 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
378 tcg_gen_trunc_i64_i32(b
, tmp1
);
380 #define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
382 /* Swap low and high halfwords. */
383 static void gen_swap_half(TCGv var
)
385 TCGv tmp
= new_tmp();
386 tcg_gen_shri_i32(tmp
, var
, 16);
387 tcg_gen_shli_i32(var
, var
, 16);
388 tcg_gen_or_i32(var
, var
, tmp
);
392 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
393 tmp = (t0 ^ t1) & 0x8000;
396 t0 = (t0 + t1) ^ tmp;
399 static void gen_add16(TCGv t0
, TCGv t1
)
401 TCGv tmp
= new_tmp();
402 tcg_gen_xor_i32(tmp
, t0
, t1
);
403 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
404 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
405 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
406 tcg_gen_add_i32(t0
, t0
, t1
);
407 tcg_gen_xor_i32(t0
, t0
, tmp
);
412 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
414 /* Set CF to the top bit of var. */
415 static void gen_set_CF_bit31(TCGv var
)
417 TCGv tmp
= new_tmp();
418 tcg_gen_shri_i32(tmp
, var
, 31);
423 /* Set N and Z flags from var. */
424 static inline void gen_logic_CC(TCGv var
)
426 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
427 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
431 static void gen_adc_T0_T1(void)
435 tmp
= load_cpu_field(CF
);
436 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
440 /* dest = T0 - T1 + CF - 1. */
441 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
444 tcg_gen_sub_i32(dest
, t0
, t1
);
445 tmp
= load_cpu_field(CF
);
446 tcg_gen_add_i32(dest
, dest
, tmp
);
447 tcg_gen_subi_i32(dest
, dest
, 1);
451 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
452 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
454 /* FIXME: Implement this natively. */
455 static inline void tcg_gen_not_i32(TCGv t0
, TCGv t1
)
457 tcg_gen_xori_i32(t0
, t1
, ~0);
460 /* FIXME: Implement this natively. */
461 static inline void tcg_gen_neg_i64(TCGv dest
, TCGv src
)
463 tcg_gen_sub_i64(dest
, tcg_const_i64(0), src
);
466 /* T0 &= ~T1. Clobbers T1. */
467 /* FIXME: Implement bic natively. */
468 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
470 TCGv tmp
= new_tmp();
471 tcg_gen_not_i32(tmp
, t1
);
472 tcg_gen_and_i32(dest
, t0
, tmp
);
475 static inline void gen_op_bicl_T0_T1(void)
481 /* FIXME: Implement this natively. */
482 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
484 /* FIXME: Implement this natively. */
485 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
493 tcg_gen_shri_i32(tmp
, t1
, i
);
494 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
495 tcg_gen_or_i32(t0
, t1
, tmp
);
499 static void shifter_out_im(TCGv var
, int shift
)
501 TCGv tmp
= new_tmp();
503 tcg_gen_andi_i32(tmp
, var
, 1);
505 tcg_gen_shri_i32(tmp
, var
, shift
);
507 tcg_gen_andi_i32(tmp
, tmp
, 1);
513 /* Shift by immediate. Includes special handling for shift == 0. */
514 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
520 shifter_out_im(var
, 32 - shift
);
521 tcg_gen_shli_i32(var
, var
, shift
);
527 tcg_gen_shri_i32(var
, var
, 31);
530 tcg_gen_movi_i32(var
, 0);
533 shifter_out_im(var
, shift
- 1);
534 tcg_gen_shri_i32(var
, var
, shift
);
541 shifter_out_im(var
, shift
- 1);
544 tcg_gen_sari_i32(var
, var
, shift
);
546 case 3: /* ROR/RRX */
549 shifter_out_im(var
, shift
- 1);
550 tcg_gen_rori_i32(var
, var
, shift
); break;
552 TCGv tmp
= load_cpu_field(CF
);
554 shifter_out_im(var
, 0);
555 tcg_gen_shri_i32(var
, var
, 1);
556 tcg_gen_shli_i32(tmp
, tmp
, 31);
557 tcg_gen_or_i32(var
, var
, tmp
);
563 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
564 TCGv shift
, int flags
)
568 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
569 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
570 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
571 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
575 case 0: gen_helper_shl(var
, var
, shift
); break;
576 case 1: gen_helper_shr(var
, var
, shift
); break;
577 case 2: gen_helper_sar(var
, var
, shift
); break;
578 case 3: gen_helper_ror(var
, var
, shift
); break;
584 #define PAS_OP(pfx) \
586 case 0: gen_pas_helper(glue(pfx,add16)); break; \
587 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
588 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
589 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
590 case 4: gen_pas_helper(glue(pfx,add8)); break; \
591 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
593 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
600 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
601 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
605 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
606 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
609 #undef gen_pas_helper
610 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
623 #undef gen_pas_helper
628 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
629 #define PAS_OP(pfx) \
631 case 0: gen_pas_helper(glue(pfx,add8)); break; \
632 case 1: gen_pas_helper(glue(pfx,add16)); break; \
633 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
634 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
635 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
636 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
638 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
643 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
645 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
646 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
650 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
651 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
654 #undef gen_pas_helper
655 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
668 #undef gen_pas_helper
673 static void gen_test_cc(int cc
, int label
)
680 zero
= tcg_const_i32(0);
683 tmp
= load_cpu_field(ZF
);
684 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, label
);
687 tmp
= load_cpu_field(ZF
);
688 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, zero
, label
);
691 tmp
= load_cpu_field(CF
);
692 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, zero
, label
);
695 tmp
= load_cpu_field(CF
);
696 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, label
);
699 tmp
= load_cpu_field(NF
);
700 tcg_gen_brcond_i32(TCG_COND_LT
, tmp
, zero
, label
);
703 tmp
= load_cpu_field(NF
);
704 tcg_gen_brcond_i32(TCG_COND_GE
, tmp
, zero
, label
);
707 tmp
= load_cpu_field(VF
);
708 tcg_gen_brcond_i32(TCG_COND_LT
, tmp
, zero
, label
);
711 tmp
= load_cpu_field(VF
);
712 tcg_gen_brcond_i32(TCG_COND_GE
, tmp
, zero
, label
);
714 case 8: /* hi: C && !Z */
715 inv
= gen_new_label();
716 tmp
= load_cpu_field(CF
);
717 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, inv
);
719 tmp
= load_cpu_field(ZF
);
720 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, zero
, label
);
723 case 9: /* ls: !C || Z */
724 tmp
= load_cpu_field(CF
);
725 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, label
);
727 tmp
= load_cpu_field(ZF
);
728 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, label
);
730 case 10: /* ge: 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_brcond_i32(TCG_COND_GE
, tmp
, zero
, label
);
737 case 11: /* lt: N != V -> N ^ V != 0 */
738 tmp
= load_cpu_field(VF
);
739 tmp2
= load_cpu_field(NF
);
740 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
742 tcg_gen_brcond_i32(TCG_COND_LT
, tmp
, zero
, label
);
744 case 12: /* gt: !Z && N == V */
745 inv
= gen_new_label();
746 tmp
= load_cpu_field(ZF
);
747 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, inv
);
749 tmp
= load_cpu_field(VF
);
750 tmp2
= load_cpu_field(NF
);
751 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
753 tcg_gen_brcond_i32(TCG_COND_GE
, tmp
, zero
, label
);
756 case 13: /* le: Z || N != V */
757 tmp
= load_cpu_field(ZF
);
758 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, zero
, label
);
760 tmp
= load_cpu_field(VF
);
761 tmp2
= load_cpu_field(NF
);
762 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
764 tcg_gen_brcond_i32(TCG_COND_LT
, tmp
, zero
, label
);
767 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
773 const uint8_t table_logic_cc
[16] = {
792 /* Set PC and Thumb state from an immediate address. */
793 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
797 s
->is_jmp
= DISAS_UPDATE
;
799 if (s
->thumb
!= (addr
& 1)) {
800 tcg_gen_movi_i32(tmp
, addr
& 1);
801 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
803 tcg_gen_movi_i32(tmp
, addr
& ~1);
804 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[15]));
808 /* Set PC and Thumb state from var. var is marked as dead. */
809 static inline void gen_bx(DisasContext
*s
, TCGv var
)
813 s
->is_jmp
= DISAS_UPDATE
;
815 tcg_gen_andi_i32(tmp
, var
, 1);
816 store_cpu_field(tmp
, thumb
);
817 tcg_gen_andi_i32(var
, var
, ~1);
818 store_cpu_field(var
, regs
[15]);
821 /* TODO: This should be removed. Use gen_bx instead. */
822 static inline void gen_bx_T0(DisasContext
*s
)
824 TCGv tmp
= new_tmp();
825 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
829 #if defined(CONFIG_USER_ONLY)
830 #define gen_ldst(name, s) gen_op_##name##_raw()
832 #define gen_ldst(name, s) do { \
835 gen_op_##name##_user(); \
837 gen_op_##name##_kernel(); \
840 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
842 TCGv tmp
= new_tmp();
843 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
846 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
848 TCGv tmp
= new_tmp();
849 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
852 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
854 TCGv tmp
= new_tmp();
855 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
858 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
860 TCGv tmp
= new_tmp();
861 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
864 static inline TCGv
gen_ld32(TCGv addr
, int index
)
866 TCGv tmp
= new_tmp();
867 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
870 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
872 tcg_gen_qemu_st8(val
, addr
, index
);
875 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
877 tcg_gen_qemu_st16(val
, addr
, index
);
880 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
882 tcg_gen_qemu_st32(val
, addr
, index
);
886 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
888 load_reg_var(s
, cpu_T
[0], reg
);
891 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
893 load_reg_var(s
, cpu_T
[1], reg
);
896 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
898 load_reg_var(s
, cpu_T
[2], reg
);
901 static inline void gen_set_pc_im(uint32_t val
)
903 TCGv tmp
= new_tmp();
904 tcg_gen_movi_i32(tmp
, val
);
905 store_cpu_field(tmp
, regs
[15]);
908 static inline void gen_set_pc_T0(void)
910 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, regs
[15]));
913 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
918 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
922 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
925 s
->is_jmp
= DISAS_JUMP
;
929 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
931 gen_movl_reg_TN(s
, reg
, 0);
934 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
936 gen_movl_reg_TN(s
, reg
, 1);
939 /* Force a TB lookup after an instruction that changes the CPU state. */
940 static inline void gen_lookup_tb(DisasContext
*s
)
942 gen_op_movl_T0_im(s
->pc
);
943 gen_movl_reg_T0(s
, 15);
944 s
->is_jmp
= DISAS_UPDATE
;
947 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
950 int val
, rm
, shift
, shiftop
;
953 if (!(insn
& (1 << 25))) {
956 if (!(insn
& (1 << 23)))
959 tcg_gen_addi_i32(var
, var
, val
);
963 shift
= (insn
>> 7) & 0x1f;
964 shiftop
= (insn
>> 5) & 3;
965 offset
= load_reg(s
, rm
);
966 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
967 if (!(insn
& (1 << 23)))
968 tcg_gen_sub_i32(var
, var
, offset
);
970 tcg_gen_add_i32(var
, var
, offset
);
975 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
981 if (insn
& (1 << 22)) {
983 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
984 if (!(insn
& (1 << 23)))
988 tcg_gen_addi_i32(var
, var
, val
);
992 tcg_gen_addi_i32(var
, var
, extra
);
994 offset
= load_reg(s
, rm
);
995 if (!(insn
& (1 << 23)))
996 tcg_gen_sub_i32(var
, var
, offset
);
998 tcg_gen_add_i32(var
, var
, offset
);
1003 #define VFP_OP2(name) \
1004 static inline void gen_vfp_##name(int dp) \
1007 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
1009 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1012 #define VFP_OP1i(name) \
1013 static inline void gen_vfp_##name(int dp, int arg) \
1016 gen_op_vfp_##name##d(arg); \
1018 gen_op_vfp_##name##s(arg); \
1028 static inline void gen_vfp_abs(int dp
)
1031 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1033 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1036 static inline void gen_vfp_neg(int dp
)
1039 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1041 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1044 static inline void gen_vfp_sqrt(int dp
)
1047 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1049 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1052 static inline void gen_vfp_cmp(int dp
)
1055 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1057 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1060 static inline void gen_vfp_cmpe(int dp
)
1063 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1065 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1068 static inline void gen_vfp_F1_ld0(int dp
)
1071 tcg_gen_movi_i64(cpu_F0d
, 0);
1073 tcg_gen_movi_i32(cpu_F0s
, 0);
1076 static inline void gen_vfp_uito(int dp
)
1079 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1081 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1084 static inline void gen_vfp_sito(int dp
)
1087 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1089 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1092 static inline void gen_vfp_toui(int dp
)
1095 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1097 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1100 static inline void gen_vfp_touiz(int dp
)
1103 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1105 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1108 static inline void gen_vfp_tosi(int dp
)
1111 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1113 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1116 static inline void gen_vfp_tosiz(int dp
)
1119 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1121 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1124 #define VFP_GEN_FIX(name) \
1125 static inline void gen_vfp_##name(int dp, int shift) \
1128 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1130 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1142 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1145 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1147 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1150 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1153 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1155 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1159 vfp_reg_offset (int dp
, int reg
)
1162 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1164 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1165 + offsetof(CPU_DoubleU
, l
.upper
);
1167 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1168 + offsetof(CPU_DoubleU
, l
.lower
);
1172 /* Return the offset of a 32-bit piece of a NEON register.
1173 zero is the least significant end of the register. */
1175 neon_reg_offset (int reg
, int n
)
1179 return vfp_reg_offset(0, sreg
);
1182 /* FIXME: Remove these. */
1183 #define neon_T0 cpu_T[0]
1184 #define neon_T1 cpu_T[1]
1185 #define NEON_GET_REG(T, reg, n) \
1186 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1187 #define NEON_SET_REG(T, reg, n) \
1188 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1190 static TCGv
neon_load_reg(int reg
, int pass
)
1192 TCGv tmp
= new_tmp();
1193 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1197 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1199 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1203 static inline void neon_load_reg64(TCGv var
, int reg
)
1205 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1208 static inline void neon_store_reg64(TCGv var
, int reg
)
1210 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1213 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1214 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1215 #define tcg_gen_st_f32 tcg_gen_st_i32
1216 #define tcg_gen_st_f64 tcg_gen_st_i64
1218 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1221 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1223 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1226 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1229 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1231 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1234 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1237 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1239 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1242 #define ARM_CP_RW_BIT (1 << 20)
1244 static inline void iwmmxt_load_reg(TCGv var
, int reg
)
1246 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1249 static inline void iwmmxt_store_reg(TCGv var
, int reg
)
1251 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1254 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1256 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1259 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1261 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1264 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1266 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1269 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1271 iwmmxt_store_reg(cpu_M0
, rn
);
1274 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1276 iwmmxt_load_reg(cpu_M0
, rn
);
1279 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1281 iwmmxt_load_reg(cpu_V1
, rn
);
1282 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1285 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1287 iwmmxt_load_reg(cpu_V1
, rn
);
1288 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1291 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1293 iwmmxt_load_reg(cpu_V1
, rn
);
1294 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1297 #define IWMMXT_OP(name) \
1298 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1300 iwmmxt_load_reg(cpu_V1, rn); \
1301 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1304 #define IWMMXT_OP_ENV(name) \
1305 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1307 iwmmxt_load_reg(cpu_V1, rn); \
1308 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1311 #define IWMMXT_OP_ENV_SIZE(name) \
1312 IWMMXT_OP_ENV(name##b) \
1313 IWMMXT_OP_ENV(name##w) \
1314 IWMMXT_OP_ENV(name##l)
1316 #define IWMMXT_OP_ENV1(name) \
1317 static inline void gen_op_iwmmxt_##name##_M0(void) \
1319 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1333 IWMMXT_OP_ENV_SIZE(unpackl
)
1334 IWMMXT_OP_ENV_SIZE(unpackh
)
1336 IWMMXT_OP_ENV1(unpacklub
)
1337 IWMMXT_OP_ENV1(unpackluw
)
1338 IWMMXT_OP_ENV1(unpacklul
)
1339 IWMMXT_OP_ENV1(unpackhub
)
1340 IWMMXT_OP_ENV1(unpackhuw
)
1341 IWMMXT_OP_ENV1(unpackhul
)
1342 IWMMXT_OP_ENV1(unpacklsb
)
1343 IWMMXT_OP_ENV1(unpacklsw
)
1344 IWMMXT_OP_ENV1(unpacklsl
)
1345 IWMMXT_OP_ENV1(unpackhsb
)
1346 IWMMXT_OP_ENV1(unpackhsw
)
1347 IWMMXT_OP_ENV1(unpackhsl
)
1349 IWMMXT_OP_ENV_SIZE(cmpeq
)
1350 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1351 IWMMXT_OP_ENV_SIZE(cmpgts
)
1353 IWMMXT_OP_ENV_SIZE(mins
)
1354 IWMMXT_OP_ENV_SIZE(minu
)
1355 IWMMXT_OP_ENV_SIZE(maxs
)
1356 IWMMXT_OP_ENV_SIZE(maxu
)
1358 IWMMXT_OP_ENV_SIZE(subn
)
1359 IWMMXT_OP_ENV_SIZE(addn
)
1360 IWMMXT_OP_ENV_SIZE(subu
)
1361 IWMMXT_OP_ENV_SIZE(addu
)
1362 IWMMXT_OP_ENV_SIZE(subs
)
1363 IWMMXT_OP_ENV_SIZE(adds
)
1365 IWMMXT_OP_ENV(avgb0
)
1366 IWMMXT_OP_ENV(avgb1
)
1367 IWMMXT_OP_ENV(avgw0
)
1368 IWMMXT_OP_ENV(avgw1
)
1372 IWMMXT_OP_ENV(packuw
)
1373 IWMMXT_OP_ENV(packul
)
1374 IWMMXT_OP_ENV(packuq
)
1375 IWMMXT_OP_ENV(packsw
)
1376 IWMMXT_OP_ENV(packsl
)
1377 IWMMXT_OP_ENV(packsq
)
1379 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1381 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1384 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1386 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1389 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1391 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1394 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1396 iwmmxt_load_reg(cpu_V1
, rn
);
1397 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1400 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1402 TCGv tmp
= tcg_const_i32(shift
);
1403 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1406 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1408 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1409 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1410 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1413 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1415 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1416 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1417 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1420 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1422 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1423 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1425 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1428 static void gen_op_iwmmxt_set_mup(void)
1431 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1432 tcg_gen_ori_i32(tmp
, tmp
, 2);
1433 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1436 static void gen_op_iwmmxt_set_cup(void)
1439 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1440 tcg_gen_ori_i32(tmp
, tmp
, 1);
1441 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1444 static void gen_op_iwmmxt_setpsr_nz(void)
1446 TCGv tmp
= new_tmp();
1447 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1448 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1451 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1453 iwmmxt_load_reg(cpu_V1
, rn
);
1454 tcg_gen_andi_i64(cpu_V1
, cpu_V1
, 0xffffffffu
);
1455 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1459 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1461 iwmmxt_load_reg(cpu_V0
, rn
);
1462 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1463 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1464 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1467 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1469 tcg_gen_extu_i32_i64(cpu_V0
, cpu_T
[0]);
1470 tcg_gen_extu_i32_i64(cpu_V1
, cpu_T
[0]);
1471 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 32);
1472 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
1473 iwmmxt_store_reg(cpu_V0
, rn
);
1476 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1481 rd
= (insn
>> 16) & 0xf;
1482 gen_movl_T1_reg(s
, rd
);
1484 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1485 if (insn
& (1 << 24)) {
1487 if (insn
& (1 << 23))
1488 gen_op_addl_T1_im(offset
);
1490 gen_op_addl_T1_im(-offset
);
1492 if (insn
& (1 << 21))
1493 gen_movl_reg_T1(s
, rd
);
1494 } else if (insn
& (1 << 21)) {
1496 if (insn
& (1 << 23))
1497 gen_op_movl_T0_im(offset
);
1499 gen_op_movl_T0_im(- offset
);
1500 gen_op_addl_T0_T1();
1501 gen_movl_reg_T0(s
, rd
);
1502 } else if (!(insn
& (1 << 23)))
1507 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1509 int rd
= (insn
>> 0) & 0xf;
1511 if (insn
& (1 << 8))
1512 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1515 gen_op_iwmmxt_movl_T0_wCx(rd
);
1517 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1519 gen_op_movl_T1_im(mask
);
1520 gen_op_andl_T0_T1();
1524 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1525 (ie. an undefined instruction). */
1526 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1529 int rdhi
, rdlo
, rd0
, rd1
, i
;
1532 if ((insn
& 0x0e000e00) == 0x0c000000) {
1533 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1535 rdlo
= (insn
>> 12) & 0xf;
1536 rdhi
= (insn
>> 16) & 0xf;
1537 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1538 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1539 gen_movl_reg_T0(s
, rdlo
);
1540 gen_movl_reg_T1(s
, rdhi
);
1541 } else { /* TMCRR */
1542 gen_movl_T0_reg(s
, rdlo
);
1543 gen_movl_T1_reg(s
, rdhi
);
1544 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1545 gen_op_iwmmxt_set_mup();
1550 wrd
= (insn
>> 12) & 0xf;
1551 if (gen_iwmmxt_address(s
, insn
))
1553 if (insn
& ARM_CP_RW_BIT
) {
1554 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1555 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1556 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1558 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1561 if (insn
& (1 << 8)) {
1562 if (insn
& (1 << 22)) { /* WLDRD */
1563 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1565 } else { /* WLDRW wRd */
1566 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1569 if (insn
& (1 << 22)) { /* WLDRH */
1570 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1571 } else { /* WLDRB */
1572 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1576 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1579 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1582 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1583 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1585 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1586 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1588 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1590 if (insn
& (1 << 8)) {
1591 if (insn
& (1 << 22)) { /* WSTRD */
1593 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1594 } else { /* WSTRW wRd */
1595 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1596 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1599 if (insn
& (1 << 22)) { /* WSTRH */
1600 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1601 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1602 } else { /* WSTRB */
1603 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1604 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1612 if ((insn
& 0x0f000000) != 0x0e000000)
1615 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1616 case 0x000: /* WOR */
1617 wrd
= (insn
>> 12) & 0xf;
1618 rd0
= (insn
>> 0) & 0xf;
1619 rd1
= (insn
>> 16) & 0xf;
1620 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1621 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1622 gen_op_iwmmxt_setpsr_nz();
1623 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1624 gen_op_iwmmxt_set_mup();
1625 gen_op_iwmmxt_set_cup();
1627 case 0x011: /* TMCR */
1630 rd
= (insn
>> 12) & 0xf;
1631 wrd
= (insn
>> 16) & 0xf;
1633 case ARM_IWMMXT_wCID
:
1634 case ARM_IWMMXT_wCASF
:
1636 case ARM_IWMMXT_wCon
:
1637 gen_op_iwmmxt_set_cup();
1639 case ARM_IWMMXT_wCSSF
:
1640 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1641 gen_movl_T1_reg(s
, rd
);
1642 gen_op_bicl_T0_T1();
1643 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1645 case ARM_IWMMXT_wCGR0
:
1646 case ARM_IWMMXT_wCGR1
:
1647 case ARM_IWMMXT_wCGR2
:
1648 case ARM_IWMMXT_wCGR3
:
1649 gen_op_iwmmxt_set_cup();
1650 gen_movl_reg_T0(s
, rd
);
1651 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1657 case 0x100: /* WXOR */
1658 wrd
= (insn
>> 12) & 0xf;
1659 rd0
= (insn
>> 0) & 0xf;
1660 rd1
= (insn
>> 16) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1662 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1663 gen_op_iwmmxt_setpsr_nz();
1664 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1665 gen_op_iwmmxt_set_mup();
1666 gen_op_iwmmxt_set_cup();
1668 case 0x111: /* TMRC */
1671 rd
= (insn
>> 12) & 0xf;
1672 wrd
= (insn
>> 16) & 0xf;
1673 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1674 gen_movl_reg_T0(s
, rd
);
1676 case 0x300: /* WANDN */
1677 wrd
= (insn
>> 12) & 0xf;
1678 rd0
= (insn
>> 0) & 0xf;
1679 rd1
= (insn
>> 16) & 0xf;
1680 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1681 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1682 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1683 gen_op_iwmmxt_setpsr_nz();
1684 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1685 gen_op_iwmmxt_set_mup();
1686 gen_op_iwmmxt_set_cup();
1688 case 0x200: /* WAND */
1689 wrd
= (insn
>> 12) & 0xf;
1690 rd0
= (insn
>> 0) & 0xf;
1691 rd1
= (insn
>> 16) & 0xf;
1692 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1693 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1694 gen_op_iwmmxt_setpsr_nz();
1695 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1696 gen_op_iwmmxt_set_mup();
1697 gen_op_iwmmxt_set_cup();
1699 case 0x810: case 0xa10: /* WMADD */
1700 wrd
= (insn
>> 12) & 0xf;
1701 rd0
= (insn
>> 0) & 0xf;
1702 rd1
= (insn
>> 16) & 0xf;
1703 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1704 if (insn
& (1 << 21))
1705 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1707 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1708 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1709 gen_op_iwmmxt_set_mup();
1711 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1712 wrd
= (insn
>> 12) & 0xf;
1713 rd0
= (insn
>> 16) & 0xf;
1714 rd1
= (insn
>> 0) & 0xf;
1715 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1716 switch ((insn
>> 22) & 3) {
1718 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1721 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1724 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1729 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1730 gen_op_iwmmxt_set_mup();
1731 gen_op_iwmmxt_set_cup();
1733 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1734 wrd
= (insn
>> 12) & 0xf;
1735 rd0
= (insn
>> 16) & 0xf;
1736 rd1
= (insn
>> 0) & 0xf;
1737 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1738 switch ((insn
>> 22) & 3) {
1740 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1743 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1746 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1751 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1752 gen_op_iwmmxt_set_mup();
1753 gen_op_iwmmxt_set_cup();
1755 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1756 wrd
= (insn
>> 12) & 0xf;
1757 rd0
= (insn
>> 16) & 0xf;
1758 rd1
= (insn
>> 0) & 0xf;
1759 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1760 if (insn
& (1 << 22))
1761 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1763 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1764 if (!(insn
& (1 << 20)))
1765 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1767 gen_op_iwmmxt_set_mup();
1769 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1770 wrd
= (insn
>> 12) & 0xf;
1771 rd0
= (insn
>> 16) & 0xf;
1772 rd1
= (insn
>> 0) & 0xf;
1773 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1774 if (insn
& (1 << 21)) {
1775 if (insn
& (1 << 20))
1776 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1778 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1780 if (insn
& (1 << 20))
1781 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1783 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1785 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1786 gen_op_iwmmxt_set_mup();
1788 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1789 wrd
= (insn
>> 12) & 0xf;
1790 rd0
= (insn
>> 16) & 0xf;
1791 rd1
= (insn
>> 0) & 0xf;
1792 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1793 if (insn
& (1 << 21))
1794 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1796 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1797 if (!(insn
& (1 << 20))) {
1798 iwmmxt_load_reg(cpu_V1
, wrd
);
1799 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1801 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1802 gen_op_iwmmxt_set_mup();
1804 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1805 wrd
= (insn
>> 12) & 0xf;
1806 rd0
= (insn
>> 16) & 0xf;
1807 rd1
= (insn
>> 0) & 0xf;
1808 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1809 switch ((insn
>> 22) & 3) {
1811 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1814 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1817 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1822 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1823 gen_op_iwmmxt_set_mup();
1824 gen_op_iwmmxt_set_cup();
1826 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1827 wrd
= (insn
>> 12) & 0xf;
1828 rd0
= (insn
>> 16) & 0xf;
1829 rd1
= (insn
>> 0) & 0xf;
1830 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1831 if (insn
& (1 << 22)) {
1832 if (insn
& (1 << 20))
1833 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1835 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1837 if (insn
& (1 << 20))
1838 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1840 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1842 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1843 gen_op_iwmmxt_set_mup();
1844 gen_op_iwmmxt_set_cup();
1846 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1847 wrd
= (insn
>> 12) & 0xf;
1848 rd0
= (insn
>> 16) & 0xf;
1849 rd1
= (insn
>> 0) & 0xf;
1850 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1851 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1852 gen_op_movl_T1_im(7);
1853 gen_op_andl_T0_T1();
1854 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1855 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1856 gen_op_iwmmxt_set_mup();
1858 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1859 rd
= (insn
>> 12) & 0xf;
1860 wrd
= (insn
>> 16) & 0xf;
1861 gen_movl_T0_reg(s
, rd
);
1862 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1863 switch ((insn
>> 6) & 3) {
1865 gen_op_movl_T1_im(0xff);
1866 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1869 gen_op_movl_T1_im(0xffff);
1870 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1873 gen_op_movl_T1_im(0xffffffff);
1874 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1879 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1880 gen_op_iwmmxt_set_mup();
1882 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1883 rd
= (insn
>> 12) & 0xf;
1884 wrd
= (insn
>> 16) & 0xf;
1887 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1888 switch ((insn
>> 22) & 3) {
1891 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1893 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1898 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1900 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1904 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1909 gen_movl_reg_T0(s
, rd
);
1911 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1912 if ((insn
& 0x000ff008) != 0x0003f000)
1914 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1915 switch ((insn
>> 22) & 3) {
1917 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1920 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1923 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1928 gen_op_shll_T1_im(28);
1929 gen_set_nzcv(cpu_T
[1]);
1931 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1932 rd
= (insn
>> 12) & 0xf;
1933 wrd
= (insn
>> 16) & 0xf;
1934 gen_movl_T0_reg(s
, rd
);
1935 switch ((insn
>> 6) & 3) {
1937 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1940 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1943 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1948 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1949 gen_op_iwmmxt_set_mup();
1951 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1952 if ((insn
& 0x000ff00f) != 0x0003f000)
1954 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1955 switch ((insn
>> 22) & 3) {
1957 for (i
= 0; i
< 7; i
++) {
1958 gen_op_shll_T1_im(4);
1959 gen_op_andl_T0_T1();
1963 for (i
= 0; i
< 3; i
++) {
1964 gen_op_shll_T1_im(8);
1965 gen_op_andl_T0_T1();
1969 gen_op_shll_T1_im(16);
1970 gen_op_andl_T0_T1();
1975 gen_set_nzcv(cpu_T
[0]);
1977 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1978 wrd
= (insn
>> 12) & 0xf;
1979 rd0
= (insn
>> 16) & 0xf;
1980 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1981 switch ((insn
>> 22) & 3) {
1983 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1986 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1989 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1994 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1995 gen_op_iwmmxt_set_mup();
1997 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1998 if ((insn
& 0x000ff00f) != 0x0003f000)
2000 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
2001 switch ((insn
>> 22) & 3) {
2003 for (i
= 0; i
< 7; i
++) {
2004 gen_op_shll_T1_im(4);
2009 for (i
= 0; i
< 3; i
++) {
2010 gen_op_shll_T1_im(8);
2015 gen_op_shll_T1_im(16);
2021 gen_set_nzcv(cpu_T
[0]);
2023 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2024 rd
= (insn
>> 12) & 0xf;
2025 rd0
= (insn
>> 16) & 0xf;
2026 if ((insn
& 0xf) != 0)
2028 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2029 switch ((insn
>> 22) & 3) {
2031 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
2034 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
2037 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
2042 gen_movl_reg_T0(s
, rd
);
2044 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2045 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2046 wrd
= (insn
>> 12) & 0xf;
2047 rd0
= (insn
>> 16) & 0xf;
2048 rd1
= (insn
>> 0) & 0xf;
2049 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2050 switch ((insn
>> 22) & 3) {
2052 if (insn
& (1 << 21))
2053 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2055 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2058 if (insn
& (1 << 21))
2059 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2061 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2064 if (insn
& (1 << 21))
2065 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2067 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2072 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2073 gen_op_iwmmxt_set_mup();
2074 gen_op_iwmmxt_set_cup();
2076 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2077 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2078 wrd
= (insn
>> 12) & 0xf;
2079 rd0
= (insn
>> 16) & 0xf;
2080 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2081 switch ((insn
>> 22) & 3) {
2083 if (insn
& (1 << 21))
2084 gen_op_iwmmxt_unpacklsb_M0();
2086 gen_op_iwmmxt_unpacklub_M0();
2089 if (insn
& (1 << 21))
2090 gen_op_iwmmxt_unpacklsw_M0();
2092 gen_op_iwmmxt_unpackluw_M0();
2095 if (insn
& (1 << 21))
2096 gen_op_iwmmxt_unpacklsl_M0();
2098 gen_op_iwmmxt_unpacklul_M0();
2103 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2104 gen_op_iwmmxt_set_mup();
2105 gen_op_iwmmxt_set_cup();
2107 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2108 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2109 wrd
= (insn
>> 12) & 0xf;
2110 rd0
= (insn
>> 16) & 0xf;
2111 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2112 switch ((insn
>> 22) & 3) {
2114 if (insn
& (1 << 21))
2115 gen_op_iwmmxt_unpackhsb_M0();
2117 gen_op_iwmmxt_unpackhub_M0();
2120 if (insn
& (1 << 21))
2121 gen_op_iwmmxt_unpackhsw_M0();
2123 gen_op_iwmmxt_unpackhuw_M0();
2126 if (insn
& (1 << 21))
2127 gen_op_iwmmxt_unpackhsl_M0();
2129 gen_op_iwmmxt_unpackhul_M0();
2134 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2135 gen_op_iwmmxt_set_mup();
2136 gen_op_iwmmxt_set_cup();
2138 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2139 case 0x214: case 0x614: case 0xa14: case 0xe14:
2140 wrd
= (insn
>> 12) & 0xf;
2141 rd0
= (insn
>> 16) & 0xf;
2142 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2143 if (gen_iwmmxt_shift(insn
, 0xff))
2145 switch ((insn
>> 22) & 3) {
2149 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2152 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2155 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2158 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2159 gen_op_iwmmxt_set_mup();
2160 gen_op_iwmmxt_set_cup();
2162 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2163 case 0x014: case 0x414: case 0x814: case 0xc14:
2164 wrd
= (insn
>> 12) & 0xf;
2165 rd0
= (insn
>> 16) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2167 if (gen_iwmmxt_shift(insn
, 0xff))
2169 switch ((insn
>> 22) & 3) {
2173 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2176 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2179 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2182 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2183 gen_op_iwmmxt_set_mup();
2184 gen_op_iwmmxt_set_cup();
2186 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2187 case 0x114: case 0x514: case 0x914: case 0xd14:
2188 wrd
= (insn
>> 12) & 0xf;
2189 rd0
= (insn
>> 16) & 0xf;
2190 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2191 if (gen_iwmmxt_shift(insn
, 0xff))
2193 switch ((insn
>> 22) & 3) {
2197 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2200 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2203 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2206 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2207 gen_op_iwmmxt_set_mup();
2208 gen_op_iwmmxt_set_cup();
2210 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2211 case 0x314: case 0x714: case 0xb14: case 0xf14:
2212 wrd
= (insn
>> 12) & 0xf;
2213 rd0
= (insn
>> 16) & 0xf;
2214 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2215 switch ((insn
>> 22) & 3) {
2219 if (gen_iwmmxt_shift(insn
, 0xf))
2221 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2224 if (gen_iwmmxt_shift(insn
, 0x1f))
2226 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2229 if (gen_iwmmxt_shift(insn
, 0x3f))
2231 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2234 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2235 gen_op_iwmmxt_set_mup();
2236 gen_op_iwmmxt_set_cup();
2238 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2239 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2240 wrd
= (insn
>> 12) & 0xf;
2241 rd0
= (insn
>> 16) & 0xf;
2242 rd1
= (insn
>> 0) & 0xf;
2243 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2244 switch ((insn
>> 22) & 3) {
2246 if (insn
& (1 << 21))
2247 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2249 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2252 if (insn
& (1 << 21))
2253 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2255 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2258 if (insn
& (1 << 21))
2259 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2261 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2266 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2267 gen_op_iwmmxt_set_mup();
2269 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2270 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2271 wrd
= (insn
>> 12) & 0xf;
2272 rd0
= (insn
>> 16) & 0xf;
2273 rd1
= (insn
>> 0) & 0xf;
2274 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2275 switch ((insn
>> 22) & 3) {
2277 if (insn
& (1 << 21))
2278 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2280 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2283 if (insn
& (1 << 21))
2284 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2286 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2289 if (insn
& (1 << 21))
2290 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2292 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2297 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2298 gen_op_iwmmxt_set_mup();
2300 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2301 case 0x402: case 0x502: case 0x602: case 0x702:
2302 wrd
= (insn
>> 12) & 0xf;
2303 rd0
= (insn
>> 16) & 0xf;
2304 rd1
= (insn
>> 0) & 0xf;
2305 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2306 gen_op_movl_T0_im((insn
>> 20) & 3);
2307 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2308 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2309 gen_op_iwmmxt_set_mup();
2311 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2312 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2313 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2314 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2315 wrd
= (insn
>> 12) & 0xf;
2316 rd0
= (insn
>> 16) & 0xf;
2317 rd1
= (insn
>> 0) & 0xf;
2318 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2319 switch ((insn
>> 20) & 0xf) {
2321 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2324 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2327 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2330 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2333 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2336 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2339 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2342 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2345 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2350 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2351 gen_op_iwmmxt_set_mup();
2352 gen_op_iwmmxt_set_cup();
2354 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2355 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2356 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2357 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2358 wrd
= (insn
>> 12) & 0xf;
2359 rd0
= (insn
>> 16) & 0xf;
2360 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2361 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2362 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2363 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2364 gen_op_iwmmxt_set_mup();
2365 gen_op_iwmmxt_set_cup();
2367 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2368 case 0x418: case 0x518: case 0x618: case 0x718:
2369 case 0x818: case 0x918: case 0xa18: case 0xb18:
2370 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2371 wrd
= (insn
>> 12) & 0xf;
2372 rd0
= (insn
>> 16) & 0xf;
2373 rd1
= (insn
>> 0) & 0xf;
2374 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2375 switch ((insn
>> 20) & 0xf) {
2377 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2380 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2383 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2386 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2389 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2392 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2395 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2398 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2401 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2406 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2407 gen_op_iwmmxt_set_mup();
2408 gen_op_iwmmxt_set_cup();
2410 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2411 case 0x408: case 0x508: case 0x608: case 0x708:
2412 case 0x808: case 0x908: case 0xa08: case 0xb08:
2413 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2414 wrd
= (insn
>> 12) & 0xf;
2415 rd0
= (insn
>> 16) & 0xf;
2416 rd1
= (insn
>> 0) & 0xf;
2417 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2418 if (!(insn
& (1 << 20)))
2420 switch ((insn
>> 22) & 3) {
2424 if (insn
& (1 << 21))
2425 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2427 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2430 if (insn
& (1 << 21))
2431 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2433 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2436 if (insn
& (1 << 21))
2437 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2439 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2442 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2443 gen_op_iwmmxt_set_mup();
2444 gen_op_iwmmxt_set_cup();
2446 case 0x201: case 0x203: case 0x205: case 0x207:
2447 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2448 case 0x211: case 0x213: case 0x215: case 0x217:
2449 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2450 wrd
= (insn
>> 5) & 0xf;
2451 rd0
= (insn
>> 12) & 0xf;
2452 rd1
= (insn
>> 0) & 0xf;
2453 if (rd0
== 0xf || rd1
== 0xf)
2455 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2456 switch ((insn
>> 16) & 0xf) {
2457 case 0x0: /* TMIA */
2458 gen_movl_T0_reg(s
, rd0
);
2459 gen_movl_T1_reg(s
, rd1
);
2460 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2462 case 0x8: /* TMIAPH */
2463 gen_movl_T0_reg(s
, rd0
);
2464 gen_movl_T1_reg(s
, rd1
);
2465 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2467 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2468 gen_movl_T1_reg(s
, rd0
);
2469 if (insn
& (1 << 16))
2470 gen_op_shrl_T1_im(16);
2471 gen_op_movl_T0_T1();
2472 gen_movl_T1_reg(s
, rd1
);
2473 if (insn
& (1 << 17))
2474 gen_op_shrl_T1_im(16);
2475 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2480 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2481 gen_op_iwmmxt_set_mup();
2490 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2491 (ie. an undefined instruction). */
2492 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2494 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2496 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2497 /* Multiply with Internal Accumulate Format */
2498 rd0
= (insn
>> 12) & 0xf;
2500 acc
= (insn
>> 5) & 7;
2505 switch ((insn
>> 16) & 0xf) {
2507 gen_movl_T0_reg(s
, rd0
);
2508 gen_movl_T1_reg(s
, rd1
);
2509 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2511 case 0x8: /* MIAPH */
2512 gen_movl_T0_reg(s
, rd0
);
2513 gen_movl_T1_reg(s
, rd1
);
2514 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2516 case 0xc: /* MIABB */
2517 case 0xd: /* MIABT */
2518 case 0xe: /* MIATB */
2519 case 0xf: /* MIATT */
2520 gen_movl_T1_reg(s
, rd0
);
2521 if (insn
& (1 << 16))
2522 gen_op_shrl_T1_im(16);
2523 gen_op_movl_T0_T1();
2524 gen_movl_T1_reg(s
, rd1
);
2525 if (insn
& (1 << 17))
2526 gen_op_shrl_T1_im(16);
2527 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2533 gen_op_iwmmxt_movq_wRn_M0(acc
);
2537 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2538 /* Internal Accumulator Access Format */
2539 rdhi
= (insn
>> 16) & 0xf;
2540 rdlo
= (insn
>> 12) & 0xf;
2546 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2547 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2548 gen_movl_reg_T0(s
, rdlo
);
2549 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2550 gen_op_andl_T0_T1();
2551 gen_movl_reg_T0(s
, rdhi
);
2553 gen_movl_T0_reg(s
, rdlo
);
2554 gen_movl_T1_reg(s
, rdhi
);
2555 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2563 /* Disassemble system coprocessor instruction. Return nonzero if
2564 instruction is not defined. */
2565 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2568 uint32_t rd
= (insn
>> 12) & 0xf;
2569 uint32_t cp
= (insn
>> 8) & 0xf;
2574 if (insn
& ARM_CP_RW_BIT
) {
2575 if (!env
->cp
[cp
].cp_read
)
2577 gen_set_pc_im(s
->pc
);
2579 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2580 store_reg(s
, rd
, tmp
);
2582 if (!env
->cp
[cp
].cp_write
)
2584 gen_set_pc_im(s
->pc
);
2585 tmp
= load_reg(s
, rd
);
2586 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2591 static int cp15_user_ok(uint32_t insn
)
2593 int cpn
= (insn
>> 16) & 0xf;
2594 int cpm
= insn
& 0xf;
2595 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2597 if (cpn
== 13 && cpm
== 0) {
2599 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2603 /* ISB, DSB, DMB. */
2604 if ((cpm
== 5 && op
== 4)
2605 || (cpm
== 10 && (op
== 4 || op
== 5)))
2611 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2612 instruction is not defined. */
2613 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2618 /* M profile cores use memory mapped registers instead of cp15. */
2619 if (arm_feature(env
, ARM_FEATURE_M
))
2622 if ((insn
& (1 << 25)) == 0) {
2623 if (insn
& (1 << 20)) {
2627 /* mcrr. Used for block cache operations, so implement as no-op. */
2630 if ((insn
& (1 << 4)) == 0) {
2634 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2637 if ((insn
& 0x0fff0fff) == 0x0e070f90
2638 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2639 /* Wait for interrupt. */
2640 gen_set_pc_im(s
->pc
);
2641 s
->is_jmp
= DISAS_WFI
;
2644 rd
= (insn
>> 12) & 0xf;
2645 if (insn
& ARM_CP_RW_BIT
) {
2647 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2648 /* If the destination register is r15 then sets condition codes. */
2650 store_reg(s
, rd
, tmp
);
2654 tmp
= load_reg(s
, rd
);
2655 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2657 /* Normally we would always end the TB here, but Linux
2658 * arch/arm/mach-pxa/sleep.S expects two instructions following
2659 * an MMU enable to execute from cache. Imitate this behaviour. */
2660 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2661 (insn
& 0x0fff0fff) != 0x0e010f10)
2667 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2668 #define VFP_SREG(insn, bigbit, smallbit) \
2669 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2670 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2671 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2672 reg = (((insn) >> (bigbit)) & 0x0f) \
2673 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2675 if (insn & (1 << (smallbit))) \
2677 reg = ((insn) >> (bigbit)) & 0x0f; \
2680 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2681 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2682 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2683 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2684 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2685 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2687 /* Move between integer and VFP cores. */
2688 static TCGv
gen_vfp_mrs(void)
2690 TCGv tmp
= new_tmp();
2691 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2695 static void gen_vfp_msr(TCGv tmp
)
2697 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2702 vfp_enabled(CPUState
* env
)
2704 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2707 static void gen_neon_dup_u8(TCGv var
, int shift
)
2709 TCGv tmp
= new_tmp();
2711 tcg_gen_shri_i32(var
, var
, shift
);
2712 tcg_gen_andi_i32(var
, var
, 0xff);
2713 tcg_gen_shli_i32(tmp
, var
, 8);
2714 tcg_gen_or_i32(var
, var
, tmp
);
2715 tcg_gen_shli_i32(tmp
, var
, 16);
2716 tcg_gen_or_i32(var
, var
, tmp
);
2720 static void gen_neon_dup_low16(TCGv var
)
2722 TCGv tmp
= new_tmp();
2723 tcg_gen_andi_i32(var
, var
, 0xffff);
2724 tcg_gen_shli_i32(tmp
, var
, 16);
2725 tcg_gen_or_i32(var
, var
, tmp
);
2729 static void gen_neon_dup_high16(TCGv var
)
2731 TCGv tmp
= new_tmp();
2732 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2733 tcg_gen_shri_i32(tmp
, var
, 16);
2734 tcg_gen_or_i32(var
, var
, tmp
);
2738 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2739 (ie. an undefined instruction). */
2740 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2742 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2747 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2750 if (!vfp_enabled(env
)) {
2751 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2752 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2754 rn
= (insn
>> 16) & 0xf;
2755 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2756 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2759 dp
= ((insn
& 0xf00) == 0xb00);
2760 switch ((insn
>> 24) & 0xf) {
2762 if (insn
& (1 << 4)) {
2763 /* single register transfer */
2764 rd
= (insn
>> 12) & 0xf;
2769 VFP_DREG_N(rn
, insn
);
2772 if (insn
& 0x00c00060
2773 && !arm_feature(env
, ARM_FEATURE_NEON
))
2776 pass
= (insn
>> 21) & 1;
2777 if (insn
& (1 << 22)) {
2779 offset
= ((insn
>> 5) & 3) * 8;
2780 } else if (insn
& (1 << 5)) {
2782 offset
= (insn
& (1 << 6)) ? 16 : 0;
2787 if (insn
& ARM_CP_RW_BIT
) {
2789 tmp
= neon_load_reg(rn
, pass
);
2793 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2794 if (insn
& (1 << 23))
2800 if (insn
& (1 << 23)) {
2802 tcg_gen_shri_i32(tmp
, tmp
, 16);
2808 tcg_gen_sari_i32(tmp
, tmp
, 16);
2817 store_reg(s
, rd
, tmp
);
2820 tmp
= load_reg(s
, rd
);
2821 if (insn
& (1 << 23)) {
2824 gen_neon_dup_u8(tmp
, 0);
2825 } else if (size
== 1) {
2826 gen_neon_dup_low16(tmp
);
2829 tcg_gen_mov_i32(tmp2
, tmp
);
2830 neon_store_reg(rn
, 0, tmp2
);
2831 neon_store_reg(rn
, 0, tmp
);
2836 tmp2
= neon_load_reg(rn
, pass
);
2837 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2841 tmp2
= neon_load_reg(rn
, pass
);
2842 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2848 neon_store_reg(rn
, pass
, tmp
);
2852 if ((insn
& 0x6f) != 0x00)
2854 rn
= VFP_SREG_N(insn
);
2855 if (insn
& ARM_CP_RW_BIT
) {
2857 if (insn
& (1 << 21)) {
2858 /* system register */
2863 /* VFP2 allows access to FSID from userspace.
2864 VFP3 restricts all id registers to privileged
2867 && arm_feature(env
, ARM_FEATURE_VFP3
))
2869 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2874 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2876 case ARM_VFP_FPINST
:
2877 case ARM_VFP_FPINST2
:
2878 /* Not present in VFP3. */
2880 || arm_feature(env
, ARM_FEATURE_VFP3
))
2882 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2886 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2887 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2890 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2896 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2898 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2904 gen_mov_F0_vreg(0, rn
);
2905 tmp
= gen_vfp_mrs();
2908 /* Set the 4 flag bits in the CPSR. */
2912 store_reg(s
, rd
, tmp
);
2916 tmp
= load_reg(s
, rd
);
2917 if (insn
& (1 << 21)) {
2919 /* system register */
2924 /* Writes are ignored. */
2927 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2934 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2937 case ARM_VFP_FPINST
:
2938 case ARM_VFP_FPINST2
:
2939 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2946 gen_mov_vreg_F0(0, rn
);
2951 /* data processing */
2952 /* The opcode is in bits 23, 21, 20 and 6. */
2953 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2957 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2959 /* rn is register number */
2960 VFP_DREG_N(rn
, insn
);
2963 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2964 /* Integer or single precision destination. */
2965 rd
= VFP_SREG_D(insn
);
2967 VFP_DREG_D(rd
, insn
);
2970 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2971 /* Integer source. */
2972 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2974 VFP_DREG_M(rm
, insn
);
2977 rn
= VFP_SREG_N(insn
);
2978 if (op
== 15 && rn
== 15) {
2979 /* Double precision destination. */
2980 VFP_DREG_D(rd
, insn
);
2982 rd
= VFP_SREG_D(insn
);
2984 rm
= VFP_SREG_M(insn
);
2987 veclen
= env
->vfp
.vec_len
;
2988 if (op
== 15 && rn
> 3)
2991 /* Shut up compiler warnings. */
3002 /* Figure out what type of vector operation this is. */
3003 if ((rd
& bank_mask
) == 0) {
3008 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
3010 delta_d
= env
->vfp
.vec_stride
+ 1;
3012 if ((rm
& bank_mask
) == 0) {
3013 /* mixed scalar/vector */
3022 /* Load the initial operands. */
3027 /* Integer source */
3028 gen_mov_F0_vreg(0, rm
);
3033 gen_mov_F0_vreg(dp
, rd
);
3034 gen_mov_F1_vreg(dp
, rm
);
3038 /* Compare with zero */
3039 gen_mov_F0_vreg(dp
, rd
);
3046 /* Source and destination the same. */
3047 gen_mov_F0_vreg(dp
, rd
);
3050 /* One source operand. */
3051 gen_mov_F0_vreg(dp
, rm
);
3055 /* Two source operands. */
3056 gen_mov_F0_vreg(dp
, rn
);
3057 gen_mov_F1_vreg(dp
, rm
);
3061 /* Perform the calculation. */
3063 case 0: /* mac: fd + (fn * fm) */
3065 gen_mov_F1_vreg(dp
, rd
);
3068 case 1: /* nmac: fd - (fn * fm) */
3071 gen_mov_F1_vreg(dp
, rd
);
3074 case 2: /* msc: -fd + (fn * fm) */
3076 gen_mov_F1_vreg(dp
, rd
);
3079 case 3: /* nmsc: -fd - (fn * fm) */
3081 gen_mov_F1_vreg(dp
, rd
);
3085 case 4: /* mul: fn * fm */
3088 case 5: /* nmul: -(fn * fm) */
3092 case 6: /* add: fn + fm */
3095 case 7: /* sub: fn - fm */
3098 case 8: /* div: fn / fm */
3101 case 14: /* fconst */
3102 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3105 n
= (insn
<< 12) & 0x80000000;
3106 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3113 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3120 tcg_gen_movi_i32(cpu_F0d
, ((uint64_t)n
) << 32);
3123 case 15: /* extension space */
3146 case 11: /* cmpez */
3150 case 15: /* single<->double conversion */
3152 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3154 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3156 case 16: /* fuito */
3159 case 17: /* fsito */
3162 case 20: /* fshto */
3163 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3165 gen_vfp_shto(dp
, rm
);
3167 case 21: /* fslto */
3168 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3170 gen_vfp_slto(dp
, rm
);
3172 case 22: /* fuhto */
3173 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3175 gen_vfp_uhto(dp
, rm
);
3177 case 23: /* fulto */
3178 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3180 gen_vfp_ulto(dp
, rm
);
3182 case 24: /* ftoui */
3185 case 25: /* ftouiz */
3188 case 26: /* ftosi */
3191 case 27: /* ftosiz */
3194 case 28: /* ftosh */
3195 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3197 gen_vfp_tosh(dp
, rm
);
3199 case 29: /* ftosl */
3200 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3202 gen_vfp_tosl(dp
, rm
);
3204 case 30: /* ftouh */
3205 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3207 gen_vfp_touh(dp
, rm
);
3209 case 31: /* ftoul */
3210 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3212 gen_vfp_toul(dp
, rm
);
3214 default: /* undefined */
3215 printf ("rn:%d\n", rn
);
3219 default: /* undefined */
3220 printf ("op:%d\n", op
);
3224 /* Write back the result. */
3225 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3226 ; /* Comparison, do nothing. */
3227 else if (op
== 15 && rn
> 17)
3228 /* Integer result. */
3229 gen_mov_vreg_F0(0, rd
);
3230 else if (op
== 15 && rn
== 15)
3232 gen_mov_vreg_F0(!dp
, rd
);
3234 gen_mov_vreg_F0(dp
, rd
);
3236 /* break out of the loop if we have finished */
3240 if (op
== 15 && delta_m
== 0) {
3241 /* single source one-many */
3243 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3245 gen_mov_vreg_F0(dp
, rd
);
3249 /* Setup the next operands. */
3251 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3255 /* One source operand. */
3256 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3258 gen_mov_F0_vreg(dp
, rm
);
3260 /* Two source operands. */
3261 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3263 gen_mov_F0_vreg(dp
, rn
);
3265 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3267 gen_mov_F1_vreg(dp
, rm
);
3275 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3276 /* two-register transfer */
3277 rn
= (insn
>> 16) & 0xf;
3278 rd
= (insn
>> 12) & 0xf;
3280 VFP_DREG_M(rm
, insn
);
3282 rm
= VFP_SREG_M(insn
);
3285 if (insn
& ARM_CP_RW_BIT
) {
3288 gen_mov_F0_vreg(0, rm
* 2);
3289 tmp
= gen_vfp_mrs();
3290 store_reg(s
, rd
, tmp
);
3291 gen_mov_F0_vreg(0, rm
* 2 + 1);
3292 tmp
= gen_vfp_mrs();
3293 store_reg(s
, rn
, tmp
);
3295 gen_mov_F0_vreg(0, rm
);
3296 tmp
= gen_vfp_mrs();
3297 store_reg(s
, rn
, tmp
);
3298 gen_mov_F0_vreg(0, rm
+ 1);
3299 tmp
= gen_vfp_mrs();
3300 store_reg(s
, rd
, tmp
);
3305 tmp
= load_reg(s
, rd
);
3307 gen_mov_vreg_F0(0, rm
* 2);
3308 tmp
= load_reg(s
, rn
);
3310 gen_mov_vreg_F0(0, rm
* 2 + 1);
3312 tmp
= load_reg(s
, rn
);
3314 gen_mov_vreg_F0(0, rm
);
3315 tmp
= load_reg(s
, rd
);
3317 gen_mov_vreg_F0(0, rm
+ 1);
3322 rn
= (insn
>> 16) & 0xf;
3324 VFP_DREG_D(rd
, insn
);
3326 rd
= VFP_SREG_D(insn
);
3327 if (s
->thumb
&& rn
== 15) {
3328 gen_op_movl_T1_im(s
->pc
& ~2);
3330 gen_movl_T1_reg(s
, rn
);
3332 if ((insn
& 0x01200000) == 0x01000000) {
3333 /* Single load/store */
3334 offset
= (insn
& 0xff) << 2;
3335 if ((insn
& (1 << 23)) == 0)
3337 gen_op_addl_T1_im(offset
);
3338 if (insn
& (1 << 20)) {
3340 gen_mov_vreg_F0(dp
, rd
);
3342 gen_mov_F0_vreg(dp
, rd
);
3346 /* load/store multiple */
3348 n
= (insn
>> 1) & 0x7f;
3352 if (insn
& (1 << 24)) /* pre-decrement */
3353 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3359 for (i
= 0; i
< n
; i
++) {
3360 if (insn
& ARM_CP_RW_BIT
) {
3363 gen_mov_vreg_F0(dp
, rd
+ i
);
3366 gen_mov_F0_vreg(dp
, rd
+ i
);
3369 gen_op_addl_T1_im(offset
);
3371 if (insn
& (1 << 21)) {
3373 if (insn
& (1 << 24))
3374 offset
= -offset
* n
;
3375 else if (dp
&& (insn
& 1))
3381 gen_op_addl_T1_im(offset
);
3382 gen_movl_reg_T1(s
, rn
);
3388 /* Should never happen. */
3394 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3396 TranslationBlock
*tb
;
3399 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3401 gen_set_pc_im(dest
);
3402 tcg_gen_exit_tb((long)tb
+ n
);
3404 gen_set_pc_im(dest
);
3409 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3411 if (__builtin_expect(s
->singlestep_enabled
, 0)) {
3412 /* An indirect jump so that we still trigger the debug exception. */
3417 gen_goto_tb(s
, 0, dest
);
3418 s
->is_jmp
= DISAS_TB_JUMP
;
3422 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3425 tcg_gen_sari_i32(t0
, t0
, 16);
3429 tcg_gen_sari_i32(t1
, t1
, 16);
3432 tcg_gen_mul_i32(t0
, t0
, t1
);
3435 /* Return the mask of PSR bits set by a MSR instruction. */
3436 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3440 if (flags
& (1 << 0))
3442 if (flags
& (1 << 1))
3444 if (flags
& (1 << 2))
3446 if (flags
& (1 << 3))
3449 /* Mask out undefined bits. */
3450 mask
&= ~CPSR_RESERVED
;
3451 if (!arm_feature(env
, ARM_FEATURE_V6
))
3452 mask
&= ~(CPSR_E
| CPSR_GE
);
3453 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3455 /* Mask out execution state bits. */
3458 /* Mask out privileged bits. */
3464 /* Returns nonzero if access to the PSR is not permitted. */
3465 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3469 /* ??? This is also undefined in system mode. */
3473 tmp
= load_cpu_field(spsr
);
3474 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3475 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3476 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3477 store_cpu_field(tmp
, spsr
);
3479 gen_set_cpsr(cpu_T
[0], mask
);
3485 /* Generate an old-style exception return. */
3486 static void gen_exception_return(DisasContext
*s
)
3490 tmp
= load_cpu_field(spsr
);
3491 gen_set_cpsr(tmp
, 0xffffffff);
3493 s
->is_jmp
= DISAS_UPDATE
;
3496 /* Generate a v6 exception return. Marks both values as dead. */
3497 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3499 gen_set_cpsr(cpsr
, 0xffffffff);
3501 store_reg(s
, 15, pc
);
3502 s
->is_jmp
= DISAS_UPDATE
;
3506 gen_set_condexec (DisasContext
*s
)
3508 if (s
->condexec_mask
) {
3509 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3510 TCGv tmp
= new_tmp();
3511 tcg_gen_movi_i32(tmp
, val
);
3512 store_cpu_field(tmp
, condexec_bits
);
3516 static void gen_nop_hint(DisasContext
*s
, int val
)
3520 gen_set_pc_im(s
->pc
);
3521 s
->is_jmp
= DISAS_WFI
;
3525 /* TODO: Implement SEV and WFE. May help SMP performance. */
3531 /* These macros help make the code more readable when migrating from the
3532 old dyngen helpers. They should probably be removed when
3533 T0/T1 are removed. */
3534 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3535 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3537 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3539 static inline int gen_neon_add(int size
)
3542 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3543 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3544 case 2: gen_op_addl_T0_T1(); break;
3550 static inline void gen_neon_rsb(int size
)
3553 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3554 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3555 case 2: gen_op_rsbl_T0_T1(); break;
3560 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3561 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3562 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3563 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3564 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3566 /* FIXME: This is wrong. They set the wrong overflow bit. */
3567 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3568 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3569 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3570 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3572 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3573 switch ((size << 1) | u) { \
3575 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3578 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3581 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3584 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3587 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3590 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3592 default: return 1; \
3595 #define GEN_NEON_INTEGER_OP(name) do { \
3596 switch ((size << 1) | u) { \
3598 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3601 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3604 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3607 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3610 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3613 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3615 default: return 1; \
3619 gen_neon_movl_scratch_T0(int scratch
)
3623 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3624 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3628 gen_neon_movl_scratch_T1(int scratch
)
3632 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3633 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3637 gen_neon_movl_T0_scratch(int scratch
)
3641 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3642 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3646 gen_neon_movl_T1_scratch(int scratch
)
3650 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3651 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3654 static inline void gen_neon_get_scalar(int size
, int reg
)
3657 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3659 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3661 gen_neon_dup_low16(cpu_T
[0]);
3663 gen_neon_dup_high16(cpu_T
[0]);
3667 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3671 for (n
= 0; n
< q
+ 1; n
+= 2) {
3672 NEON_GET_REG(T0
, reg
, n
);
3673 NEON_GET_REG(T0
, reg
, n
+ n
);
3675 case 0: gen_helper_neon_unzip_u8(); break;
3676 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3677 case 2: /* no-op */; break;
3680 gen_neon_movl_scratch_T0(tmp
+ n
);
3681 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3689 } neon_ls_element_type
[11] = {
3703 /* Translate a NEON load/store element instruction. Return nonzero if the
3704 instruction is invalid. */
3705 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3721 if (!vfp_enabled(env
))
3723 VFP_DREG_D(rd
, insn
);
3724 rn
= (insn
>> 16) & 0xf;
3726 load
= (insn
& (1 << 21)) != 0;
3727 if ((insn
& (1 << 23)) == 0) {
3728 /* Load store all elements. */
3729 op
= (insn
>> 8) & 0xf;
3730 size
= (insn
>> 6) & 3;
3731 if (op
> 10 || size
== 3)
3733 nregs
= neon_ls_element_type
[op
].nregs
;
3734 interleave
= neon_ls_element_type
[op
].interleave
;
3735 gen_movl_T1_reg(s
, rn
);
3736 stride
= (1 << size
) * interleave
;
3737 for (reg
= 0; reg
< nregs
; reg
++) {
3738 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3739 gen_movl_T1_reg(s
, rn
);
3740 gen_op_addl_T1_im((1 << size
) * reg
);
3741 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3742 gen_movl_T1_reg(s
, rn
);
3743 gen_op_addl_T1_im(1 << size
);
3745 for (pass
= 0; pass
< 2; pass
++) {
3748 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3749 neon_store_reg(rd
, pass
, tmp
);
3751 tmp
= neon_load_reg(rd
, pass
);
3752 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3754 gen_op_addl_T1_im(stride
);
3755 } else if (size
== 1) {
3757 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3758 gen_op_addl_T1_im(stride
);
3759 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3760 gen_op_addl_T1_im(stride
);
3761 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3763 neon_store_reg(rd
, pass
, tmp
);
3765 tmp
= neon_load_reg(rd
, pass
);
3767 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3768 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3769 gen_op_addl_T1_im(stride
);
3770 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3771 gen_op_addl_T1_im(stride
);
3773 } else /* size == 0 */ {
3775 for (n
= 0; n
< 4; n
++) {
3776 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3777 gen_op_addl_T1_im(stride
);
3781 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3785 neon_store_reg(rd
, pass
, tmp2
);
3787 tmp2
= neon_load_reg(rd
, pass
);
3788 for (n
= 0; n
< 4; n
++) {
3791 tcg_gen_mov_i32(tmp
, tmp2
);
3793 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3795 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3796 gen_op_addl_T1_im(stride
);
3802 rd
+= neon_ls_element_type
[op
].spacing
;
3806 size
= (insn
>> 10) & 3;
3808 /* Load single element to all lanes. */
3811 size
= (insn
>> 6) & 3;
3812 nregs
= ((insn
>> 8) & 3) + 1;
3813 stride
= (insn
& (1 << 5)) ? 2 : 1;
3814 gen_movl_T1_reg(s
, rn
);
3815 for (reg
= 0; reg
< nregs
; reg
++) {
3818 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3819 gen_neon_dup_u8(tmp
, 0);
3822 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3823 gen_neon_dup_low16(tmp
);
3826 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3831 gen_op_addl_T1_im(1 << size
);
3833 tcg_gen_mov_i32(tmp2
, tmp
);
3834 neon_store_reg(rd
, 0, tmp2
);
3835 neon_store_reg(rd
, 0, tmp
);
3838 stride
= (1 << size
) * nregs
;
3840 /* Single element. */
3841 pass
= (insn
>> 7) & 1;
3844 shift
= ((insn
>> 5) & 3) * 8;
3848 shift
= ((insn
>> 6) & 1) * 16;
3849 stride
= (insn
& (1 << 5)) ? 2 : 1;
3853 stride
= (insn
& (1 << 6)) ? 2 : 1;
3858 nregs
= ((insn
>> 8) & 3) + 1;
3859 gen_movl_T1_reg(s
, rn
);
3860 for (reg
= 0; reg
< nregs
; reg
++) {
3864 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3867 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3870 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3874 tmp2
= neon_load_reg(rd
, pass
);
3875 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3878 neon_store_reg(rd
, pass
, tmp
);
3879 } else { /* Store */
3880 tmp
= neon_load_reg(rd
, pass
);
3882 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3885 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3888 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3891 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3896 gen_op_addl_T1_im(1 << size
);
3898 stride
= nregs
* (1 << size
);
3904 base
= load_reg(s
, rn
);
3906 tcg_gen_addi_i32(base
, base
, stride
);
3909 index
= load_reg(s
, rm
);
3910 tcg_gen_add_i32(base
, base
, index
);
3913 store_reg(s
, rn
, base
);
3918 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3919 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3921 tcg_gen_and_i32(t
, t
, c
);
3922 tcg_gen_bic_i32(f
, f
, c
);
3923 tcg_gen_or_i32(dest
, t
, f
);
3926 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv src
)
3929 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3930 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3931 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3936 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv src
)
3939 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3940 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3941 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3946 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv src
)
3949 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3950 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3951 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3956 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3962 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3963 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3968 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3969 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3976 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3977 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3982 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3983 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3990 static inline void gen_neon_widen(TCGv dest
, TCGv src
, int size
, int u
)
3994 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3995 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3996 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4001 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4002 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4003 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4010 static inline void gen_neon_addl(int size
)
4013 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4014 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4015 case 2: tcg_gen_add_i64(CPU_V001
); break;
4020 static inline void gen_neon_subl(int size
)
4023 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4024 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4025 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4030 static inline void gen_neon_negl(TCGv var
, int size
)
4033 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4034 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4035 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4040 static inline void gen_neon_addl_saturate(TCGv op0
, TCGv op1
, int size
)
4043 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4044 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4049 static inline void gen_neon_mull(TCGv dest
, TCGv a
, TCGv b
, int size
, int u
)
4053 switch ((size
<< 1) | u
) {
4054 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4055 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4056 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4057 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4059 tmp
= gen_muls_i64_i32(a
, b
);
4060 tcg_gen_mov_i64(dest
, tmp
);
4063 tmp
= gen_mulu_i64_i32(a
, b
);
4064 tcg_gen_mov_i64(dest
, tmp
);
4074 /* Translate a NEON data processing instruction. Return nonzero if the
4075 instruction is invalid.
4076 We process data in a mixture of 32-bit and 64-bit chunks.
4077 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4079 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4096 if (!vfp_enabled(env
))
4098 q
= (insn
& (1 << 6)) != 0;
4099 u
= (insn
>> 24) & 1;
4100 VFP_DREG_D(rd
, insn
);
4101 VFP_DREG_N(rn
, insn
);
4102 VFP_DREG_M(rm
, insn
);
4103 size
= (insn
>> 20) & 3;
4104 if ((insn
& (1 << 23)) == 0) {
4105 /* Three register same length. */
4106 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4107 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4108 || op
== 10 || op
== 11 || op
== 16)) {
4109 /* 64-bit element instructions. */
4110 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4111 neon_load_reg64(cpu_V0
, rn
+ pass
);
4112 neon_load_reg64(cpu_V1
, rm
+ pass
);
4116 gen_helper_neon_add_saturate_u64(CPU_V001
);
4118 gen_helper_neon_add_saturate_s64(CPU_V001
);
4123 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4125 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4130 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4132 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4137 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4140 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4144 case 10: /* VRSHL */
4146 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4148 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4151 case 11: /* VQRSHL */
4153 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4156 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4162 tcg_gen_sub_i64(CPU_V001
);
4164 tcg_gen_add_i64(CPU_V001
);
4170 neon_store_reg64(cpu_V0
, rd
+ pass
);
4177 case 10: /* VRSHL */
4178 case 11: /* VQRSHL */
4181 /* Shift instruction operands are reversed. */
4188 case 20: /* VPMAX */
4189 case 21: /* VPMIN */
4190 case 23: /* VPADD */
4193 case 26: /* VPADD (float) */
4194 pairwise
= (u
&& size
< 2);
4196 case 30: /* VPMIN/VPMAX (float) */
4203 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4212 NEON_GET_REG(T0
, rn
, n
);
4213 NEON_GET_REG(T1
, rn
, n
+ 1);
4215 NEON_GET_REG(T0
, rm
, n
);
4216 NEON_GET_REG(T1
, rm
, n
+ 1);
4220 NEON_GET_REG(T0
, rn
, pass
);
4221 NEON_GET_REG(T1
, rm
, pass
);
4225 GEN_NEON_INTEGER_OP(hadd
);
4228 GEN_NEON_INTEGER_OP_ENV(qadd
);
4230 case 2: /* VRHADD */
4231 GEN_NEON_INTEGER_OP(rhadd
);
4233 case 3: /* Logic ops. */
4234 switch ((u
<< 2) | size
) {
4236 gen_op_andl_T0_T1();
4239 gen_op_bicl_T0_T1();
4249 gen_op_xorl_T0_T1();
4252 tmp
= neon_load_reg(rd
, pass
);
4253 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4257 tmp
= neon_load_reg(rd
, pass
);
4258 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4262 tmp
= neon_load_reg(rd
, pass
);
4263 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4269 GEN_NEON_INTEGER_OP(hsub
);
4272 GEN_NEON_INTEGER_OP_ENV(qsub
);
4275 GEN_NEON_INTEGER_OP(cgt
);
4278 GEN_NEON_INTEGER_OP(cge
);
4281 GEN_NEON_INTEGER_OP(shl
);
4284 GEN_NEON_INTEGER_OP_ENV(qshl
);
4286 case 10: /* VRSHL */
4287 GEN_NEON_INTEGER_OP(rshl
);
4289 case 11: /* VQRSHL */
4290 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4293 GEN_NEON_INTEGER_OP(max
);
4296 GEN_NEON_INTEGER_OP(min
);
4299 GEN_NEON_INTEGER_OP(abd
);
4302 GEN_NEON_INTEGER_OP(abd
);
4303 NEON_GET_REG(T1
, rd
, pass
);
4307 if (!u
) { /* VADD */
4308 if (gen_neon_add(size
))
4312 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4313 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4314 case 2: gen_op_subl_T0_T1(); break;
4320 if (!u
) { /* VTST */
4322 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4323 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4324 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4329 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4330 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4331 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4336 case 18: /* Multiply. */
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;
4343 NEON_GET_REG(T1
, rd
, pass
);
4351 if (u
) { /* polynomial */
4352 gen_helper_neon_mul_p8(CPU_T001
);
4353 } else { /* Integer */
4355 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4356 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4357 case 2: gen_op_mul_T0_T1(); break;
4362 case 20: /* VPMAX */
4363 GEN_NEON_INTEGER_OP(pmax
);
4365 case 21: /* VPMIN */
4366 GEN_NEON_INTEGER_OP(pmin
);
4368 case 22: /* Hultiply high. */
4369 if (!u
) { /* VQDMULH */
4371 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4372 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4375 } else { /* VQRDHMUL */
4377 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4378 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4383 case 23: /* VPADD */
4387 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4388 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4389 case 2: gen_op_addl_T0_T1(); break;
4393 case 26: /* Floating point arithnetic. */
4394 switch ((u
<< 2) | size
) {
4396 gen_helper_neon_add_f32(CPU_T001
);
4399 gen_helper_neon_sub_f32(CPU_T001
);
4402 gen_helper_neon_add_f32(CPU_T001
);
4405 gen_helper_neon_abd_f32(CPU_T001
);
4411 case 27: /* Float multiply. */
4412 gen_helper_neon_mul_f32(CPU_T001
);
4414 NEON_GET_REG(T1
, rd
, pass
);
4416 gen_helper_neon_add_f32(CPU_T001
);
4418 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4422 case 28: /* Float compare. */
4424 gen_helper_neon_ceq_f32(CPU_T001
);
4427 gen_helper_neon_cge_f32(CPU_T001
);
4429 gen_helper_neon_cgt_f32(CPU_T001
);
4432 case 29: /* Float compare absolute. */
4436 gen_helper_neon_acge_f32(CPU_T001
);
4438 gen_helper_neon_acgt_f32(CPU_T001
);
4440 case 30: /* Float min/max. */
4442 gen_helper_neon_max_f32(CPU_T001
);
4444 gen_helper_neon_min_f32(CPU_T001
);
4448 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4450 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4455 /* Save the result. For elementwise operations we can put it
4456 straight into the destination register. For pairwise operations
4457 we have to be careful to avoid clobbering the source operands. */
4458 if (pairwise
&& rd
== rm
) {
4459 gen_neon_movl_scratch_T0(pass
);
4461 NEON_SET_REG(T0
, rd
, pass
);
4465 if (pairwise
&& rd
== rm
) {
4466 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4467 gen_neon_movl_T0_scratch(pass
);
4468 NEON_SET_REG(T0
, rd
, pass
);
4471 /* End of 3 register same size operations. */
4472 } else if (insn
& (1 << 4)) {
4473 if ((insn
& 0x00380080) != 0) {
4474 /* Two registers and shift. */
4475 op
= (insn
>> 8) & 0xf;
4476 if (insn
& (1 << 7)) {
4481 while ((insn
& (1 << (size
+ 19))) == 0)
4484 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4485 /* To avoid excessive dumplication of ops we implement shift
4486 by immediate using the variable shift operations. */
4488 /* Shift by immediate:
4489 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4490 /* Right shifts are encoded as N - shift, where N is the
4491 element size in bits. */
4493 shift
= shift
- (1 << (size
+ 3));
4501 imm
= (uint8_t) shift
;
4506 imm
= (uint16_t) shift
;
4517 for (pass
= 0; pass
< count
; pass
++) {
4519 neon_load_reg64(cpu_V0
, rm
+ pass
);
4520 tcg_gen_movi_i64(cpu_V1
, imm
);
4525 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4527 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4532 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4534 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4539 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4541 case 5: /* VSHL, VSLI */
4542 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4546 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4548 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4550 case 7: /* VQSHLU */
4551 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4554 if (op
== 1 || op
== 3) {
4556 neon_load_reg64(cpu_V0
, rd
+ pass
);
4557 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4558 } else if (op
== 4 || (op
== 5 && u
)) {
4560 cpu_abort(env
, "VS[LR]I.64 not implemented");
4562 neon_store_reg64(cpu_V0
, rd
+ pass
);
4563 } else { /* size < 3 */
4564 /* Operands in T0 and T1. */
4565 gen_op_movl_T1_im(imm
);
4566 NEON_GET_REG(T0
, rm
, pass
);
4570 GEN_NEON_INTEGER_OP(shl
);
4574 GEN_NEON_INTEGER_OP(rshl
);
4579 GEN_NEON_INTEGER_OP(shl
);
4581 case 5: /* VSHL, VSLI */
4583 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4584 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4585 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4590 GEN_NEON_INTEGER_OP_ENV(qshl
);
4592 case 7: /* VQSHLU */
4594 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4595 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4596 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4602 if (op
== 1 || op
== 3) {
4604 NEON_GET_REG(T1
, rd
, pass
);
4606 } else if (op
== 4 || (op
== 5 && u
)) {
4611 imm
= 0xff >> -shift
;
4613 imm
= (uint8_t)(0xff << shift
);
4619 imm
= 0xffff >> -shift
;
4621 imm
= (uint16_t)(0xffff << shift
);
4626 imm
= 0xffffffffu
>> -shift
;
4628 imm
= 0xffffffffu
<< shift
;
4633 tmp
= neon_load_reg(rd
, pass
);
4634 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4635 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4636 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4638 NEON_SET_REG(T0
, rd
, pass
);
4641 } else if (op
< 10) {
4642 /* Shift by immediate and narrow:
4643 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4644 shift
= shift
- (1 << (size
+ 3));
4648 imm
= (uint16_t)shift
;
4650 tmp2
= tcg_const_i32(imm
);
4653 imm
= (uint32_t)shift
;
4654 tmp2
= tcg_const_i32(imm
);
4656 tmp2
= tcg_const_i64(shift
);
4662 for (pass
= 0; pass
< 2; pass
++) {
4664 neon_load_reg64(cpu_V0
, rm
+ pass
);
4667 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp2
);
4669 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp2
);
4672 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp2
);
4674 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp2
);
4677 tmp
= neon_load_reg(rm
+ pass
, 0);
4678 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4679 tcg_gen_extu_i32_i64(cpu_V0
, tmp
);
4681 tmp
= neon_load_reg(rm
+ pass
, 1);
4682 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4683 tcg_gen_extu_i32_i64(cpu_V1
, tmp
);
4685 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 32);
4686 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4689 if (op
== 8 && !u
) {
4690 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4693 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4695 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4700 neon_store_reg(rd
, 0, tmp2
);
4701 neon_store_reg(rd
, 1, tmp
);
4704 } else if (op
== 10) {
4708 tmp
= neon_load_reg(rm
, 0);
4709 tmp2
= neon_load_reg(rm
, 1);
4710 for (pass
= 0; pass
< 2; pass
++) {
4714 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4717 /* The shift is less than the width of the source
4718 type, so we can just shift the whole register. */
4719 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4720 if (size
< 2 || !u
) {
4723 imm
= (0xffu
>> (8 - shift
));
4726 imm
= 0xffff >> (16 - shift
);
4728 imm64
= imm
| (((uint64_t)imm
) << 32);
4729 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4732 neon_store_reg64(cpu_V0
, rd
+ pass
);
4734 } else if (op
== 15 || op
== 16) {
4735 /* VCVT fixed-point. */
4736 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4737 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4740 gen_vfp_ulto(0, shift
);
4742 gen_vfp_slto(0, shift
);
4745 gen_vfp_toul(0, shift
);
4747 gen_vfp_tosl(0, shift
);
4749 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4754 } else { /* (insn & 0x00380080) == 0 */
4757 op
= (insn
>> 8) & 0xf;
4758 /* One register and immediate. */
4759 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4760 invert
= (insn
& (1 << 5)) != 0;
4778 imm
= (imm
<< 8) | (imm
<< 24);
4781 imm
= (imm
< 8) | 0xff;
4784 imm
= (imm
<< 16) | 0xffff;
4787 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4792 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4793 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4799 if (op
!= 14 || !invert
)
4800 gen_op_movl_T1_im(imm
);
4802 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4803 if (op
& 1 && op
< 12) {
4804 tmp
= neon_load_reg(rd
, pass
);
4806 /* The immediate value has already been inverted, so
4808 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4810 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4815 if (op
== 14 && invert
) {
4818 for (n
= 0; n
< 4; n
++) {
4819 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4820 val
|= 0xff << (n
* 8);
4822 tcg_gen_movi_i32(tmp
, val
);
4824 tcg_gen_movi_i32(tmp
, imm
);
4827 neon_store_reg(rd
, pass
, tmp
);
4830 } else { /* (insn & 0x00800010 == 0x00800010) */
4832 op
= (insn
>> 8) & 0xf;
4833 if ((insn
& (1 << 6)) == 0) {
4834 /* Three registers of different lengths. */
4838 /* prewiden, src1_wide, src2_wide */
4839 static const int neon_3reg_wide
[16][3] = {
4840 {1, 0, 0}, /* VADDL */
4841 {1, 1, 0}, /* VADDW */
4842 {1, 0, 0}, /* VSUBL */
4843 {1, 1, 0}, /* VSUBW */
4844 {0, 1, 1}, /* VADDHN */
4845 {0, 0, 0}, /* VABAL */
4846 {0, 1, 1}, /* VSUBHN */
4847 {0, 0, 0}, /* VABDL */
4848 {0, 0, 0}, /* VMLAL */
4849 {0, 0, 0}, /* VQDMLAL */
4850 {0, 0, 0}, /* VMLSL */
4851 {0, 0, 0}, /* VQDMLSL */
4852 {0, 0, 0}, /* Integer VMULL */
4853 {0, 0, 0}, /* VQDMULL */
4854 {0, 0, 0} /* Polynomial VMULL */
4857 prewiden
= neon_3reg_wide
[op
][0];
4858 src1_wide
= neon_3reg_wide
[op
][1];
4859 src2_wide
= neon_3reg_wide
[op
][2];
4861 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4864 /* Avoid overlapping operands. Wide source operands are
4865 always aligned so will never overlap with wide
4866 destinations in problematic ways. */
4867 if (rd
== rm
&& !src2_wide
) {
4868 NEON_GET_REG(T0
, rm
, 1);
4869 gen_neon_movl_scratch_T0(2);
4870 } else if (rd
== rn
&& !src1_wide
) {
4871 NEON_GET_REG(T0
, rn
, 1);
4872 gen_neon_movl_scratch_T0(2);
4874 for (pass
= 0; pass
< 2; pass
++) {
4876 neon_load_reg64(cpu_V0
, rn
+ pass
);
4878 if (pass
== 1 && rd
== rn
) {
4879 gen_neon_movl_T0_scratch(2);
4881 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4883 tmp
= neon_load_reg(rn
, pass
);
4886 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4890 neon_load_reg64(cpu_V1
, rm
+ pass
);
4892 if (pass
== 1 && rd
== rm
) {
4893 gen_neon_movl_T0_scratch(2);
4895 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4897 tmp2
= neon_load_reg(rm
, pass
);
4900 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4904 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4905 gen_neon_addl(size
);
4907 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4908 gen_neon_subl(size
);
4910 case 5: case 7: /* VABAL, VABDL */
4911 switch ((size
<< 1) | u
) {
4913 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4916 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4919 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4922 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4925 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4928 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4935 case 8: case 9: case 10: case 11: case 12: case 13:
4936 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4937 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4939 case 14: /* Polynomial VMULL */
4940 cpu_abort(env
, "Polynomial VMULL not implemented");
4942 default: /* 15 is RESERVED. */
4945 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4947 if (op
== 10 || op
== 11) {
4948 gen_neon_negl(cpu_V0
, size
);
4952 neon_load_reg64(cpu_V1
, rd
+ pass
);
4956 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4957 gen_neon_addl(size
);
4959 case 9: case 11: /* VQDMLAL, VQDMLSL */
4960 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4961 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4964 case 13: /* VQDMULL */
4965 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4970 neon_store_reg64(cpu_V0
, rd
+ pass
);
4971 } else if (op
== 4 || op
== 6) {
4972 /* Narrowing operation. */
4977 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4980 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4983 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4984 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4991 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4994 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4997 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4998 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4999 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5007 neon_store_reg(rd
, 0, tmp3
);
5008 neon_store_reg(rd
, 1, tmp
);
5011 /* Write back the result. */
5012 neon_store_reg64(cpu_V0
, rd
+ pass
);
5016 /* Two registers and a scalar. */
5018 case 0: /* Integer VMLA scalar */
5019 case 1: /* Float VMLA scalar */
5020 case 4: /* Integer VMLS scalar */
5021 case 5: /* Floating point VMLS scalar */
5022 case 8: /* Integer VMUL scalar */
5023 case 9: /* Floating point VMUL scalar */
5024 case 12: /* VQDMULH scalar */
5025 case 13: /* VQRDMULH scalar */
5026 gen_neon_get_scalar(size
, rm
);
5027 gen_neon_movl_scratch_T0(0);
5028 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5030 gen_neon_movl_T0_scratch(0);
5031 NEON_GET_REG(T1
, rn
, pass
);
5034 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5036 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5038 } else if (op
== 13) {
5040 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5042 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5044 } else if (op
& 1) {
5045 gen_helper_neon_mul_f32(CPU_T001
);
5048 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5049 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5050 case 2: gen_op_mul_T0_T1(); break;
5056 NEON_GET_REG(T1
, rd
, pass
);
5062 gen_helper_neon_add_f32(CPU_T001
);
5068 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5074 NEON_SET_REG(T0
, rd
, pass
);
5077 case 2: /* VMLAL sclar */
5078 case 3: /* VQDMLAL scalar */
5079 case 6: /* VMLSL scalar */
5080 case 7: /* VQDMLSL scalar */
5081 case 10: /* VMULL scalar */
5082 case 11: /* VQDMULL scalar */
5083 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5086 gen_neon_get_scalar(size
, rm
);
5087 NEON_GET_REG(T1
, rn
, 1);
5089 for (pass
= 0; pass
< 2; pass
++) {
5091 tmp
= neon_load_reg(rn
, 0);
5094 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5097 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5098 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5099 if (op
== 6 || op
== 7) {
5100 gen_neon_negl(cpu_V0
, size
);
5103 neon_load_reg64(cpu_V1
, rd
+ pass
);
5107 gen_neon_addl(size
);
5110 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5111 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5117 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5122 neon_store_reg64(cpu_V0
, rd
+ pass
);
5125 default: /* 14 and 15 are RESERVED */
5129 } else { /* size == 3 */
5132 imm
= (insn
>> 8) & 0xf;
5139 neon_load_reg64(cpu_V0
, rn
);
5141 neon_load_reg64(cpu_V1
, rn
+ 1);
5143 } else if (imm
== 8) {
5144 neon_load_reg64(cpu_V0
, rn
+ 1);
5146 neon_load_reg64(cpu_V1
, rm
);
5149 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5151 neon_load_reg64(cpu_V0
, rn
);
5152 neon_load_reg64(tmp
, rn
+ 1);
5154 neon_load_reg64(cpu_V0
, rn
+ 1);
5155 neon_load_reg64(tmp
, rm
);
5157 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5158 tcg_gen_shli_i64(cpu_V1
, tmp
, 64 - ((imm
& 7) * 8));
5159 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5161 neon_load_reg64(cpu_V1
, rm
);
5163 neon_load_reg64(cpu_V1
, rm
+ 1);
5166 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5167 tcg_gen_shri_i64(tmp
, tmp
, imm
* 8);
5168 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp
);
5170 neon_load_reg64(cpu_V0
, rn
);
5171 tcg_gen_shri_i32(cpu_V0
, cpu_V0
, imm
* 8);
5172 neon_load_reg64(cpu_V1
, rm
);
5173 tcg_gen_shli_i32(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5174 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5176 neon_store_reg64(cpu_V0
, rd
);
5178 neon_store_reg64(cpu_V1
, rd
+ 1);
5180 } else if ((insn
& (1 << 11)) == 0) {
5181 /* Two register misc. */
5182 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5183 size
= (insn
>> 18) & 3;
5185 case 0: /* VREV64 */
5188 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5189 NEON_GET_REG(T0
, rm
, pass
* 2);
5190 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5192 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5193 case 1: gen_swap_half(cpu_T
[0]); break;
5194 case 2: /* no-op */ break;
5197 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5199 NEON_SET_REG(T1
, rd
, pass
* 2);
5201 gen_op_movl_T0_T1();
5203 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5204 case 1: gen_swap_half(cpu_T
[0]); break;
5207 NEON_SET_REG(T0
, rd
, pass
* 2);
5211 case 4: case 5: /* VPADDL */
5212 case 12: case 13: /* VPADAL */
5215 for (pass
= 0; pass
< q
+ 1; pass
++) {
5216 tmp
= neon_load_reg(rm
, pass
* 2);
5217 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5218 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5219 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5221 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5222 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5223 case 2: tcg_gen_add_i64(CPU_V001
); break;
5228 neon_load_reg64(cpu_V1
, rd
+ pass
);
5229 gen_neon_addl(size
);
5231 neon_store_reg64(cpu_V0
, rd
+ pass
);
5236 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5237 NEON_GET_REG(T0
, rm
, n
);
5238 NEON_GET_REG(T1
, rd
, n
+ 1);
5239 NEON_SET_REG(T1
, rm
, n
);
5240 NEON_SET_REG(T0
, rd
, n
+ 1);
5248 Rd A3 A2 A1 A0 B2 B0 A2 A0
5249 Rm B3 B2 B1 B0 B3 B1 A3 A1
5253 gen_neon_unzip(rd
, q
, 0, size
);
5254 gen_neon_unzip(rm
, q
, 4, size
);
5256 static int unzip_order_q
[8] =
5257 {0, 2, 4, 6, 1, 3, 5, 7};
5258 for (n
= 0; n
< 8; n
++) {
5259 int reg
= (n
< 4) ? rd
: rm
;
5260 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5261 NEON_SET_REG(T0
, reg
, n
% 4);
5264 static int unzip_order
[4] =
5266 for (n
= 0; n
< 4; n
++) {
5267 int reg
= (n
< 2) ? rd
: rm
;
5268 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5269 NEON_SET_REG(T0
, reg
, n
% 2);
5275 Rd A3 A2 A1 A0 B1 A1 B0 A0
5276 Rm B3 B2 B1 B0 B3 A3 B2 A2
5280 count
= (q
? 4 : 2);
5281 for (n
= 0; n
< count
; n
++) {
5282 NEON_GET_REG(T0
, rd
, n
);
5283 NEON_GET_REG(T1
, rd
, n
);
5285 case 0: gen_helper_neon_zip_u8(); break;
5286 case 1: gen_helper_neon_zip_u16(); break;
5287 case 2: /* no-op */; break;
5290 gen_neon_movl_scratch_T0(n
* 2);
5291 gen_neon_movl_scratch_T1(n
* 2 + 1);
5293 for (n
= 0; n
< count
* 2; n
++) {
5294 int reg
= (n
< count
) ? rd
: rm
;
5295 gen_neon_movl_T0_scratch(n
);
5296 NEON_SET_REG(T0
, reg
, n
% count
);
5299 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5302 for (pass
= 0; pass
< 2; pass
++) {
5303 neon_load_reg64(cpu_V0
, rm
+ pass
);
5305 if (op
== 36 && q
== 0) {
5306 gen_neon_narrow(size
, tmp
, cpu_V0
);
5308 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5310 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5315 neon_store_reg(rd
, 0, tmp2
);
5316 neon_store_reg(rd
, 1, tmp
);
5320 case 38: /* VSHLL */
5323 tmp
= neon_load_reg(rm
, 0);
5324 tmp2
= neon_load_reg(rm
, 1);
5325 for (pass
= 0; pass
< 2; pass
++) {
5328 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5329 neon_store_reg64(cpu_V0
, rd
+ pass
);
5334 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5335 if (op
== 30 || op
== 31 || op
>= 58) {
5336 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5337 neon_reg_offset(rm
, pass
));
5339 NEON_GET_REG(T0
, rm
, pass
);
5342 case 1: /* VREV32 */
5344 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5345 case 1: gen_swap_half(cpu_T
[0]); break;
5349 case 2: /* VREV16 */
5352 gen_rev16(cpu_T
[0]);
5356 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5357 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5358 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5364 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5365 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5366 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5373 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5380 case 14: /* VQABS */
5382 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5383 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5384 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5388 case 15: /* VQNEG */
5390 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5391 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5392 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5396 case 16: case 19: /* VCGT #0, VCLE #0 */
5397 gen_op_movl_T1_im(0);
5399 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5400 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5401 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5407 case 17: case 20: /* VCGE #0, VCLT #0 */
5408 gen_op_movl_T1_im(0);
5410 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5411 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5412 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5418 case 18: /* VCEQ #0 */
5419 gen_op_movl_T1_im(0);
5421 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5422 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5423 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5429 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5430 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5431 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5436 gen_op_movl_T1_im(0);
5441 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5442 gen_op_movl_T1_im(0);
5443 gen_helper_neon_cgt_f32(CPU_T001
);
5447 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5448 gen_op_movl_T1_im(0);
5449 gen_helper_neon_cge_f32(CPU_T001
);
5453 case 26: /* Float VCEQ #0 */
5454 gen_op_movl_T1_im(0);
5455 gen_helper_neon_ceq_f32(CPU_T001
);
5457 case 30: /* Float VABS */
5460 case 31: /* Float VNEG */
5464 NEON_GET_REG(T1
, rd
, pass
);
5465 NEON_SET_REG(T1
, rm
, pass
);
5468 NEON_GET_REG(T1
, rd
, pass
);
5470 case 0: gen_helper_neon_trn_u8(); break;
5471 case 1: gen_helper_neon_trn_u16(); break;
5475 NEON_SET_REG(T1
, rm
, pass
);
5477 case 56: /* Integer VRECPE */
5478 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5480 case 57: /* Integer VRSQRTE */
5481 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5483 case 58: /* Float VRECPE */
5484 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5486 case 59: /* Float VRSQRTE */
5487 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5489 case 60: /* VCVT.F32.S32 */
5492 case 61: /* VCVT.F32.U32 */
5495 case 62: /* VCVT.S32.F32 */
5498 case 63: /* VCVT.U32.F32 */
5502 /* Reserved: 21, 29, 39-56 */
5505 if (op
== 30 || op
== 31 || op
>= 58) {
5506 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5507 neon_reg_offset(rd
, pass
));
5509 NEON_SET_REG(T0
, rd
, pass
);
5514 } else if ((insn
& (1 << 10)) == 0) {
5516 n
= (insn
>> 5) & 0x18;
5517 if (insn
& (1 << 6)) {
5518 tmp
= neon_load_reg(rd
, 0);
5521 tcg_gen_movi_i32(tmp
, 0);
5523 tmp2
= neon_load_reg(rm
, 0);
5524 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5526 if (insn
& (1 << 6)) {
5527 tmp
= neon_load_reg(rd
, 1);
5530 tcg_gen_movi_i32(tmp
, 0);
5532 tmp3
= neon_load_reg(rm
, 1);
5533 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5535 neon_store_reg(rd
, 0, tmp2
);
5536 neon_store_reg(rd
, 1, tmp2
);
5537 } else if ((insn
& 0x380) == 0) {
5539 if (insn
& (1 << 19)) {
5540 NEON_SET_REG(T0
, rm
, 1);
5542 NEON_SET_REG(T0
, rm
, 0);
5544 if (insn
& (1 << 16)) {
5545 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5546 } else if (insn
& (1 << 17)) {
5547 if ((insn
>> 18) & 1)
5548 gen_neon_dup_high16(cpu_T
[0]);
5550 gen_neon_dup_low16(cpu_T
[0]);
5552 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5553 NEON_SET_REG(T0
, rd
, pass
);
5563 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5567 cpnum
= (insn
>> 8) & 0xf;
5568 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5569 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5575 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5576 return disas_iwmmxt_insn(env
, s
, insn
);
5577 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5578 return disas_dsp_insn(env
, s
, insn
);
5583 return disas_vfp_insn (env
, s
, insn
);
5585 return disas_cp15_insn (env
, s
, insn
);
5587 /* Unknown coprocessor. See if the board has hooked it. */
5588 return disas_cp_insn (env
, s
, insn
);
5593 /* Store a 64-bit value to a register pair. Clobbers val. */
5594 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv val
)
5598 tcg_gen_trunc_i64_i32(tmp
, val
);
5599 store_reg(s
, rlow
, tmp
);
5601 tcg_gen_shri_i64(val
, val
, 32);
5602 tcg_gen_trunc_i64_i32(tmp
, val
);
5603 store_reg(s
, rhigh
, tmp
);
5606 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5607 static void gen_addq_lo(DisasContext
*s
, TCGv val
, int rlow
)
5612 /* Load 64-bit value rd:rn. */
5613 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5614 tmp2
= load_reg(s
, rlow
);
5615 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5617 tcg_gen_add_i64(val
, val
, tmp
);
5620 /* load and add a 64-bit value from a register pair. */
5621 static void gen_addq(DisasContext
*s
, TCGv val
, int rlow
, int rhigh
)
5626 /* Load 64-bit value rd:rn. */
5627 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5628 tmp2
= load_reg(s
, rhigh
);
5629 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5631 tcg_gen_shli_i64(tmp
, tmp
, 32);
5632 tcg_gen_add_i64(val
, val
, tmp
);
5634 tmp2
= load_reg(s
, rlow
);
5635 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5637 tcg_gen_add_i64(val
, val
, tmp
);
5640 /* Set N and Z flags from a 64-bit value. */
5641 static void gen_logicq_cc(TCGv val
)
5643 TCGv tmp
= new_tmp();
5644 gen_helper_logicq_cc(tmp
, val
);
5649 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5651 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5657 insn
= ldl_code(s
->pc
);
5660 /* M variants do not implement ARM mode. */
5665 /* Unconditional instructions. */
5666 if (((insn
>> 25) & 7) == 1) {
5667 /* NEON Data processing. */
5668 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5671 if (disas_neon_data_insn(env
, s
, insn
))
5675 if ((insn
& 0x0f100000) == 0x04000000) {
5676 /* NEON load/store. */
5677 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5680 if (disas_neon_ls_insn(env
, s
, insn
))
5684 if ((insn
& 0x0d70f000) == 0x0550f000)
5686 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5689 if (insn
& (1 << 9)) {
5690 /* BE8 mode not implemented. */
5694 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5695 switch ((insn
>> 4) & 0xf) {
5698 gen_helper_clrex(cpu_env
);
5704 /* We don't emulate caches so these are a no-op. */
5709 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5715 op1
= (insn
& 0x1f);
5716 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5717 addr
= load_reg(s
, 13);
5720 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5722 i
= (insn
>> 23) & 3;
5724 case 0: offset
= -4; break; /* DA */
5725 case 1: offset
= -8; break; /* DB */
5726 case 2: offset
= 0; break; /* IA */
5727 case 3: offset
= 4; break; /* IB */
5731 tcg_gen_addi_i32(addr
, addr
, offset
);
5732 tmp
= load_reg(s
, 14);
5733 gen_st32(tmp
, addr
, 0);
5735 gen_helper_cpsr_read(tmp
);
5736 tcg_gen_addi_i32(addr
, addr
, 4);
5737 gen_st32(tmp
, addr
, 0);
5738 if (insn
& (1 << 21)) {
5739 /* Base writeback. */
5741 case 0: offset
= -8; break;
5742 case 1: offset
= -4; break;
5743 case 2: offset
= 4; break;
5744 case 3: offset
= 0; break;
5748 tcg_gen_addi_i32(addr
, tmp
, offset
);
5749 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5750 gen_movl_reg_T1(s
, 13);
5752 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5757 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5763 rn
= (insn
>> 16) & 0xf;
5764 addr
= load_reg(s
, rn
);
5765 i
= (insn
>> 23) & 3;
5767 case 0: offset
= -4; break; /* DA */
5768 case 1: offset
= -8; break; /* DB */
5769 case 2: offset
= 0; break; /* IA */
5770 case 3: offset
= 4; break; /* IB */
5774 tcg_gen_addi_i32(addr
, addr
, offset
);
5775 /* Load PC into tmp and CPSR into tmp2. */
5776 tmp
= gen_ld32(addr
, 0);
5777 tcg_gen_addi_i32(addr
, addr
, 4);
5778 tmp2
= gen_ld32(addr
, 0);
5779 if (insn
& (1 << 21)) {
5780 /* Base writeback. */
5782 case 0: offset
= -8; break;
5783 case 1: offset
= -4; break;
5784 case 2: offset
= 4; break;
5785 case 3: offset
= 0; break;
5789 tcg_gen_addi_i32(addr
, addr
, offset
);
5790 store_reg(s
, rn
, addr
);
5794 gen_rfe(s
, tmp
, tmp2
);
5795 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5796 /* branch link and change to thumb (blx <offset>) */
5799 val
= (uint32_t)s
->pc
;
5801 tcg_gen_movi_i32(tmp
, val
);
5802 store_reg(s
, 14, tmp
);
5803 /* Sign-extend the 24-bit offset */
5804 offset
= (((int32_t)insn
) << 8) >> 8;
5805 /* offset * 4 + bit24 * 2 + (thumb bit) */
5806 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5807 /* pipeline offset */
5811 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5812 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5813 /* iWMMXt register transfer. */
5814 if (env
->cp15
.c15_cpar
& (1 << 1))
5815 if (!disas_iwmmxt_insn(env
, s
, insn
))
5818 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5819 /* Coprocessor double register transfer. */
5820 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5821 /* Additional coprocessor register transfer. */
5822 } else if ((insn
& 0x0ff10010) == 0x01000000) {
5825 /* cps (privileged) */
5829 if (insn
& (1 << 19)) {
5830 if (insn
& (1 << 8))
5832 if (insn
& (1 << 7))
5834 if (insn
& (1 << 6))
5836 if (insn
& (1 << 18))
5839 if (insn
& (1 << 14)) {
5841 val
|= (insn
& 0x1f);
5844 gen_op_movl_T0_im(val
);
5845 gen_set_psr_T0(s
, mask
, 0);
5852 /* if not always execute, we generate a conditional jump to
5854 s
->condlabel
= gen_new_label();
5855 gen_test_cc(cond
^ 1, s
->condlabel
);
5858 if ((insn
& 0x0f900000) == 0x03000000) {
5859 if ((insn
& (1 << 21)) == 0) {
5861 rd
= (insn
>> 12) & 0xf;
5862 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5863 if ((insn
& (1 << 22)) == 0) {
5866 tcg_gen_movi_i32(tmp
, val
);
5869 tmp
= load_reg(s
, rd
);
5870 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
5871 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5873 store_reg(s
, rd
, tmp
);
5875 if (((insn
>> 12) & 0xf) != 0xf)
5877 if (((insn
>> 16) & 0xf) == 0) {
5878 gen_nop_hint(s
, insn
& 0xff);
5880 /* CPSR = immediate */
5882 shift
= ((insn
>> 8) & 0xf) * 2;
5884 val
= (val
>> shift
) | (val
<< (32 - shift
));
5885 gen_op_movl_T0_im(val
);
5886 i
= ((insn
& (1 << 22)) != 0);
5887 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5891 } else if ((insn
& 0x0f900000) == 0x01000000
5892 && (insn
& 0x00000090) != 0x00000090) {
5893 /* miscellaneous instructions */
5894 op1
= (insn
>> 21) & 3;
5895 sh
= (insn
>> 4) & 0xf;
5898 case 0x0: /* move program status register */
5901 gen_movl_T0_reg(s
, rm
);
5902 i
= ((op1
& 2) != 0);
5903 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5907 rd
= (insn
>> 12) & 0xf;
5911 tmp
= load_cpu_field(spsr
);
5914 gen_helper_cpsr_read(tmp
);
5916 store_reg(s
, rd
, tmp
);
5921 /* branch/exchange thumb (bx). */
5922 tmp
= load_reg(s
, rm
);
5924 } else if (op1
== 3) {
5926 rd
= (insn
>> 12) & 0xf;
5927 tmp
= load_reg(s
, rm
);
5928 gen_helper_clz(tmp
, tmp
);
5929 store_reg(s
, rd
, tmp
);
5937 /* Trivial implementation equivalent to bx. */
5938 tmp
= load_reg(s
, rm
);
5948 /* branch link/exchange thumb (blx) */
5949 tmp
= load_reg(s
, rm
);
5951 tcg_gen_movi_i32(tmp2
, s
->pc
);
5952 store_reg(s
, 14, tmp2
);
5955 case 0x5: /* saturating add/subtract */
5956 rd
= (insn
>> 12) & 0xf;
5957 rn
= (insn
>> 16) & 0xf;
5958 tmp
= load_reg(s
, rn
);
5959 tmp2
= load_reg(s
, rn
);
5961 gen_helper_double_saturate(tmp2
, tmp2
);
5963 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
5965 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
5967 store_reg(s
, rd
, tmp
);
5970 gen_set_condexec(s
);
5971 gen_set_pc_im(s
->pc
- 4);
5972 gen_exception(EXCP_BKPT
);
5973 s
->is_jmp
= DISAS_JUMP
;
5975 case 0x8: /* signed multiply */
5979 rs
= (insn
>> 8) & 0xf;
5980 rn
= (insn
>> 12) & 0xf;
5981 rd
= (insn
>> 16) & 0xf;
5983 /* (32 * 16) >> 16 */
5984 tmp
= load_reg(s
, rm
);
5985 tmp2
= load_reg(s
, rs
);
5987 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
5990 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
5991 tcg_gen_shri_i64(tmp2
, tmp2
, 16);
5993 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
5994 if ((sh
& 2) == 0) {
5995 tmp2
= load_reg(s
, rn
);
5996 gen_helper_add_setq(tmp
, tmp
, tmp2
);
5999 store_reg(s
, rd
, tmp
);
6002 tmp
= load_reg(s
, rm
);
6003 tmp2
= load_reg(s
, rs
);
6004 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6007 tmp
= tcg_temp_new(TCG_TYPE_I64
);
6008 tcg_gen_ext_i32_i64(tmp
, cpu_T
[0]);
6009 gen_addq(s
, tmp
, rn
, rd
);
6010 gen_storeq_reg(s
, rn
, rd
, tmp
);
6013 tmp2
= load_reg(s
, rn
);
6014 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6017 store_reg(s
, rd
, tmp
);
6024 } else if (((insn
& 0x0e000000) == 0 &&
6025 (insn
& 0x00000090) != 0x90) ||
6026 ((insn
& 0x0e000000) == (1 << 25))) {
6027 int set_cc
, logic_cc
, shiftop
;
6029 op1
= (insn
>> 21) & 0xf;
6030 set_cc
= (insn
>> 20) & 1;
6031 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6033 /* data processing instruction */
6034 if (insn
& (1 << 25)) {
6035 /* immediate operand */
6037 shift
= ((insn
>> 8) & 0xf) * 2;
6039 val
= (val
>> shift
) | (val
<< (32 - shift
));
6040 gen_op_movl_T1_im(val
);
6041 if (logic_cc
&& shift
)
6042 gen_set_CF_bit31(cpu_T
[1]);
6046 gen_movl_T1_reg(s
, rm
);
6047 shiftop
= (insn
>> 5) & 3;
6048 if (!(insn
& (1 << 4))) {
6049 shift
= (insn
>> 7) & 0x1f;
6050 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
6052 rs
= (insn
>> 8) & 0xf;
6053 tmp
= load_reg(s
, rs
);
6054 gen_arm_shift_reg(cpu_T
[1], shiftop
, tmp
, logic_cc
);
6057 if (op1
!= 0x0f && op1
!= 0x0d) {
6058 rn
= (insn
>> 16) & 0xf;
6059 gen_movl_T0_reg(s
, rn
);
6061 rd
= (insn
>> 12) & 0xf;
6064 gen_op_andl_T0_T1();
6065 gen_movl_reg_T0(s
, rd
);
6067 gen_op_logic_T0_cc();
6070 gen_op_xorl_T0_T1();
6071 gen_movl_reg_T0(s
, rd
);
6073 gen_op_logic_T0_cc();
6076 if (set_cc
&& rd
== 15) {
6077 /* SUBS r15, ... is used for exception return. */
6080 gen_op_subl_T0_T1_cc();
6081 gen_exception_return(s
);
6084 gen_op_subl_T0_T1_cc();
6086 gen_op_subl_T0_T1();
6087 gen_movl_reg_T0(s
, rd
);
6092 gen_op_rsbl_T0_T1_cc();
6094 gen_op_rsbl_T0_T1();
6095 gen_movl_reg_T0(s
, rd
);
6099 gen_op_addl_T0_T1_cc();
6101 gen_op_addl_T0_T1();
6102 gen_movl_reg_T0(s
, rd
);
6106 gen_op_adcl_T0_T1_cc();
6109 gen_movl_reg_T0(s
, rd
);
6113 gen_op_sbcl_T0_T1_cc();
6116 gen_movl_reg_T0(s
, rd
);
6120 gen_op_rscl_T0_T1_cc();
6123 gen_movl_reg_T0(s
, rd
);
6127 gen_op_andl_T0_T1();
6128 gen_op_logic_T0_cc();
6133 gen_op_xorl_T0_T1();
6134 gen_op_logic_T0_cc();
6139 gen_op_subl_T0_T1_cc();
6144 gen_op_addl_T0_T1_cc();
6149 gen_movl_reg_T0(s
, rd
);
6151 gen_op_logic_T0_cc();
6154 if (logic_cc
&& rd
== 15) {
6155 /* MOVS r15, ... is used for exception return. */
6158 gen_op_movl_T0_T1();
6159 gen_exception_return(s
);
6161 gen_movl_reg_T1(s
, rd
);
6163 gen_op_logic_T1_cc();
6167 gen_op_bicl_T0_T1();
6168 gen_movl_reg_T0(s
, rd
);
6170 gen_op_logic_T0_cc();
6175 gen_movl_reg_T1(s
, rd
);
6177 gen_op_logic_T1_cc();
6181 /* other instructions */
6182 op1
= (insn
>> 24) & 0xf;
6186 /* multiplies, extra load/stores */
6187 sh
= (insn
>> 5) & 3;
6190 rd
= (insn
>> 16) & 0xf;
6191 rn
= (insn
>> 12) & 0xf;
6192 rs
= (insn
>> 8) & 0xf;
6194 op1
= (insn
>> 20) & 0xf;
6196 case 0: case 1: case 2: case 3: case 6:
6198 tmp
= load_reg(s
, rs
);
6199 tmp2
= load_reg(s
, rm
);
6200 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6202 if (insn
& (1 << 22)) {
6203 /* Subtract (mls) */
6205 tmp2
= load_reg(s
, rn
);
6206 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6208 } else if (insn
& (1 << 21)) {
6210 tmp2
= load_reg(s
, rn
);
6211 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6214 if (insn
& (1 << 20))
6216 store_reg(s
, rd
, tmp
);
6220 tmp
= load_reg(s
, rs
);
6221 tmp2
= load_reg(s
, rm
);
6222 if (insn
& (1 << 22))
6223 tmp
= gen_muls_i64_i32(tmp
, tmp2
);
6225 tmp
= gen_mulu_i64_i32(tmp
, tmp2
);
6226 if (insn
& (1 << 21)) /* mult accumulate */
6227 gen_addq(s
, tmp
, rn
, rd
);
6228 if (!(insn
& (1 << 23))) { /* double accumulate */
6230 gen_addq_lo(s
, tmp
, rn
);
6231 gen_addq_lo(s
, tmp
, rd
);
6233 if (insn
& (1 << 20))
6235 gen_storeq_reg(s
, rn
, rd
, tmp
);
6239 rn
= (insn
>> 16) & 0xf;
6240 rd
= (insn
>> 12) & 0xf;
6241 if (insn
& (1 << 23)) {
6242 /* load/store exclusive */
6243 gen_movl_T1_reg(s
, rn
);
6244 if (insn
& (1 << 20)) {
6245 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6246 tmp
= gen_ld32(addr
, IS_USER(s
));
6247 store_reg(s
, rd
, tmp
);
6249 int label
= gen_new_label();
6251 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6252 tcg_gen_brcond_i32(TCG_COND_NE
, cpu_T
[0],
6253 tcg_const_i32(0), label
);
6254 tmp
= load_reg(s
,rm
);
6255 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
6256 gen_movl_reg_T0(s
, rd
);
6259 /* SWP instruction */
6262 /* ??? This is not really atomic. However we know
6263 we never have multiple CPUs running in parallel,
6264 so it is good enough. */
6265 addr
= load_reg(s
, rn
);
6266 tmp
= load_reg(s
, rm
);
6267 if (insn
& (1 << 22)) {
6268 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6269 gen_st8(tmp
, addr
, IS_USER(s
));
6271 tmp2
= gen_ld32(addr
, IS_USER(s
));
6272 gen_st32(tmp
, addr
, IS_USER(s
));
6275 store_reg(s
, rd
, tmp2
);
6281 /* Misc load/store */
6282 rn
= (insn
>> 16) & 0xf;
6283 rd
= (insn
>> 12) & 0xf;
6284 addr
= load_reg(s
, rn
);
6285 if (insn
& (1 << 24))
6286 gen_add_datah_offset(s
, insn
, 0, addr
);
6288 if (insn
& (1 << 20)) {
6292 tmp
= gen_ld16u(addr
, IS_USER(s
));
6295 tmp
= gen_ld8s(addr
, IS_USER(s
));
6299 tmp
= gen_ld16s(addr
, IS_USER(s
));
6303 } else if (sh
& 2) {
6307 tmp
= load_reg(s
, rd
);
6308 gen_st32(tmp
, addr
, IS_USER(s
));
6309 tcg_gen_addi_i32(addr
, addr
, 4);
6310 tmp
= load_reg(s
, rd
+ 1);
6311 gen_st32(tmp
, addr
, IS_USER(s
));
6315 tmp
= gen_ld32(addr
, IS_USER(s
));
6316 store_reg(s
, rd
, tmp
);
6317 tcg_gen_addi_i32(addr
, addr
, 4);
6318 tmp
= gen_ld32(addr
, IS_USER(s
));
6322 address_offset
= -4;
6325 tmp
= load_reg(s
, rd
);
6326 gen_st16(tmp
, addr
, IS_USER(s
));
6329 /* Perform base writeback before the loaded value to
6330 ensure correct behavior with overlapping index registers.
6331 ldrd with base writeback is is undefined if the
6332 destination and index registers overlap. */
6333 if (!(insn
& (1 << 24))) {
6334 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6335 store_reg(s
, rn
, addr
);
6336 } else if (insn
& (1 << 21)) {
6338 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6339 store_reg(s
, rn
, addr
);
6344 /* Complete the load. */
6345 store_reg(s
, rd
, tmp
);
6354 if (insn
& (1 << 4)) {
6356 /* Armv6 Media instructions. */
6358 rn
= (insn
>> 16) & 0xf;
6359 rd
= (insn
>> 12) & 0xf;
6360 rs
= (insn
>> 8) & 0xf;
6361 switch ((insn
>> 23) & 3) {
6362 case 0: /* Parallel add/subtract. */
6363 op1
= (insn
>> 20) & 7;
6364 tmp
= load_reg(s
, rn
);
6365 tmp2
= load_reg(s
, rm
);
6366 sh
= (insn
>> 5) & 7;
6367 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6369 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6371 store_reg(s
, rd
, tmp
);
6374 if ((insn
& 0x00700020) == 0) {
6376 tmp
= load_reg(s
, rn
);
6377 tmp2
= load_reg(s
, rm
);
6378 shift
= (insn
>> 7) & 0x1f;
6380 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6381 if (insn
& (1 << 6)) {
6383 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6384 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff);
6387 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
6388 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6390 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6391 store_reg(s
, rd
, tmp
);
6392 } else if ((insn
& 0x00200020) == 0x00200000) {
6394 tmp
= load_reg(s
, rm
);
6395 shift
= (insn
>> 7) & 0x1f;
6396 if (insn
& (1 << 6)) {
6399 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6401 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6403 sh
= (insn
>> 16) & 0x1f;
6405 if (insn
& (1 << 22))
6406 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6408 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6410 store_reg(s
, rd
, tmp
);
6411 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6413 tmp
= load_reg(s
, rm
);
6414 sh
= (insn
>> 16) & 0x1f;
6416 if (insn
& (1 << 22))
6417 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6419 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6421 store_reg(s
, rd
, tmp
);
6422 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6424 tmp
= load_reg(s
, rn
);
6425 tmp2
= load_reg(s
, rm
);
6427 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6428 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6431 store_reg(s
, rd
, tmp
);
6432 } else if ((insn
& 0x000003e0) == 0x00000060) {
6433 tmp
= load_reg(s
, rm
);
6434 shift
= (insn
>> 10) & 3;
6435 /* ??? In many cases it's not neccessary to do a
6436 rotate, a shift is sufficient. */
6438 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6439 op1
= (insn
>> 20) & 7;
6441 case 0: gen_sxtb16(tmp
); break;
6442 case 2: gen_sxtb(tmp
); break;
6443 case 3: gen_sxth(tmp
); break;
6444 case 4: gen_uxtb16(tmp
); break;
6445 case 6: gen_uxtb(tmp
); break;
6446 case 7: gen_uxth(tmp
); break;
6447 default: goto illegal_op
;
6450 tmp2
= load_reg(s
, rn
);
6451 if ((op1
& 3) == 0) {
6452 gen_add16(tmp
, tmp2
);
6454 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6458 store_reg(s
, rd
, tmp2
);
6459 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6461 tmp
= load_reg(s
, rm
);
6462 if (insn
& (1 << 22)) {
6463 if (insn
& (1 << 7)) {
6467 gen_helper_rbit(tmp
, tmp
);
6470 if (insn
& (1 << 7))
6473 tcg_gen_bswap_i32(tmp
, tmp
);
6475 store_reg(s
, rd
, tmp
);
6480 case 2: /* Multiplies (Type 3). */
6481 tmp
= load_reg(s
, rm
);
6482 tmp2
= load_reg(s
, rs
);
6483 if (insn
& (1 << 20)) {
6484 /* Signed multiply most significant [accumulate]. */
6485 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
6486 if (insn
& (1 << 5))
6487 tcg_gen_addi_i64(tmp2
, tmp2
, 0x80000000u
);
6488 tcg_gen_shri_i64(tmp2
, tmp2
, 32);
6490 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
6492 tmp2
= load_reg(s
, rn
);
6493 if (insn
& (1 << 6)) {
6494 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6496 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6500 store_reg(s
, rd
, tmp
);
6502 if (insn
& (1 << 5))
6503 gen_swap_half(tmp2
);
6504 gen_smul_dual(tmp
, tmp2
);
6505 /* This addition cannot overflow. */
6506 if (insn
& (1 << 6)) {
6507 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6509 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6512 if (insn
& (1 << 22)) {
6513 /* smlald, smlsld */
6514 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
6515 tcg_gen_ext_i32_i64(tmp2
, tmp
);
6517 gen_addq(s
, tmp2
, rn
, rd
);
6518 gen_storeq_reg(s
, rn
, rd
, tmp2
);
6520 /* smuad, smusd, smlad, smlsd */
6523 tmp2
= load_reg(s
, rn
);
6524 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6527 store_reg(s
, rd
, tmp
);
6532 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6534 case 0: /* Unsigned sum of absolute differences. */
6536 tmp
= load_reg(s
, rm
);
6537 tmp2
= load_reg(s
, rs
);
6538 gen_helper_usad8(tmp
, tmp
, tmp2
);
6541 tmp2
= load_reg(s
, rn
);
6542 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6545 store_reg(s
, rd
, tmp
);
6547 case 0x20: case 0x24: case 0x28: case 0x2c:
6548 /* Bitfield insert/clear. */
6550 shift
= (insn
>> 7) & 0x1f;
6551 i
= (insn
>> 16) & 0x1f;
6555 tcg_gen_movi_i32(tmp
, 0);
6557 tmp
= load_reg(s
, rm
);
6560 tmp2
= load_reg(s
, rd
);
6561 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6564 store_reg(s
, rd
, tmp
);
6566 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6567 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6568 tmp
= load_reg(s
, rm
);
6569 shift
= (insn
>> 7) & 0x1f;
6570 i
= ((insn
>> 16) & 0x1f) + 1;
6575 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6577 gen_sbfx(tmp
, shift
, i
);
6580 store_reg(s
, rd
, tmp
);
6590 /* Check for undefined extension instructions
6591 * per the ARM Bible IE:
6592 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6594 sh
= (0xf << 20) | (0xf << 4);
6595 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6599 /* load/store byte/word */
6600 rn
= (insn
>> 16) & 0xf;
6601 rd
= (insn
>> 12) & 0xf;
6602 tmp2
= load_reg(s
, rn
);
6603 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6604 if (insn
& (1 << 24))
6605 gen_add_data_offset(s
, insn
, tmp2
);
6606 if (insn
& (1 << 20)) {
6609 if (insn
& (1 << 22)) {
6610 tmp
= gen_ld8u(tmp2
, i
);
6612 tmp
= gen_ld32(tmp2
, i
);
6616 tmp
= load_reg(s
, rd
);
6617 if (insn
& (1 << 22))
6618 gen_st8(tmp
, tmp2
, i
);
6620 gen_st32(tmp
, tmp2
, i
);
6622 if (!(insn
& (1 << 24))) {
6623 gen_add_data_offset(s
, insn
, tmp2
);
6624 store_reg(s
, rn
, tmp2
);
6625 } else if (insn
& (1 << 21)) {
6626 store_reg(s
, rn
, tmp2
);
6630 if (insn
& (1 << 20)) {
6631 /* Complete the load. */
6635 store_reg(s
, rd
, tmp
);
6641 int j
, n
, user
, loaded_base
;
6643 /* load/store multiple words */
6644 /* XXX: store correct base if write back */
6646 if (insn
& (1 << 22)) {
6648 goto illegal_op
; /* only usable in supervisor mode */
6650 if ((insn
& (1 << 15)) == 0)
6653 rn
= (insn
>> 16) & 0xf;
6654 addr
= load_reg(s
, rn
);
6656 /* compute total size */
6660 if (insn
& (1 << i
))
6663 /* XXX: test invalid n == 0 case ? */
6664 if (insn
& (1 << 23)) {
6665 if (insn
& (1 << 24)) {
6667 tcg_gen_addi_i32(addr
, addr
, 4);
6669 /* post increment */
6672 if (insn
& (1 << 24)) {
6674 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6676 /* post decrement */
6678 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6683 if (insn
& (1 << i
)) {
6684 if (insn
& (1 << 20)) {
6686 tmp
= gen_ld32(addr
, IS_USER(s
));
6690 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6692 } else if (i
== rn
) {
6696 store_reg(s
, i
, tmp
);
6701 /* special case: r15 = PC + 8 */
6702 val
= (long)s
->pc
+ 4;
6704 tcg_gen_movi_i32(tmp
, val
);
6707 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6709 tmp
= load_reg(s
, i
);
6711 gen_st32(tmp
, addr
, IS_USER(s
));
6714 /* no need to add after the last transfer */
6716 tcg_gen_addi_i32(addr
, addr
, 4);
6719 if (insn
& (1 << 21)) {
6721 if (insn
& (1 << 23)) {
6722 if (insn
& (1 << 24)) {
6725 /* post increment */
6726 tcg_gen_addi_i32(addr
, addr
, 4);
6729 if (insn
& (1 << 24)) {
6732 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6734 /* post decrement */
6735 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6738 store_reg(s
, rn
, addr
);
6743 store_reg(s
, rn
, loaded_var
);
6745 if ((insn
& (1 << 22)) && !user
) {
6746 /* Restore CPSR from SPSR. */
6747 tmp
= load_cpu_field(spsr
);
6748 gen_set_cpsr(tmp
, 0xffffffff);
6750 s
->is_jmp
= DISAS_UPDATE
;
6759 /* branch (and link) */
6760 val
= (int32_t)s
->pc
;
6761 if (insn
& (1 << 24)) {
6763 tcg_gen_movi_i32(tmp
, val
);
6764 store_reg(s
, 14, tmp
);
6766 offset
= (((int32_t)insn
<< 8) >> 8);
6767 val
+= (offset
<< 2) + 4;
6775 if (disas_coproc_insn(env
, s
, insn
))
6780 gen_set_pc_im(s
->pc
);
6781 s
->is_jmp
= DISAS_SWI
;
6785 gen_set_condexec(s
);
6786 gen_set_pc_im(s
->pc
- 4);
6787 gen_exception(EXCP_UDEF
);
6788 s
->is_jmp
= DISAS_JUMP
;
6794 /* Return true if this is a Thumb-2 logical op. */
6796 thumb2_logic_op(int op
)
6801 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6802 then set condition code flags based on the result of the operation.
6803 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6804 to the high bit of T1.
6805 Returns zero if the opcode is valid. */
6808 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6815 gen_op_andl_T0_T1();
6819 gen_op_bicl_T0_T1();
6832 gen_op_xorl_T0_T1();
6837 gen_op_addl_T0_T1_cc();
6839 gen_op_addl_T0_T1();
6843 gen_op_adcl_T0_T1_cc();
6849 gen_op_sbcl_T0_T1_cc();
6855 gen_op_subl_T0_T1_cc();
6857 gen_op_subl_T0_T1();
6861 gen_op_rsbl_T0_T1_cc();
6863 gen_op_rsbl_T0_T1();
6865 default: /* 5, 6, 7, 9, 12, 15. */
6869 gen_op_logic_T0_cc();
6871 gen_set_CF_bit31(cpu_T
[1]);
6876 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6878 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6880 uint32_t insn
, imm
, shift
, offset
;
6881 uint32_t rd
, rn
, rm
, rs
;
6891 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
6892 || arm_feature (env
, ARM_FEATURE_M
))) {
6893 /* Thumb-1 cores may need to tread bl and blx as a pair of
6894 16-bit instructions to get correct prefetch abort behavior. */
6896 if ((insn
& (1 << 12)) == 0) {
6897 /* Second half of blx. */
6898 offset
= ((insn
& 0x7ff) << 1);
6899 tmp
= load_reg(s
, 14);
6900 tcg_gen_addi_i32(tmp
, tmp
, offset
);
6901 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
6904 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6905 store_reg(s
, 14, tmp2
);
6909 if (insn
& (1 << 11)) {
6910 /* Second half of bl. */
6911 offset
= ((insn
& 0x7ff) << 1) | 1;
6912 tmp
= load_reg(s
, 14);
6913 tcg_gen_addi_i32(tmp
, tmp
, 14);
6916 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6917 store_reg(s
, 14, tmp2
);
6921 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
6922 /* Instruction spans a page boundary. Implement it as two
6923 16-bit instructions in case the second half causes an
6925 offset
= ((int32_t)insn
<< 21) >> 9;
6926 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
6927 gen_movl_reg_T0(s
, 14);
6930 /* Fall through to 32-bit decode. */
6933 insn
= lduw_code(s
->pc
);
6935 insn
|= (uint32_t)insn_hw1
<< 16;
6937 if ((insn
& 0xf800e800) != 0xf000e800) {
6941 rn
= (insn
>> 16) & 0xf;
6942 rs
= (insn
>> 12) & 0xf;
6943 rd
= (insn
>> 8) & 0xf;
6945 switch ((insn
>> 25) & 0xf) {
6946 case 0: case 1: case 2: case 3:
6947 /* 16-bit instructions. Should never happen. */
6950 if (insn
& (1 << 22)) {
6951 /* Other load/store, table branch. */
6952 if (insn
& 0x01200000) {
6953 /* Load/store doubleword. */
6956 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
6958 addr
= load_reg(s
, rn
);
6960 offset
= (insn
& 0xff) * 4;
6961 if ((insn
& (1 << 23)) == 0)
6963 if (insn
& (1 << 24)) {
6964 tcg_gen_addi_i32(addr
, addr
, offset
);
6967 if (insn
& (1 << 20)) {
6969 tmp
= gen_ld32(addr
, IS_USER(s
));
6970 store_reg(s
, rs
, tmp
);
6971 tcg_gen_addi_i32(addr
, addr
, 4);
6972 tmp
= gen_ld32(addr
, IS_USER(s
));
6973 store_reg(s
, rd
, tmp
);
6976 tmp
= load_reg(s
, rs
);
6977 gen_st32(tmp
, addr
, IS_USER(s
));
6978 tcg_gen_addi_i32(addr
, addr
, 4);
6979 tmp
= load_reg(s
, rd
);
6980 gen_st32(tmp
, addr
, IS_USER(s
));
6982 if (insn
& (1 << 21)) {
6983 /* Base writeback. */
6986 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
6987 store_reg(s
, rn
, addr
);
6991 } else if ((insn
& (1 << 23)) == 0) {
6992 /* Load/store exclusive word. */
6993 gen_movl_T1_reg(s
, rn
);
6994 if (insn
& (1 << 20)) {
6995 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6996 tmp
= gen_ld32(addr
, IS_USER(s
));
6997 store_reg(s
, rd
, tmp
);
6999 int label
= gen_new_label();
7000 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7001 tcg_gen_brcond_i32(TCG_COND_NE
, cpu_T
[0],
7002 tcg_const_i32(0), label
);
7003 tmp
= load_reg(s
, rs
);
7004 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7005 gen_set_label(label
);
7006 gen_movl_reg_T0(s
, rd
);
7008 } else if ((insn
& (1 << 6)) == 0) {
7012 tcg_gen_movi_i32(addr
, s
->pc
);
7014 addr
= load_reg(s
, rn
);
7016 tmp
= load_reg(s
, rm
);
7017 tcg_gen_add_i32(addr
, addr
, tmp
);
7018 if (insn
& (1 << 4)) {
7020 tcg_gen_add_i32(addr
, addr
, tmp
);
7022 tmp
= gen_ld16u(addr
, IS_USER(s
));
7025 tmp
= gen_ld8u(addr
, IS_USER(s
));
7028 tcg_gen_shli_i32(tmp
, tmp
, 1);
7029 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7030 store_reg(s
, 15, tmp
);
7032 /* Load/store exclusive byte/halfword/doubleword. */
7033 /* ??? These are not really atomic. However we know
7034 we never have multiple CPUs running in parallel,
7035 so it is good enough. */
7036 op
= (insn
>> 4) & 0x3;
7037 /* Must use a global reg for the address because we have
7038 a conditional branch in the store instruction. */
7039 gen_movl_T1_reg(s
, rn
);
7041 if (insn
& (1 << 20)) {
7042 gen_helper_mark_exclusive(cpu_env
, addr
);
7045 tmp
= gen_ld8u(addr
, IS_USER(s
));
7048 tmp
= gen_ld16u(addr
, IS_USER(s
));
7051 tmp
= gen_ld32(addr
, IS_USER(s
));
7052 tcg_gen_addi_i32(addr
, addr
, 4);
7053 tmp2
= gen_ld32(addr
, IS_USER(s
));
7054 store_reg(s
, rd
, tmp2
);
7059 store_reg(s
, rs
, tmp
);
7061 int label
= gen_new_label();
7062 /* Must use a global that is not killed by the branch. */
7063 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7064 tcg_gen_brcond_i32(TCG_COND_NE
, cpu_T
[0], tcg_const_i32(0),
7066 tmp
= load_reg(s
, rs
);
7069 gen_st8(tmp
, addr
, IS_USER(s
));
7072 gen_st16(tmp
, addr
, IS_USER(s
));
7075 gen_st32(tmp
, addr
, IS_USER(s
));
7076 tcg_gen_addi_i32(addr
, addr
, 4);
7077 tmp
= load_reg(s
, rd
);
7078 gen_st32(tmp
, addr
, IS_USER(s
));
7083 gen_set_label(label
);
7084 gen_movl_reg_T0(s
, rm
);
7088 /* Load/store multiple, RFE, SRS. */
7089 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7090 /* Not available in user mode. */
7093 if (insn
& (1 << 20)) {
7095 addr
= load_reg(s
, rn
);
7096 if ((insn
& (1 << 24)) == 0)
7097 tcg_gen_addi_i32(addr
, addr
, -8);
7098 /* Load PC into tmp and CPSR into tmp2. */
7099 tmp
= gen_ld32(addr
, 0);
7100 tcg_gen_addi_i32(addr
, addr
, 4);
7101 tmp2
= gen_ld32(addr
, 0);
7102 if (insn
& (1 << 21)) {
7103 /* Base writeback. */
7104 if (insn
& (1 << 24)) {
7105 tcg_gen_addi_i32(addr
, addr
, 4);
7107 tcg_gen_addi_i32(addr
, addr
, -4);
7109 store_reg(s
, rn
, addr
);
7113 gen_rfe(s
, tmp
, tmp2
);
7117 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7118 addr
= load_reg(s
, 13);
7121 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7123 if ((insn
& (1 << 24)) == 0) {
7124 tcg_gen_addi_i32(addr
, addr
, -8);
7126 tmp
= load_reg(s
, 14);
7127 gen_st32(tmp
, addr
, 0);
7128 tcg_gen_addi_i32(addr
, addr
, 4);
7130 gen_helper_cpsr_read(tmp
);
7131 gen_st32(tmp
, addr
, 0);
7132 if (insn
& (1 << 21)) {
7133 if ((insn
& (1 << 24)) == 0) {
7134 tcg_gen_addi_i32(addr
, addr
, -4);
7136 tcg_gen_addi_i32(addr
, addr
, 4);
7138 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7139 store_reg(s
, 13, addr
);
7141 gen_helper_set_r13_banked(cpu_env
,
7142 tcg_const_i32(op
), addr
);
7150 /* Load/store multiple. */
7151 addr
= load_reg(s
, rn
);
7153 for (i
= 0; i
< 16; i
++) {
7154 if (insn
& (1 << i
))
7157 if (insn
& (1 << 24)) {
7158 tcg_gen_addi_i32(addr
, addr
, -offset
);
7161 for (i
= 0; i
< 16; i
++) {
7162 if ((insn
& (1 << i
)) == 0)
7164 if (insn
& (1 << 20)) {
7166 tmp
= gen_ld32(addr
, IS_USER(s
));
7170 store_reg(s
, i
, tmp
);
7174 tmp
= load_reg(s
, i
);
7175 gen_st32(tmp
, addr
, IS_USER(s
));
7177 tcg_gen_addi_i32(addr
, addr
, 4);
7179 if (insn
& (1 << 21)) {
7180 /* Base register writeback. */
7181 if (insn
& (1 << 24)) {
7182 tcg_gen_addi_i32(addr
, addr
, -offset
);
7184 /* Fault if writeback register is in register list. */
7185 if (insn
& (1 << rn
))
7187 store_reg(s
, rn
, addr
);
7194 case 5: /* Data processing register constant shift. */
7196 gen_op_movl_T0_im(0);
7198 gen_movl_T0_reg(s
, rn
);
7199 gen_movl_T1_reg(s
, rm
);
7200 op
= (insn
>> 21) & 0xf;
7201 shiftop
= (insn
>> 4) & 3;
7202 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7203 conds
= (insn
& (1 << 20)) != 0;
7204 logic_cc
= (conds
&& thumb2_logic_op(op
));
7205 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7206 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7209 gen_movl_reg_T0(s
, rd
);
7211 case 13: /* Misc data processing. */
7212 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7213 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7216 case 0: /* Register controlled shift. */
7217 tmp
= load_reg(s
, rn
);
7218 tmp2
= load_reg(s
, rm
);
7219 if ((insn
& 0x70) != 0)
7221 op
= (insn
>> 21) & 3;
7222 logic_cc
= (insn
& (1 << 20)) != 0;
7223 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7226 store_reg(s
, rd
, tmp
);
7228 case 1: /* Sign/zero extend. */
7229 tmp
= load_reg(s
, rm
);
7230 shift
= (insn
>> 4) & 3;
7231 /* ??? In many cases it's not neccessary to do a
7232 rotate, a shift is sufficient. */
7234 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7235 op
= (insn
>> 20) & 7;
7237 case 0: gen_sxth(tmp
); break;
7238 case 1: gen_uxth(tmp
); break;
7239 case 2: gen_sxtb16(tmp
); break;
7240 case 3: gen_uxtb16(tmp
); break;
7241 case 4: gen_sxtb(tmp
); break;
7242 case 5: gen_uxtb(tmp
); break;
7243 default: goto illegal_op
;
7246 tmp2
= load_reg(s
, rn
);
7247 if ((op
>> 1) == 1) {
7248 gen_add16(tmp
, tmp2
);
7250 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7254 store_reg(s
, rd
, tmp
);
7256 case 2: /* SIMD add/subtract. */
7257 op
= (insn
>> 20) & 7;
7258 shift
= (insn
>> 4) & 7;
7259 if ((op
& 3) == 3 || (shift
& 3) == 3)
7261 tmp
= load_reg(s
, rn
);
7262 tmp2
= load_reg(s
, rm
);
7263 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7265 store_reg(s
, rd
, tmp
);
7267 case 3: /* Other data processing. */
7268 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7270 /* Saturating add/subtract. */
7271 tmp
= load_reg(s
, rn
);
7272 tmp2
= load_reg(s
, rm
);
7274 gen_helper_double_saturate(tmp
, tmp
);
7276 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7278 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7281 tmp
= load_reg(s
, rn
);
7283 case 0x0a: /* rbit */
7284 gen_helper_rbit(tmp
, tmp
);
7286 case 0x08: /* rev */
7287 tcg_gen_bswap_i32(tmp
, tmp
);
7289 case 0x09: /* rev16 */
7292 case 0x0b: /* revsh */
7295 case 0x10: /* sel */
7296 tmp2
= load_reg(s
, rm
);
7298 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7299 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7303 case 0x18: /* clz */
7304 gen_helper_clz(tmp
, tmp
);
7310 store_reg(s
, rd
, tmp
);
7312 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7313 op
= (insn
>> 4) & 0xf;
7314 tmp
= load_reg(s
, rn
);
7315 tmp2
= load_reg(s
, rm
);
7316 switch ((insn
>> 20) & 7) {
7317 case 0: /* 32 x 32 -> 32 */
7318 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7321 tmp2
= load_reg(s
, rs
);
7323 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7325 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7329 case 1: /* 16 x 16 -> 32 */
7330 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7333 tmp2
= load_reg(s
, rs
);
7334 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7338 case 2: /* Dual multiply add. */
7339 case 4: /* Dual multiply subtract. */
7341 gen_swap_half(tmp2
);
7342 gen_smul_dual(tmp
, tmp2
);
7343 /* This addition cannot overflow. */
7344 if (insn
& (1 << 22)) {
7345 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7347 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7352 tmp2
= load_reg(s
, rs
);
7353 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7357 case 3: /* 32 * 16 -> 32msb */
7359 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7362 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
7363 tcg_gen_shri_i64(tmp2
, tmp2
, 16);
7365 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
7368 tmp2
= load_reg(s
, rs
);
7369 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7373 case 5: case 6: /* 32 * 32 -> 32msb */
7374 gen_imull(tmp
, tmp2
);
7375 if (insn
& (1 << 5)) {
7376 gen_roundqd(tmp
, tmp2
);
7383 tmp2
= load_reg(s
, rs
);
7384 if (insn
& (1 << 21)) {
7385 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7387 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7392 case 7: /* Unsigned sum of absolute differences. */
7393 gen_helper_usad8(tmp
, tmp
, tmp2
);
7396 tmp2
= load_reg(s
, rs
);
7397 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7402 store_reg(s
, rd
, tmp
);
7404 case 6: case 7: /* 64-bit multiply, Divide. */
7405 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7406 tmp
= load_reg(s
, rn
);
7407 tmp2
= load_reg(s
, rm
);
7408 if ((op
& 0x50) == 0x10) {
7410 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7413 gen_helper_udiv(tmp
, tmp
, tmp2
);
7415 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7417 store_reg(s
, rd
, tmp
);
7418 } else if ((op
& 0xe) == 0xc) {
7419 /* Dual multiply accumulate long. */
7421 gen_swap_half(tmp2
);
7422 gen_smul_dual(tmp
, tmp2
);
7424 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7426 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7429 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
7430 gen_addq(s
, tmp
, rs
, rd
);
7431 gen_storeq_reg(s
, rs
, rd
, tmp
);
7434 /* Unsigned 64-bit multiply */
7435 tmp
= gen_mulu_i64_i32(tmp
, tmp2
);
7439 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7441 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
7442 tcg_gen_ext_i32_i64(tmp2
, tmp
);
7446 /* Signed 64-bit multiply */
7447 tmp
= gen_muls_i64_i32(tmp
, tmp2
);
7452 gen_addq_lo(s
, tmp
, rs
);
7453 gen_addq_lo(s
, tmp
, rd
);
7454 } else if (op
& 0x40) {
7455 /* 64-bit accumulate. */
7456 gen_addq(s
, tmp
, rs
, rd
);
7458 gen_storeq_reg(s
, rs
, rd
, tmp
);
7463 case 6: case 7: case 14: case 15:
7465 if (((insn
>> 24) & 3) == 3) {
7466 /* Translate into the equivalent ARM encoding. */
7467 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7468 if (disas_neon_data_insn(env
, s
, insn
))
7471 if (insn
& (1 << 28))
7473 if (disas_coproc_insn (env
, s
, insn
))
7477 case 8: case 9: case 10: case 11:
7478 if (insn
& (1 << 15)) {
7479 /* Branches, misc control. */
7480 if (insn
& 0x5000) {
7481 /* Unconditional branch. */
7482 /* signextend(hw1[10:0]) -> offset[:12]. */
7483 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7484 /* hw1[10:0] -> offset[11:1]. */
7485 offset
|= (insn
& 0x7ff) << 1;
7486 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7487 offset[24:22] already have the same value because of the
7488 sign extension above. */
7489 offset
^= ((~insn
) & (1 << 13)) << 10;
7490 offset
^= ((~insn
) & (1 << 11)) << 11;
7492 if (insn
& (1 << 14)) {
7493 /* Branch and link. */
7494 gen_op_movl_T1_im(s
->pc
| 1);
7495 gen_movl_reg_T1(s
, 14);
7499 if (insn
& (1 << 12)) {
7504 offset
&= ~(uint32_t)2;
7505 gen_bx_im(s
, offset
);
7507 } else if (((insn
>> 23) & 7) == 7) {
7509 if (insn
& (1 << 13))
7512 if (insn
& (1 << 26)) {
7513 /* Secure monitor call (v6Z) */
7514 goto illegal_op
; /* not implemented. */
7516 op
= (insn
>> 20) & 7;
7518 case 0: /* msr cpsr. */
7520 tmp
= load_reg(s
, rn
);
7521 addr
= tcg_const_i32(insn
& 0xff);
7522 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7527 case 1: /* msr spsr. */
7530 gen_movl_T0_reg(s
, rn
);
7531 if (gen_set_psr_T0(s
,
7532 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7536 case 2: /* cps, nop-hint. */
7537 if (((insn
>> 8) & 7) == 0) {
7538 gen_nop_hint(s
, insn
& 0xff);
7540 /* Implemented as NOP in user mode. */
7545 if (insn
& (1 << 10)) {
7546 if (insn
& (1 << 7))
7548 if (insn
& (1 << 6))
7550 if (insn
& (1 << 5))
7552 if (insn
& (1 << 9))
7553 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7555 if (insn
& (1 << 8)) {
7557 imm
|= (insn
& 0x1f);
7560 gen_op_movl_T0_im(imm
);
7561 gen_set_psr_T0(s
, offset
, 0);
7564 case 3: /* Special control operations. */
7565 op
= (insn
>> 4) & 0xf;
7568 gen_helper_clrex(cpu_env
);
7573 /* These execute as NOPs. */
7581 /* Trivial implementation equivalent to bx. */
7582 tmp
= load_reg(s
, rn
);
7585 case 5: /* Exception return. */
7586 /* Unpredictable in user mode. */
7588 case 6: /* mrs cpsr. */
7591 addr
= tcg_const_i32(insn
& 0xff);
7592 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7594 gen_helper_cpsr_read(tmp
);
7596 store_reg(s
, rd
, tmp
);
7598 case 7: /* mrs spsr. */
7599 /* Not accessible in user mode. */
7600 if (IS_USER(s
) || IS_M(env
))
7602 tmp
= load_cpu_field(spsr
);
7603 store_reg(s
, rd
, tmp
);
7608 /* Conditional branch. */
7609 op
= (insn
>> 22) & 0xf;
7610 /* Generate a conditional jump to next instruction. */
7611 s
->condlabel
= gen_new_label();
7612 gen_test_cc(op
^ 1, s
->condlabel
);
7615 /* offset[11:1] = insn[10:0] */
7616 offset
= (insn
& 0x7ff) << 1;
7617 /* offset[17:12] = insn[21:16]. */
7618 offset
|= (insn
& 0x003f0000) >> 4;
7619 /* offset[31:20] = insn[26]. */
7620 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7621 /* offset[18] = insn[13]. */
7622 offset
|= (insn
& (1 << 13)) << 5;
7623 /* offset[19] = insn[11]. */
7624 offset
|= (insn
& (1 << 11)) << 8;
7626 /* jump to the offset */
7627 gen_jmp(s
, s
->pc
+ offset
);
7630 /* Data processing immediate. */
7631 if (insn
& (1 << 25)) {
7632 if (insn
& (1 << 24)) {
7633 if (insn
& (1 << 20))
7635 /* Bitfield/Saturate. */
7636 op
= (insn
>> 21) & 7;
7638 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7641 tcg_gen_movi_i32(tmp
, 0);
7643 tmp
= load_reg(s
, rn
);
7646 case 2: /* Signed bitfield extract. */
7648 if (shift
+ imm
> 32)
7651 gen_sbfx(tmp
, shift
, imm
);
7653 case 6: /* Unsigned bitfield extract. */
7655 if (shift
+ imm
> 32)
7658 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7660 case 3: /* Bitfield insert/clear. */
7663 imm
= imm
+ 1 - shift
;
7665 tmp2
= load_reg(s
, rd
);
7666 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7672 default: /* Saturate. */
7675 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7677 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7679 tmp2
= tcg_const_i32(imm
);
7682 if ((op
& 1) && shift
== 0)
7683 gen_helper_usat16(tmp
, tmp
, tmp2
);
7685 gen_helper_usat(tmp
, tmp
, tmp2
);
7688 if ((op
& 1) && shift
== 0)
7689 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7691 gen_helper_ssat(tmp
, tmp
, tmp2
);
7695 store_reg(s
, rd
, tmp
);
7697 imm
= ((insn
& 0x04000000) >> 15)
7698 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7699 if (insn
& (1 << 22)) {
7700 /* 16-bit immediate. */
7701 imm
|= (insn
>> 4) & 0xf000;
7702 if (insn
& (1 << 23)) {
7704 tmp
= load_reg(s
, rd
);
7705 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
7706 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7710 tcg_gen_movi_i32(tmp
, imm
);
7713 /* Add/sub 12-bit immediate. */
7715 offset
= s
->pc
& ~(uint32_t)3;
7716 if (insn
& (1 << 23))
7721 tcg_gen_movi_i32(tmp
, offset
);
7723 tmp
= load_reg(s
, rn
);
7724 if (insn
& (1 << 23))
7725 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7727 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7730 store_reg(s
, rd
, tmp
);
7733 int shifter_out
= 0;
7734 /* modified 12-bit immediate. */
7735 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7736 imm
= (insn
& 0xff);
7739 /* Nothing to do. */
7741 case 1: /* 00XY00XY */
7744 case 2: /* XY00XY00 */
7748 case 3: /* XYXYXYXY */
7752 default: /* Rotated constant. */
7753 shift
= (shift
<< 1) | (imm
>> 7);
7755 imm
= imm
<< (32 - shift
);
7759 gen_op_movl_T1_im(imm
);
7760 rn
= (insn
>> 16) & 0xf;
7762 gen_op_movl_T0_im(0);
7764 gen_movl_T0_reg(s
, rn
);
7765 op
= (insn
>> 21) & 0xf;
7766 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7769 rd
= (insn
>> 8) & 0xf;
7771 gen_movl_reg_T0(s
, rd
);
7776 case 12: /* Load/store single data item. */
7781 if ((insn
& 0x01100000) == 0x01000000) {
7782 if (disas_neon_ls_insn(env
, s
, insn
))
7790 /* s->pc has already been incremented by 4. */
7791 imm
= s
->pc
& 0xfffffffc;
7792 if (insn
& (1 << 23))
7793 imm
+= insn
& 0xfff;
7795 imm
-= insn
& 0xfff;
7796 tcg_gen_movi_i32(addr
, imm
);
7798 addr
= load_reg(s
, rn
);
7799 if (insn
& (1 << 23)) {
7800 /* Positive offset. */
7802 tcg_gen_addi_i32(addr
, addr
, imm
);
7804 op
= (insn
>> 8) & 7;
7807 case 0: case 8: /* Shifted Register. */
7808 shift
= (insn
>> 4) & 0xf;
7811 tmp
= load_reg(s
, rm
);
7813 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7814 tcg_gen_add_i32(addr
, addr
, tmp
);
7817 case 4: /* Negative offset. */
7818 tcg_gen_addi_i32(addr
, addr
, -imm
);
7820 case 6: /* User privilege. */
7821 tcg_gen_addi_i32(addr
, addr
, imm
);
7824 case 1: /* Post-decrement. */
7827 case 3: /* Post-increment. */
7831 case 5: /* Pre-decrement. */
7834 case 7: /* Pre-increment. */
7835 tcg_gen_addi_i32(addr
, addr
, imm
);
7843 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7844 if (insn
& (1 << 20)) {
7846 if (rs
== 15 && op
!= 2) {
7849 /* Memory hint. Implemented as NOP. */
7852 case 0: tmp
= gen_ld8u(addr
, user
); break;
7853 case 4: tmp
= gen_ld8s(addr
, user
); break;
7854 case 1: tmp
= gen_ld16u(addr
, user
); break;
7855 case 5: tmp
= gen_ld16s(addr
, user
); break;
7856 case 2: tmp
= gen_ld32(addr
, user
); break;
7857 default: goto illegal_op
;
7862 store_reg(s
, rs
, tmp
);
7869 tmp
= load_reg(s
, rs
);
7871 case 0: gen_st8(tmp
, addr
, user
); break;
7872 case 1: gen_st16(tmp
, addr
, user
); break;
7873 case 2: gen_st32(tmp
, addr
, user
); break;
7874 default: goto illegal_op
;
7878 tcg_gen_addi_i32(addr
, addr
, imm
);
7880 store_reg(s
, rn
, addr
);
7894 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
7896 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
7903 if (s
->condexec_mask
) {
7904 cond
= s
->condexec_cond
;
7905 s
->condlabel
= gen_new_label();
7906 gen_test_cc(cond
^ 1, s
->condlabel
);
7910 insn
= lduw_code(s
->pc
);
7913 switch (insn
>> 12) {
7916 op
= (insn
>> 11) & 3;
7919 rn
= (insn
>> 3) & 7;
7920 gen_movl_T0_reg(s
, rn
);
7921 if (insn
& (1 << 10)) {
7923 gen_op_movl_T1_im((insn
>> 6) & 7);
7926 rm
= (insn
>> 6) & 7;
7927 gen_movl_T1_reg(s
, rm
);
7929 if (insn
& (1 << 9)) {
7930 if (s
->condexec_mask
)
7931 gen_op_subl_T0_T1();
7933 gen_op_subl_T0_T1_cc();
7935 if (s
->condexec_mask
)
7936 gen_op_addl_T0_T1();
7938 gen_op_addl_T0_T1_cc();
7940 gen_movl_reg_T0(s
, rd
);
7942 /* shift immediate */
7943 rm
= (insn
>> 3) & 7;
7944 shift
= (insn
>> 6) & 0x1f;
7945 tmp
= load_reg(s
, rm
);
7946 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
7947 if (!s
->condexec_mask
)
7949 store_reg(s
, rd
, tmp
);
7953 /* arithmetic large immediate */
7954 op
= (insn
>> 11) & 3;
7955 rd
= (insn
>> 8) & 0x7;
7957 gen_op_movl_T0_im(insn
& 0xff);
7959 gen_movl_T0_reg(s
, rd
);
7960 gen_op_movl_T1_im(insn
& 0xff);
7964 if (!s
->condexec_mask
)
7965 gen_op_logic_T0_cc();
7968 gen_op_subl_T0_T1_cc();
7971 if (s
->condexec_mask
)
7972 gen_op_addl_T0_T1();
7974 gen_op_addl_T0_T1_cc();
7977 if (s
->condexec_mask
)
7978 gen_op_subl_T0_T1();
7980 gen_op_subl_T0_T1_cc();
7984 gen_movl_reg_T0(s
, rd
);
7987 if (insn
& (1 << 11)) {
7988 rd
= (insn
>> 8) & 7;
7989 /* load pc-relative. Bit 1 of PC is ignored. */
7990 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
7991 val
&= ~(uint32_t)2;
7993 tcg_gen_movi_i32(addr
, val
);
7994 tmp
= gen_ld32(addr
, IS_USER(s
));
7996 store_reg(s
, rd
, tmp
);
7999 if (insn
& (1 << 10)) {
8000 /* data processing extended or blx */
8001 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8002 rm
= (insn
>> 3) & 0xf;
8003 op
= (insn
>> 8) & 3;
8006 gen_movl_T0_reg(s
, rd
);
8007 gen_movl_T1_reg(s
, rm
);
8008 gen_op_addl_T0_T1();
8009 gen_movl_reg_T0(s
, rd
);
8012 gen_movl_T0_reg(s
, rd
);
8013 gen_movl_T1_reg(s
, rm
);
8014 gen_op_subl_T0_T1_cc();
8016 case 2: /* mov/cpy */
8017 gen_movl_T0_reg(s
, rm
);
8018 gen_movl_reg_T0(s
, rd
);
8020 case 3:/* branch [and link] exchange thumb register */
8021 tmp
= load_reg(s
, rm
);
8022 if (insn
& (1 << 7)) {
8023 val
= (uint32_t)s
->pc
| 1;
8025 tcg_gen_movi_i32(tmp2
, val
);
8026 store_reg(s
, 14, tmp2
);
8034 /* data processing register */
8036 rm
= (insn
>> 3) & 7;
8037 op
= (insn
>> 6) & 0xf;
8038 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8039 /* the shift/rotate ops want the operands backwards */
8048 if (op
== 9) /* neg */
8049 gen_op_movl_T0_im(0);
8050 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8051 gen_movl_T0_reg(s
, rd
);
8053 gen_movl_T1_reg(s
, rm
);
8056 gen_op_andl_T0_T1();
8057 if (!s
->condexec_mask
)
8058 gen_op_logic_T0_cc();
8061 gen_op_xorl_T0_T1();
8062 if (!s
->condexec_mask
)
8063 gen_op_logic_T0_cc();
8066 if (s
->condexec_mask
) {
8067 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8069 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8070 gen_op_logic_T1_cc();
8074 if (s
->condexec_mask
) {
8075 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8077 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8078 gen_op_logic_T1_cc();
8082 if (s
->condexec_mask
) {
8083 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8085 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8086 gen_op_logic_T1_cc();
8090 if (s
->condexec_mask
)
8093 gen_op_adcl_T0_T1_cc();
8096 if (s
->condexec_mask
)
8099 gen_op_sbcl_T0_T1_cc();
8102 if (s
->condexec_mask
) {
8103 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8105 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8106 gen_op_logic_T1_cc();
8110 gen_op_andl_T0_T1();
8111 gen_op_logic_T0_cc();
8115 if (s
->condexec_mask
)
8116 gen_op_subl_T0_T1();
8118 gen_op_subl_T0_T1_cc();
8121 gen_op_subl_T0_T1_cc();
8125 gen_op_addl_T0_T1_cc();
8130 if (!s
->condexec_mask
)
8131 gen_op_logic_T0_cc();
8134 gen_op_mull_T0_T1();
8135 if (!s
->condexec_mask
)
8136 gen_op_logic_T0_cc();
8139 gen_op_bicl_T0_T1();
8140 if (!s
->condexec_mask
)
8141 gen_op_logic_T0_cc();
8145 if (!s
->condexec_mask
)
8146 gen_op_logic_T1_cc();
8153 gen_movl_reg_T1(s
, rm
);
8155 gen_movl_reg_T0(s
, rd
);
8160 /* load/store register offset. */
8162 rn
= (insn
>> 3) & 7;
8163 rm
= (insn
>> 6) & 7;
8164 op
= (insn
>> 9) & 7;
8165 addr
= load_reg(s
, rn
);
8166 tmp
= load_reg(s
, rm
);
8167 tcg_gen_add_i32(addr
, addr
, tmp
);
8170 if (op
< 3) /* store */
8171 tmp
= load_reg(s
, rd
);
8175 gen_st32(tmp
, addr
, IS_USER(s
));
8178 gen_st16(tmp
, addr
, IS_USER(s
));
8181 gen_st8(tmp
, addr
, IS_USER(s
));
8184 tmp
= gen_ld8s(addr
, IS_USER(s
));
8187 tmp
= gen_ld32(addr
, IS_USER(s
));
8190 tmp
= gen_ld16u(addr
, IS_USER(s
));
8193 tmp
= gen_ld8u(addr
, IS_USER(s
));
8196 tmp
= gen_ld16s(addr
, IS_USER(s
));
8199 if (op
>= 3) /* load */
8200 store_reg(s
, rd
, tmp
);
8205 /* load/store word immediate offset */
8207 rn
= (insn
>> 3) & 7;
8208 addr
= load_reg(s
, rn
);
8209 val
= (insn
>> 4) & 0x7c;
8210 tcg_gen_addi_i32(addr
, addr
, val
);
8212 if (insn
& (1 << 11)) {
8214 tmp
= gen_ld32(addr
, IS_USER(s
));
8215 store_reg(s
, rd
, tmp
);
8218 tmp
= load_reg(s
, rd
);
8219 gen_st32(tmp
, addr
, IS_USER(s
));
8225 /* load/store byte immediate offset */
8227 rn
= (insn
>> 3) & 7;
8228 addr
= load_reg(s
, rn
);
8229 val
= (insn
>> 6) & 0x1f;
8230 tcg_gen_addi_i32(addr
, addr
, val
);
8232 if (insn
& (1 << 11)) {
8234 tmp
= gen_ld8u(addr
, IS_USER(s
));
8235 store_reg(s
, rd
, tmp
);
8238 tmp
= load_reg(s
, rd
);
8239 gen_st8(tmp
, addr
, IS_USER(s
));
8245 /* load/store halfword immediate offset */
8247 rn
= (insn
>> 3) & 7;
8248 addr
= load_reg(s
, rn
);
8249 val
= (insn
>> 5) & 0x3e;
8250 tcg_gen_addi_i32(addr
, addr
, val
);
8252 if (insn
& (1 << 11)) {
8254 tmp
= gen_ld16u(addr
, IS_USER(s
));
8255 store_reg(s
, rd
, tmp
);
8258 tmp
= load_reg(s
, rd
);
8259 gen_st16(tmp
, addr
, IS_USER(s
));
8265 /* load/store from stack */
8266 rd
= (insn
>> 8) & 7;
8267 addr
= load_reg(s
, 13);
8268 val
= (insn
& 0xff) * 4;
8269 tcg_gen_addi_i32(addr
, addr
, val
);
8271 if (insn
& (1 << 11)) {
8273 tmp
= gen_ld32(addr
, IS_USER(s
));
8274 store_reg(s
, rd
, tmp
);
8277 tmp
= load_reg(s
, rd
);
8278 gen_st32(tmp
, addr
, IS_USER(s
));
8284 /* add to high reg */
8285 rd
= (insn
>> 8) & 7;
8286 if (insn
& (1 << 11)) {
8288 tmp
= load_reg(s
, 13);
8290 /* PC. bit 1 is ignored. */
8292 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8294 val
= (insn
& 0xff) * 4;
8295 tcg_gen_addi_i32(tmp
, tmp
, val
);
8296 store_reg(s
, rd
, tmp
);
8301 op
= (insn
>> 8) & 0xf;
8304 /* adjust stack pointer */
8305 tmp
= load_reg(s
, 13);
8306 val
= (insn
& 0x7f) * 4;
8307 if (insn
& (1 << 7))
8308 val
= -(int32_t)val
;
8309 tcg_gen_addi_i32(tmp
, tmp
, val
);
8310 store_reg(s
, 13, tmp
);
8313 case 2: /* sign/zero extend. */
8316 rm
= (insn
>> 3) & 7;
8317 tmp
= load_reg(s
, rm
);
8318 switch ((insn
>> 6) & 3) {
8319 case 0: gen_sxth(tmp
); break;
8320 case 1: gen_sxtb(tmp
); break;
8321 case 2: gen_uxth(tmp
); break;
8322 case 3: gen_uxtb(tmp
); break;
8324 store_reg(s
, rd
, tmp
);
8326 case 4: case 5: case 0xc: case 0xd:
8328 addr
= load_reg(s
, 13);
8329 if (insn
& (1 << 8))
8333 for (i
= 0; i
< 8; i
++) {
8334 if (insn
& (1 << i
))
8337 if ((insn
& (1 << 11)) == 0) {
8338 tcg_gen_addi_i32(addr
, addr
, -offset
);
8340 for (i
= 0; i
< 8; i
++) {
8341 if (insn
& (1 << i
)) {
8342 if (insn
& (1 << 11)) {
8344 tmp
= gen_ld32(addr
, IS_USER(s
));
8345 store_reg(s
, i
, tmp
);
8348 tmp
= load_reg(s
, i
);
8349 gen_st32(tmp
, addr
, IS_USER(s
));
8351 /* advance to the next address. */
8352 tcg_gen_addi_i32(addr
, addr
, 4);
8355 if (insn
& (1 << 8)) {
8356 if (insn
& (1 << 11)) {
8358 tmp
= gen_ld32(addr
, IS_USER(s
));
8359 /* don't set the pc until the rest of the instruction
8363 tmp
= load_reg(s
, 14);
8364 gen_st32(tmp
, addr
, IS_USER(s
));
8366 tcg_gen_addi_i32(addr
, addr
, 4);
8368 if ((insn
& (1 << 11)) == 0) {
8369 tcg_gen_addi_i32(addr
, addr
, -offset
);
8371 /* write back the new stack pointer */
8372 store_reg(s
, 13, addr
);
8373 /* set the new PC value */
8374 if ((insn
& 0x0900) == 0x0900)
8378 case 1: case 3: case 9: case 11: /* czb */
8380 tmp
= load_reg(s
, rm
);
8381 tmp2
= tcg_const_i32(0);
8382 s
->condlabel
= gen_new_label();
8384 if (insn
& (1 << 11))
8385 tcg_gen_brcond_i32(TCG_COND_EQ
, tmp
, tmp2
, s
->condlabel
);
8387 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, tmp2
, s
->condlabel
);
8389 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8390 val
= (uint32_t)s
->pc
+ 2;
8395 case 15: /* IT, nop-hint. */
8396 if ((insn
& 0xf) == 0) {
8397 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8401 s
->condexec_cond
= (insn
>> 4) & 0xe;
8402 s
->condexec_mask
= insn
& 0x1f;
8403 /* No actual code generated for this insn, just setup state. */
8406 case 0xe: /* bkpt */
8407 gen_set_condexec(s
);
8408 gen_set_pc_im(s
->pc
- 2);
8409 gen_exception(EXCP_BKPT
);
8410 s
->is_jmp
= DISAS_JUMP
;
8415 rn
= (insn
>> 3) & 0x7;
8417 tmp
= load_reg(s
, rn
);
8418 switch ((insn
>> 6) & 3) {
8419 case 0: tcg_gen_bswap_i32(tmp
, tmp
); break;
8420 case 1: gen_rev16(tmp
); break;
8421 case 3: gen_revsh(tmp
); break;
8422 default: goto illegal_op
;
8424 store_reg(s
, rd
, tmp
);
8432 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8435 addr
= tcg_const_i32(16);
8436 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8440 addr
= tcg_const_i32(17);
8441 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8445 if (insn
& (1 << 4))
8446 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8450 val
= ((insn
& 7) << 6) & shift
;
8451 gen_op_movl_T0_im(val
);
8452 gen_set_psr_T0(s
, shift
, 0);
8462 /* load/store multiple */
8463 rn
= (insn
>> 8) & 0x7;
8464 addr
= load_reg(s
, rn
);
8465 for (i
= 0; i
< 8; i
++) {
8466 if (insn
& (1 << i
)) {
8467 if (insn
& (1 << 11)) {
8469 tmp
= gen_ld32(addr
, IS_USER(s
));
8470 store_reg(s
, i
, tmp
);
8473 tmp
= load_reg(s
, i
);
8474 gen_st32(tmp
, addr
, IS_USER(s
));
8476 /* advance to the next address */
8477 tcg_gen_addi_i32(addr
, addr
, 4);
8480 /* Base register writeback. */
8481 if ((insn
& (1 << rn
)) == 0) {
8482 store_reg(s
, rn
, addr
);
8489 /* conditional branch or swi */
8490 cond
= (insn
>> 8) & 0xf;
8496 gen_set_condexec(s
);
8497 gen_set_pc_im(s
->pc
| 1);
8498 s
->is_jmp
= DISAS_SWI
;
8501 /* generate a conditional jump to next instruction */
8502 s
->condlabel
= gen_new_label();
8503 gen_test_cc(cond
^ 1, s
->condlabel
);
8505 gen_movl_T1_reg(s
, 15);
8507 /* jump to the offset */
8508 val
= (uint32_t)s
->pc
+ 2;
8509 offset
= ((int32_t)insn
<< 24) >> 24;
8515 if (insn
& (1 << 11)) {
8516 if (disas_thumb2_insn(env
, s
, insn
))
8520 /* unconditional branch */
8521 val
= (uint32_t)s
->pc
;
8522 offset
= ((int32_t)insn
<< 21) >> 21;
8523 val
+= (offset
<< 1) + 2;
8528 if (disas_thumb2_insn(env
, s
, insn
))
8534 gen_set_condexec(s
);
8535 gen_set_pc_im(s
->pc
- 4);
8536 gen_exception(EXCP_UDEF
);
8537 s
->is_jmp
= DISAS_JUMP
;
8541 gen_set_condexec(s
);
8542 gen_set_pc_im(s
->pc
- 2);
8543 gen_exception(EXCP_UDEF
);
8544 s
->is_jmp
= DISAS_JUMP
;
8547 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8548 basic block 'tb'. If search_pc is TRUE, also generate PC
8549 information for each intermediate instruction. */
8550 static inline int gen_intermediate_code_internal(CPUState
*env
,
8551 TranslationBlock
*tb
,
8554 DisasContext dc1
, *dc
= &dc1
;
8555 uint16_t *gen_opc_end
;
8557 target_ulong pc_start
;
8558 uint32_t next_page_start
;
8560 /* generate intermediate code */
8562 memset(temps
, 0, sizeof(temps
));
8568 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8570 dc
->is_jmp
= DISAS_NEXT
;
8572 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8574 dc
->thumb
= env
->thumb
;
8575 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8576 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8578 #if !defined(CONFIG_USER_ONLY)
8580 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8582 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8585 cpu_F0s
= tcg_temp_new(TCG_TYPE_I32
);
8586 cpu_F1s
= tcg_temp_new(TCG_TYPE_I32
);
8587 cpu_F0d
= tcg_temp_new(TCG_TYPE_I64
);
8588 cpu_F1d
= tcg_temp_new(TCG_TYPE_I64
);
8591 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8592 cpu_M0
= tcg_temp_new(TCG_TYPE_I64
);
8593 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8595 /* Reset the conditional execution bits immediately. This avoids
8596 complications trying to do it at the end of the block. */
8597 if (env
->condexec_bits
)
8599 TCGv tmp
= new_tmp();
8600 tcg_gen_movi_i32(tmp
, 0);
8601 store_cpu_field(tmp
, condexec_bits
);
8604 #ifndef CONFIG_USER_ONLY
8605 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8606 /* We always get here via a jump, so know we are not in a
8607 conditional execution block. */
8608 gen_exception(EXCP_EXCEPTION_EXIT
);
8612 if (env
->nb_breakpoints
> 0) {
8613 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
8614 if (env
->breakpoints
[j
] == dc
->pc
) {
8615 gen_set_condexec(dc
);
8616 gen_set_pc_im(dc
->pc
);
8617 gen_exception(EXCP_DEBUG
);
8618 dc
->is_jmp
= DISAS_JUMP
;
8619 /* Advance PC so that clearing the breakpoint will
8620 invalidate this TB. */
8622 goto done_generating
;
8628 j
= gen_opc_ptr
- gen_opc_buf
;
8632 gen_opc_instr_start
[lj
++] = 0;
8634 gen_opc_pc
[lj
] = dc
->pc
;
8635 gen_opc_instr_start
[lj
] = 1;
8639 disas_thumb_insn(env
, dc
);
8640 if (dc
->condexec_mask
) {
8641 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8642 | ((dc
->condexec_mask
>> 4) & 1);
8643 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8644 if (dc
->condexec_mask
== 0) {
8645 dc
->condexec_cond
= 0;
8649 disas_arm_insn(env
, dc
);
8652 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8656 if (dc
->condjmp
&& !dc
->is_jmp
) {
8657 gen_set_label(dc
->condlabel
);
8660 /* Terminate the TB on memory ops if watchpoints are present. */
8661 /* FIXME: This should be replacd by the deterministic execution
8662 * IRQ raising bits. */
8663 if (dc
->is_mem
&& env
->nb_watchpoints
)
8666 /* Translation stops when a conditional branch is enoutered.
8667 * Otherwise the subsequent code could get translated several times.
8668 * Also stop translation when a page boundary is reached. This
8669 * ensures prefech aborts occur at the right place. */
8670 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8671 !env
->singlestep_enabled
&&
8672 dc
->pc
< next_page_start
);
8674 /* At this stage dc->condjmp will only be set when the skipped
8675 instruction was a conditional branch or trap, and the PC has
8676 already been written. */
8677 if (__builtin_expect(env
->singlestep_enabled
, 0)) {
8678 /* Make sure the pc is updated, and raise a debug exception. */
8680 gen_set_condexec(dc
);
8681 if (dc
->is_jmp
== DISAS_SWI
) {
8682 gen_exception(EXCP_SWI
);
8684 gen_exception(EXCP_DEBUG
);
8686 gen_set_label(dc
->condlabel
);
8688 if (dc
->condjmp
|| !dc
->is_jmp
) {
8689 gen_set_pc_im(dc
->pc
);
8692 gen_set_condexec(dc
);
8693 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8694 gen_exception(EXCP_SWI
);
8696 /* FIXME: Single stepping a WFI insn will not halt
8698 gen_exception(EXCP_DEBUG
);
8701 /* While branches must always occur at the end of an IT block,
8702 there are a few other things that can cause us to terminate
8703 the TB in the middel of an IT block:
8704 - Exception generating instructions (bkpt, swi, undefined).
8706 - Hardware watchpoints.
8707 Hardware breakpoints have already been handled and skip this code.
8709 gen_set_condexec(dc
);
8710 switch(dc
->is_jmp
) {
8712 gen_goto_tb(dc
, 1, dc
->pc
);
8717 /* indicate that the hash table must be used to find the next TB */
8721 /* nothing more to generate */
8727 gen_exception(EXCP_SWI
);
8731 gen_set_label(dc
->condlabel
);
8732 gen_set_condexec(dc
);
8733 gen_goto_tb(dc
, 1, dc
->pc
);
8738 *gen_opc_ptr
= INDEX_op_end
;
8741 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
8742 fprintf(logfile
, "----------------\n");
8743 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
8744 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8745 fprintf(logfile
, "\n");
8749 j
= gen_opc_ptr
- gen_opc_buf
;
8752 gen_opc_instr_start
[lj
++] = 0;
8754 tb
->size
= dc
->pc
- pc_start
;
8759 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8761 return gen_intermediate_code_internal(env
, tb
, 0);
8764 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8766 return gen_intermediate_code_internal(env
, tb
, 1);
8769 static const char *cpu_mode_names
[16] = {
8770 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8771 "???", "???", "???", "und", "???", "???", "???", "sys"
8774 void cpu_dump_state(CPUState
*env
, FILE *f
,
8775 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8784 /* ??? This assumes float64 and double have the same layout.
8785 Oh well, it's only debug dumps. */
8793 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8795 cpu_fprintf(f
, "\n");
8797 cpu_fprintf(f
, " ");
8799 psr
= cpsr_read(env
);
8800 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8802 psr
& (1 << 31) ? 'N' : '-',
8803 psr
& (1 << 30) ? 'Z' : '-',
8804 psr
& (1 << 29) ? 'C' : '-',
8805 psr
& (1 << 28) ? 'V' : '-',
8806 psr
& CPSR_T
? 'T' : 'A',
8807 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8810 for (i
= 0; i
< 16; i
++) {
8811 d
.d
= env
->vfp
.regs
[i
];
8815 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8816 i
* 2, (int)s0
.i
, s0
.s
,
8817 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8818 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8821 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);