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_ext8u_i32(var, var)
225 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
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 /* T0 &= ~T1. Clobbers T1. */
455 /* FIXME: Implement bic natively. */
456 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
458 TCGv tmp
= new_tmp();
459 tcg_gen_not_i32(tmp
, t1
);
460 tcg_gen_and_i32(dest
, t0
, tmp
);
463 static inline void gen_op_bicl_T0_T1(void)
469 /* FIXME: Implement this natively. */
470 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
472 /* FIXME: Implement this natively. */
473 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
481 tcg_gen_shri_i32(tmp
, t1
, i
);
482 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
483 tcg_gen_or_i32(t0
, t1
, tmp
);
487 static void shifter_out_im(TCGv var
, int shift
)
489 TCGv tmp
= new_tmp();
491 tcg_gen_andi_i32(tmp
, var
, 1);
493 tcg_gen_shri_i32(tmp
, var
, shift
);
495 tcg_gen_andi_i32(tmp
, tmp
, 1);
501 /* Shift by immediate. Includes special handling for shift == 0. */
502 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
508 shifter_out_im(var
, 32 - shift
);
509 tcg_gen_shli_i32(var
, var
, shift
);
515 tcg_gen_shri_i32(var
, var
, 31);
518 tcg_gen_movi_i32(var
, 0);
521 shifter_out_im(var
, shift
- 1);
522 tcg_gen_shri_i32(var
, var
, shift
);
529 shifter_out_im(var
, shift
- 1);
532 tcg_gen_sari_i32(var
, var
, shift
);
534 case 3: /* ROR/RRX */
537 shifter_out_im(var
, shift
- 1);
538 tcg_gen_rori_i32(var
, var
, shift
); break;
540 TCGv tmp
= load_cpu_field(CF
);
542 shifter_out_im(var
, 0);
543 tcg_gen_shri_i32(var
, var
, 1);
544 tcg_gen_shli_i32(tmp
, tmp
, 31);
545 tcg_gen_or_i32(var
, var
, tmp
);
551 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
552 TCGv shift
, int flags
)
556 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
557 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
558 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
559 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
563 case 0: gen_helper_shl(var
, var
, shift
); break;
564 case 1: gen_helper_shr(var
, var
, shift
); break;
565 case 2: gen_helper_sar(var
, var
, shift
); break;
566 case 3: gen_helper_ror(var
, var
, shift
); break;
572 #define PAS_OP(pfx) \
574 case 0: gen_pas_helper(glue(pfx,add16)); break; \
575 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
576 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
577 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
578 case 4: gen_pas_helper(glue(pfx,add8)); break; \
579 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
581 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
586 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
588 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
589 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
593 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
594 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
597 #undef gen_pas_helper
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
611 #undef gen_pas_helper
616 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
617 #define PAS_OP(pfx) \
619 case 0: gen_pas_helper(glue(pfx,add8)); break; \
620 case 1: gen_pas_helper(glue(pfx,add16)); break; \
621 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
622 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
623 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
624 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
626 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
631 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
633 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
634 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
638 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
639 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
642 #undef gen_pas_helper
643 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
656 #undef gen_pas_helper
661 static void gen_test_cc(int cc
, int label
)
669 tmp
= load_cpu_field(ZF
);
670 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
673 tmp
= load_cpu_field(ZF
);
674 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
677 tmp
= load_cpu_field(CF
);
678 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
681 tmp
= load_cpu_field(CF
);
682 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
685 tmp
= load_cpu_field(NF
);
686 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
689 tmp
= load_cpu_field(NF
);
690 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
693 tmp
= load_cpu_field(VF
);
694 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
697 tmp
= load_cpu_field(VF
);
698 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
700 case 8: /* hi: C && !Z */
701 inv
= gen_new_label();
702 tmp
= load_cpu_field(CF
);
703 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
705 tmp
= load_cpu_field(ZF
);
706 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
709 case 9: /* ls: !C || Z */
710 tmp
= load_cpu_field(CF
);
711 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
713 tmp
= load_cpu_field(ZF
);
714 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
716 case 10: /* ge: N == V -> N ^ V == 0 */
717 tmp
= load_cpu_field(VF
);
718 tmp2
= load_cpu_field(NF
);
719 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
721 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
723 case 11: /* lt: N != V -> N ^ V != 0 */
724 tmp
= load_cpu_field(VF
);
725 tmp2
= load_cpu_field(NF
);
726 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
728 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
730 case 12: /* gt: !Z && N == V */
731 inv
= gen_new_label();
732 tmp
= load_cpu_field(ZF
);
733 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
735 tmp
= load_cpu_field(VF
);
736 tmp2
= load_cpu_field(NF
);
737 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
739 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
742 case 13: /* le: Z || N != V */
743 tmp
= load_cpu_field(ZF
);
744 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
746 tmp
= load_cpu_field(VF
);
747 tmp2
= load_cpu_field(NF
);
748 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
750 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
753 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
759 const uint8_t table_logic_cc
[16] = {
778 /* Set PC and Thumb state from an immediate address. */
779 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
783 s
->is_jmp
= DISAS_UPDATE
;
785 if (s
->thumb
!= (addr
& 1)) {
786 tcg_gen_movi_i32(tmp
, addr
& 1);
787 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
789 tcg_gen_movi_i32(tmp
, addr
& ~1);
790 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[15]));
794 /* Set PC and Thumb state from var. var is marked as dead. */
795 static inline void gen_bx(DisasContext
*s
, TCGv var
)
799 s
->is_jmp
= DISAS_UPDATE
;
801 tcg_gen_andi_i32(tmp
, var
, 1);
802 store_cpu_field(tmp
, thumb
);
803 tcg_gen_andi_i32(var
, var
, ~1);
804 store_cpu_field(var
, regs
[15]);
807 /* TODO: This should be removed. Use gen_bx instead. */
808 static inline void gen_bx_T0(DisasContext
*s
)
810 TCGv tmp
= new_tmp();
811 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
815 #if defined(CONFIG_USER_ONLY)
816 #define gen_ldst(name, s) gen_op_##name##_raw()
818 #define gen_ldst(name, s) do { \
821 gen_op_##name##_user(); \
823 gen_op_##name##_kernel(); \
826 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
828 TCGv tmp
= new_tmp();
829 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
832 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
834 TCGv tmp
= new_tmp();
835 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
838 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
840 TCGv tmp
= new_tmp();
841 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
844 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
846 TCGv tmp
= new_tmp();
847 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
850 static inline TCGv
gen_ld32(TCGv addr
, int index
)
852 TCGv tmp
= new_tmp();
853 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
856 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
858 tcg_gen_qemu_st8(val
, addr
, index
);
861 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
863 tcg_gen_qemu_st16(val
, addr
, index
);
866 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
868 tcg_gen_qemu_st32(val
, addr
, index
);
872 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
874 load_reg_var(s
, cpu_T
[0], reg
);
877 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
879 load_reg_var(s
, cpu_T
[1], reg
);
882 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
884 load_reg_var(s
, cpu_T
[2], reg
);
887 static inline void gen_set_pc_im(uint32_t val
)
889 TCGv tmp
= new_tmp();
890 tcg_gen_movi_i32(tmp
, val
);
891 store_cpu_field(tmp
, regs
[15]);
894 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
899 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
903 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
906 s
->is_jmp
= DISAS_JUMP
;
910 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
912 gen_movl_reg_TN(s
, reg
, 0);
915 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
917 gen_movl_reg_TN(s
, reg
, 1);
920 /* Force a TB lookup after an instruction that changes the CPU state. */
921 static inline void gen_lookup_tb(DisasContext
*s
)
923 gen_op_movl_T0_im(s
->pc
);
924 gen_movl_reg_T0(s
, 15);
925 s
->is_jmp
= DISAS_UPDATE
;
928 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
931 int val
, rm
, shift
, shiftop
;
934 if (!(insn
& (1 << 25))) {
937 if (!(insn
& (1 << 23)))
940 tcg_gen_addi_i32(var
, var
, val
);
944 shift
= (insn
>> 7) & 0x1f;
945 shiftop
= (insn
>> 5) & 3;
946 offset
= load_reg(s
, rm
);
947 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
948 if (!(insn
& (1 << 23)))
949 tcg_gen_sub_i32(var
, var
, offset
);
951 tcg_gen_add_i32(var
, var
, offset
);
956 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
962 if (insn
& (1 << 22)) {
964 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
965 if (!(insn
& (1 << 23)))
969 tcg_gen_addi_i32(var
, var
, val
);
973 tcg_gen_addi_i32(var
, var
, extra
);
975 offset
= load_reg(s
, rm
);
976 if (!(insn
& (1 << 23)))
977 tcg_gen_sub_i32(var
, var
, offset
);
979 tcg_gen_add_i32(var
, var
, offset
);
984 #define VFP_OP2(name) \
985 static inline void gen_vfp_##name(int dp) \
988 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
990 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
993 #define VFP_OP1(name) \
994 static inline void gen_vfp_##name(int dp, int arg) \
997 gen_op_vfp_##name##d(arg); \
999 gen_op_vfp_##name##s(arg); \
1009 static inline void gen_vfp_abs(int dp
)
1012 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1014 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1017 static inline void gen_vfp_neg(int dp
)
1020 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1022 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1025 static inline void gen_vfp_sqrt(int dp
)
1028 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1030 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1033 static inline void gen_vfp_cmp(int dp
)
1036 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1038 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1041 static inline void gen_vfp_cmpe(int dp
)
1044 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1046 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1049 static inline void gen_vfp_F1_ld0(int dp
)
1052 tcg_gen_movi_i64(cpu_F1d
, 0);
1054 tcg_gen_movi_i32(cpu_F1s
, 0);
1057 static inline void gen_vfp_uito(int dp
)
1060 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1062 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1065 static inline void gen_vfp_sito(int dp
)
1068 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1070 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1073 static inline void gen_vfp_toui(int dp
)
1076 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1078 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1081 static inline void gen_vfp_touiz(int dp
)
1084 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1086 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1089 static inline void gen_vfp_tosi(int dp
)
1092 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1094 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1097 static inline void gen_vfp_tosiz(int dp
)
1100 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1102 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1105 #define VFP_GEN_FIX(name) \
1106 static inline void gen_vfp_##name(int dp, int shift) \
1109 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1111 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1123 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1126 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1128 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1131 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1134 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1136 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1140 vfp_reg_offset (int dp
, int reg
)
1143 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1145 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1146 + offsetof(CPU_DoubleU
, l
.upper
);
1148 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1149 + offsetof(CPU_DoubleU
, l
.lower
);
1153 /* Return the offset of a 32-bit piece of a NEON register.
1154 zero is the least significant end of the register. */
1156 neon_reg_offset (int reg
, int n
)
1160 return vfp_reg_offset(0, sreg
);
1163 /* FIXME: Remove these. */
1164 #define neon_T0 cpu_T[0]
1165 #define neon_T1 cpu_T[1]
1166 #define NEON_GET_REG(T, reg, n) \
1167 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1168 #define NEON_SET_REG(T, reg, n) \
1169 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1171 static TCGv
neon_load_reg(int reg
, int pass
)
1173 TCGv tmp
= new_tmp();
1174 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1178 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1180 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1184 static inline void neon_load_reg64(TCGv var
, int reg
)
1186 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1189 static inline void neon_store_reg64(TCGv var
, int reg
)
1191 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1194 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1195 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1196 #define tcg_gen_st_f32 tcg_gen_st_i32
1197 #define tcg_gen_st_f64 tcg_gen_st_i64
1199 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1202 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1204 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1207 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1210 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1212 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1215 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1218 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1220 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1223 #define ARM_CP_RW_BIT (1 << 20)
1225 static inline void iwmmxt_load_reg(TCGv var
, int reg
)
1227 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1230 static inline void iwmmxt_store_reg(TCGv var
, int reg
)
1232 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1235 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1237 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1240 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1242 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1245 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1247 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1250 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1252 iwmmxt_store_reg(cpu_M0
, rn
);
1255 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1257 iwmmxt_load_reg(cpu_M0
, rn
);
1260 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1262 iwmmxt_load_reg(cpu_V1
, rn
);
1263 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1266 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1268 iwmmxt_load_reg(cpu_V1
, rn
);
1269 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1272 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1274 iwmmxt_load_reg(cpu_V1
, rn
);
1275 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1278 #define IWMMXT_OP(name) \
1279 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1281 iwmmxt_load_reg(cpu_V1, rn); \
1282 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1285 #define IWMMXT_OP_ENV(name) \
1286 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1288 iwmmxt_load_reg(cpu_V1, rn); \
1289 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1292 #define IWMMXT_OP_ENV_SIZE(name) \
1293 IWMMXT_OP_ENV(name##b) \
1294 IWMMXT_OP_ENV(name##w) \
1295 IWMMXT_OP_ENV(name##l)
1297 #define IWMMXT_OP_ENV1(name) \
1298 static inline void gen_op_iwmmxt_##name##_M0(void) \
1300 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1314 IWMMXT_OP_ENV_SIZE(unpackl
)
1315 IWMMXT_OP_ENV_SIZE(unpackh
)
1317 IWMMXT_OP_ENV1(unpacklub
)
1318 IWMMXT_OP_ENV1(unpackluw
)
1319 IWMMXT_OP_ENV1(unpacklul
)
1320 IWMMXT_OP_ENV1(unpackhub
)
1321 IWMMXT_OP_ENV1(unpackhuw
)
1322 IWMMXT_OP_ENV1(unpackhul
)
1323 IWMMXT_OP_ENV1(unpacklsb
)
1324 IWMMXT_OP_ENV1(unpacklsw
)
1325 IWMMXT_OP_ENV1(unpacklsl
)
1326 IWMMXT_OP_ENV1(unpackhsb
)
1327 IWMMXT_OP_ENV1(unpackhsw
)
1328 IWMMXT_OP_ENV1(unpackhsl
)
1330 IWMMXT_OP_ENV_SIZE(cmpeq
)
1331 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1332 IWMMXT_OP_ENV_SIZE(cmpgts
)
1334 IWMMXT_OP_ENV_SIZE(mins
)
1335 IWMMXT_OP_ENV_SIZE(minu
)
1336 IWMMXT_OP_ENV_SIZE(maxs
)
1337 IWMMXT_OP_ENV_SIZE(maxu
)
1339 IWMMXT_OP_ENV_SIZE(subn
)
1340 IWMMXT_OP_ENV_SIZE(addn
)
1341 IWMMXT_OP_ENV_SIZE(subu
)
1342 IWMMXT_OP_ENV_SIZE(addu
)
1343 IWMMXT_OP_ENV_SIZE(subs
)
1344 IWMMXT_OP_ENV_SIZE(adds
)
1346 IWMMXT_OP_ENV(avgb0
)
1347 IWMMXT_OP_ENV(avgb1
)
1348 IWMMXT_OP_ENV(avgw0
)
1349 IWMMXT_OP_ENV(avgw1
)
1353 IWMMXT_OP_ENV(packuw
)
1354 IWMMXT_OP_ENV(packul
)
1355 IWMMXT_OP_ENV(packuq
)
1356 IWMMXT_OP_ENV(packsw
)
1357 IWMMXT_OP_ENV(packsl
)
1358 IWMMXT_OP_ENV(packsq
)
1360 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1362 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1365 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1367 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1370 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1372 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1375 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1377 iwmmxt_load_reg(cpu_V1
, rn
);
1378 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1381 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1383 TCGv tmp
= tcg_const_i32(shift
);
1384 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1387 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1389 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1390 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1391 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1394 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1396 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1397 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1398 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1401 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1403 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1404 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1406 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1409 static void gen_op_iwmmxt_set_mup(void)
1412 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1413 tcg_gen_ori_i32(tmp
, tmp
, 2);
1414 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1417 static void gen_op_iwmmxt_set_cup(void)
1420 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1421 tcg_gen_ori_i32(tmp
, tmp
, 1);
1422 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1425 static void gen_op_iwmmxt_setpsr_nz(void)
1427 TCGv tmp
= new_tmp();
1428 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1429 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1432 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1434 iwmmxt_load_reg(cpu_V1
, rn
);
1435 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1436 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1440 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1442 iwmmxt_load_reg(cpu_V0
, rn
);
1443 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1444 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1445 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1448 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1450 tcg_gen_extu_i32_i64(cpu_V0
, cpu_T
[0]);
1451 tcg_gen_extu_i32_i64(cpu_V1
, cpu_T
[0]);
1452 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 32);
1453 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
1454 iwmmxt_store_reg(cpu_V0
, rn
);
1457 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1462 rd
= (insn
>> 16) & 0xf;
1463 gen_movl_T1_reg(s
, rd
);
1465 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1466 if (insn
& (1 << 24)) {
1468 if (insn
& (1 << 23))
1469 gen_op_addl_T1_im(offset
);
1471 gen_op_addl_T1_im(-offset
);
1473 if (insn
& (1 << 21))
1474 gen_movl_reg_T1(s
, rd
);
1475 } else if (insn
& (1 << 21)) {
1477 if (insn
& (1 << 23))
1478 gen_op_movl_T0_im(offset
);
1480 gen_op_movl_T0_im(- offset
);
1481 gen_op_addl_T0_T1();
1482 gen_movl_reg_T0(s
, rd
);
1483 } else if (!(insn
& (1 << 23)))
1488 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1490 int rd
= (insn
>> 0) & 0xf;
1492 if (insn
& (1 << 8))
1493 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1496 gen_op_iwmmxt_movl_T0_wCx(rd
);
1498 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1500 gen_op_movl_T1_im(mask
);
1501 gen_op_andl_T0_T1();
1505 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1506 (ie. an undefined instruction). */
1507 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1510 int rdhi
, rdlo
, rd0
, rd1
, i
;
1513 if ((insn
& 0x0e000e00) == 0x0c000000) {
1514 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1516 rdlo
= (insn
>> 12) & 0xf;
1517 rdhi
= (insn
>> 16) & 0xf;
1518 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1519 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1520 gen_movl_reg_T0(s
, rdlo
);
1521 gen_movl_reg_T1(s
, rdhi
);
1522 } else { /* TMCRR */
1523 gen_movl_T0_reg(s
, rdlo
);
1524 gen_movl_T1_reg(s
, rdhi
);
1525 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1526 gen_op_iwmmxt_set_mup();
1531 wrd
= (insn
>> 12) & 0xf;
1532 if (gen_iwmmxt_address(s
, insn
))
1534 if (insn
& ARM_CP_RW_BIT
) {
1535 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1536 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1537 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1539 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1542 if (insn
& (1 << 8)) {
1543 if (insn
& (1 << 22)) { /* WLDRD */
1544 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1546 } else { /* WLDRW wRd */
1547 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1550 if (insn
& (1 << 22)) { /* WLDRH */
1551 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1552 } else { /* WLDRB */
1553 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1557 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1560 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1563 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1564 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1566 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1567 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1569 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1571 if (insn
& (1 << 8)) {
1572 if (insn
& (1 << 22)) { /* WSTRD */
1574 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1575 } else { /* WSTRW wRd */
1576 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1577 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1580 if (insn
& (1 << 22)) { /* WSTRH */
1581 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1582 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1583 } else { /* WSTRB */
1584 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1585 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1593 if ((insn
& 0x0f000000) != 0x0e000000)
1596 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1597 case 0x000: /* WOR */
1598 wrd
= (insn
>> 12) & 0xf;
1599 rd0
= (insn
>> 0) & 0xf;
1600 rd1
= (insn
>> 16) & 0xf;
1601 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1602 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1603 gen_op_iwmmxt_setpsr_nz();
1604 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1605 gen_op_iwmmxt_set_mup();
1606 gen_op_iwmmxt_set_cup();
1608 case 0x011: /* TMCR */
1611 rd
= (insn
>> 12) & 0xf;
1612 wrd
= (insn
>> 16) & 0xf;
1614 case ARM_IWMMXT_wCID
:
1615 case ARM_IWMMXT_wCASF
:
1617 case ARM_IWMMXT_wCon
:
1618 gen_op_iwmmxt_set_cup();
1620 case ARM_IWMMXT_wCSSF
:
1621 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1622 gen_movl_T1_reg(s
, rd
);
1623 gen_op_bicl_T0_T1();
1624 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1626 case ARM_IWMMXT_wCGR0
:
1627 case ARM_IWMMXT_wCGR1
:
1628 case ARM_IWMMXT_wCGR2
:
1629 case ARM_IWMMXT_wCGR3
:
1630 gen_op_iwmmxt_set_cup();
1631 gen_movl_reg_T0(s
, rd
);
1632 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1638 case 0x100: /* WXOR */
1639 wrd
= (insn
>> 12) & 0xf;
1640 rd0
= (insn
>> 0) & 0xf;
1641 rd1
= (insn
>> 16) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1643 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1644 gen_op_iwmmxt_setpsr_nz();
1645 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1646 gen_op_iwmmxt_set_mup();
1647 gen_op_iwmmxt_set_cup();
1649 case 0x111: /* TMRC */
1652 rd
= (insn
>> 12) & 0xf;
1653 wrd
= (insn
>> 16) & 0xf;
1654 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1655 gen_movl_reg_T0(s
, rd
);
1657 case 0x300: /* WANDN */
1658 wrd
= (insn
>> 12) & 0xf;
1659 rd0
= (insn
>> 0) & 0xf;
1660 rd1
= (insn
>> 16) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1662 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1663 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1664 gen_op_iwmmxt_setpsr_nz();
1665 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1666 gen_op_iwmmxt_set_mup();
1667 gen_op_iwmmxt_set_cup();
1669 case 0x200: /* WAND */
1670 wrd
= (insn
>> 12) & 0xf;
1671 rd0
= (insn
>> 0) & 0xf;
1672 rd1
= (insn
>> 16) & 0xf;
1673 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1674 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1675 gen_op_iwmmxt_setpsr_nz();
1676 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1677 gen_op_iwmmxt_set_mup();
1678 gen_op_iwmmxt_set_cup();
1680 case 0x810: case 0xa10: /* WMADD */
1681 wrd
= (insn
>> 12) & 0xf;
1682 rd0
= (insn
>> 0) & 0xf;
1683 rd1
= (insn
>> 16) & 0xf;
1684 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1685 if (insn
& (1 << 21))
1686 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1688 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1689 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1690 gen_op_iwmmxt_set_mup();
1692 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1693 wrd
= (insn
>> 12) & 0xf;
1694 rd0
= (insn
>> 16) & 0xf;
1695 rd1
= (insn
>> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1697 switch ((insn
>> 22) & 3) {
1699 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1702 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1705 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1710 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1711 gen_op_iwmmxt_set_mup();
1712 gen_op_iwmmxt_set_cup();
1714 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1715 wrd
= (insn
>> 12) & 0xf;
1716 rd0
= (insn
>> 16) & 0xf;
1717 rd1
= (insn
>> 0) & 0xf;
1718 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1719 switch ((insn
>> 22) & 3) {
1721 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1724 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1727 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1732 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1733 gen_op_iwmmxt_set_mup();
1734 gen_op_iwmmxt_set_cup();
1736 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1737 wrd
= (insn
>> 12) & 0xf;
1738 rd0
= (insn
>> 16) & 0xf;
1739 rd1
= (insn
>> 0) & 0xf;
1740 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1741 if (insn
& (1 << 22))
1742 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1744 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1745 if (!(insn
& (1 << 20)))
1746 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1747 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1748 gen_op_iwmmxt_set_mup();
1750 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1751 wrd
= (insn
>> 12) & 0xf;
1752 rd0
= (insn
>> 16) & 0xf;
1753 rd1
= (insn
>> 0) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1755 if (insn
& (1 << 21)) {
1756 if (insn
& (1 << 20))
1757 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1759 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1761 if (insn
& (1 << 20))
1762 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1764 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1767 gen_op_iwmmxt_set_mup();
1769 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
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 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1777 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1778 if (!(insn
& (1 << 20))) {
1779 iwmmxt_load_reg(cpu_V1
, wrd
);
1780 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1782 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1783 gen_op_iwmmxt_set_mup();
1785 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1786 wrd
= (insn
>> 12) & 0xf;
1787 rd0
= (insn
>> 16) & 0xf;
1788 rd1
= (insn
>> 0) & 0xf;
1789 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1790 switch ((insn
>> 22) & 3) {
1792 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1795 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1798 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1803 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1804 gen_op_iwmmxt_set_mup();
1805 gen_op_iwmmxt_set_cup();
1807 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1808 wrd
= (insn
>> 12) & 0xf;
1809 rd0
= (insn
>> 16) & 0xf;
1810 rd1
= (insn
>> 0) & 0xf;
1811 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1812 if (insn
& (1 << 22)) {
1813 if (insn
& (1 << 20))
1814 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1816 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1818 if (insn
& (1 << 20))
1819 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1821 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1823 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1824 gen_op_iwmmxt_set_mup();
1825 gen_op_iwmmxt_set_cup();
1827 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1828 wrd
= (insn
>> 12) & 0xf;
1829 rd0
= (insn
>> 16) & 0xf;
1830 rd1
= (insn
>> 0) & 0xf;
1831 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1832 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1833 gen_op_movl_T1_im(7);
1834 gen_op_andl_T0_T1();
1835 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1836 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1837 gen_op_iwmmxt_set_mup();
1839 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1840 rd
= (insn
>> 12) & 0xf;
1841 wrd
= (insn
>> 16) & 0xf;
1842 gen_movl_T0_reg(s
, rd
);
1843 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1844 switch ((insn
>> 6) & 3) {
1846 gen_op_movl_T1_im(0xff);
1847 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1850 gen_op_movl_T1_im(0xffff);
1851 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1854 gen_op_movl_T1_im(0xffffffff);
1855 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1860 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1861 gen_op_iwmmxt_set_mup();
1863 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1864 rd
= (insn
>> 12) & 0xf;
1865 wrd
= (insn
>> 16) & 0xf;
1868 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1869 switch ((insn
>> 22) & 3) {
1872 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1874 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1879 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1881 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1885 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1890 gen_movl_reg_T0(s
, rd
);
1892 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1893 if ((insn
& 0x000ff008) != 0x0003f000)
1895 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1896 switch ((insn
>> 22) & 3) {
1898 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1901 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1904 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1909 gen_op_shll_T1_im(28);
1910 gen_set_nzcv(cpu_T
[1]);
1912 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1913 rd
= (insn
>> 12) & 0xf;
1914 wrd
= (insn
>> 16) & 0xf;
1915 gen_movl_T0_reg(s
, rd
);
1916 switch ((insn
>> 6) & 3) {
1918 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1921 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1924 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1929 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1930 gen_op_iwmmxt_set_mup();
1932 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1933 if ((insn
& 0x000ff00f) != 0x0003f000)
1935 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1936 switch ((insn
>> 22) & 3) {
1938 for (i
= 0; i
< 7; i
++) {
1939 gen_op_shll_T1_im(4);
1940 gen_op_andl_T0_T1();
1944 for (i
= 0; i
< 3; i
++) {
1945 gen_op_shll_T1_im(8);
1946 gen_op_andl_T0_T1();
1950 gen_op_shll_T1_im(16);
1951 gen_op_andl_T0_T1();
1956 gen_set_nzcv(cpu_T
[0]);
1958 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1959 wrd
= (insn
>> 12) & 0xf;
1960 rd0
= (insn
>> 16) & 0xf;
1961 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1962 switch ((insn
>> 22) & 3) {
1964 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1967 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1970 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1975 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1976 gen_op_iwmmxt_set_mup();
1978 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1979 if ((insn
& 0x000ff00f) != 0x0003f000)
1981 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1982 switch ((insn
>> 22) & 3) {
1984 for (i
= 0; i
< 7; i
++) {
1985 gen_op_shll_T1_im(4);
1990 for (i
= 0; i
< 3; i
++) {
1991 gen_op_shll_T1_im(8);
1996 gen_op_shll_T1_im(16);
2002 gen_set_nzcv(cpu_T
[0]);
2004 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2005 rd
= (insn
>> 12) & 0xf;
2006 rd0
= (insn
>> 16) & 0xf;
2007 if ((insn
& 0xf) != 0)
2009 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2010 switch ((insn
>> 22) & 3) {
2012 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
2015 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
2018 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
2023 gen_movl_reg_T0(s
, rd
);
2025 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2026 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2027 wrd
= (insn
>> 12) & 0xf;
2028 rd0
= (insn
>> 16) & 0xf;
2029 rd1
= (insn
>> 0) & 0xf;
2030 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2031 switch ((insn
>> 22) & 3) {
2033 if (insn
& (1 << 21))
2034 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2036 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2039 if (insn
& (1 << 21))
2040 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2042 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2045 if (insn
& (1 << 21))
2046 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2048 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2053 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2054 gen_op_iwmmxt_set_mup();
2055 gen_op_iwmmxt_set_cup();
2057 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2058 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2059 wrd
= (insn
>> 12) & 0xf;
2060 rd0
= (insn
>> 16) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2062 switch ((insn
>> 22) & 3) {
2064 if (insn
& (1 << 21))
2065 gen_op_iwmmxt_unpacklsb_M0();
2067 gen_op_iwmmxt_unpacklub_M0();
2070 if (insn
& (1 << 21))
2071 gen_op_iwmmxt_unpacklsw_M0();
2073 gen_op_iwmmxt_unpackluw_M0();
2076 if (insn
& (1 << 21))
2077 gen_op_iwmmxt_unpacklsl_M0();
2079 gen_op_iwmmxt_unpacklul_M0();
2084 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2085 gen_op_iwmmxt_set_mup();
2086 gen_op_iwmmxt_set_cup();
2088 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2089 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2090 wrd
= (insn
>> 12) & 0xf;
2091 rd0
= (insn
>> 16) & 0xf;
2092 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2093 switch ((insn
>> 22) & 3) {
2095 if (insn
& (1 << 21))
2096 gen_op_iwmmxt_unpackhsb_M0();
2098 gen_op_iwmmxt_unpackhub_M0();
2101 if (insn
& (1 << 21))
2102 gen_op_iwmmxt_unpackhsw_M0();
2104 gen_op_iwmmxt_unpackhuw_M0();
2107 if (insn
& (1 << 21))
2108 gen_op_iwmmxt_unpackhsl_M0();
2110 gen_op_iwmmxt_unpackhul_M0();
2115 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2116 gen_op_iwmmxt_set_mup();
2117 gen_op_iwmmxt_set_cup();
2119 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2120 case 0x214: case 0x614: case 0xa14: case 0xe14:
2121 wrd
= (insn
>> 12) & 0xf;
2122 rd0
= (insn
>> 16) & 0xf;
2123 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2124 if (gen_iwmmxt_shift(insn
, 0xff))
2126 switch ((insn
>> 22) & 3) {
2130 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2133 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2136 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2139 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2140 gen_op_iwmmxt_set_mup();
2141 gen_op_iwmmxt_set_cup();
2143 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2144 case 0x014: case 0x414: case 0x814: case 0xc14:
2145 wrd
= (insn
>> 12) & 0xf;
2146 rd0
= (insn
>> 16) & 0xf;
2147 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2148 if (gen_iwmmxt_shift(insn
, 0xff))
2150 switch ((insn
>> 22) & 3) {
2154 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2157 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2160 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2163 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2164 gen_op_iwmmxt_set_mup();
2165 gen_op_iwmmxt_set_cup();
2167 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2168 case 0x114: case 0x514: case 0x914: case 0xd14:
2169 wrd
= (insn
>> 12) & 0xf;
2170 rd0
= (insn
>> 16) & 0xf;
2171 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2172 if (gen_iwmmxt_shift(insn
, 0xff))
2174 switch ((insn
>> 22) & 3) {
2178 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2181 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2184 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2187 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2188 gen_op_iwmmxt_set_mup();
2189 gen_op_iwmmxt_set_cup();
2191 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2192 case 0x314: case 0x714: case 0xb14: case 0xf14:
2193 wrd
= (insn
>> 12) & 0xf;
2194 rd0
= (insn
>> 16) & 0xf;
2195 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2196 switch ((insn
>> 22) & 3) {
2200 if (gen_iwmmxt_shift(insn
, 0xf))
2202 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2205 if (gen_iwmmxt_shift(insn
, 0x1f))
2207 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2210 if (gen_iwmmxt_shift(insn
, 0x3f))
2212 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2215 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2216 gen_op_iwmmxt_set_mup();
2217 gen_op_iwmmxt_set_cup();
2219 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2220 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2221 wrd
= (insn
>> 12) & 0xf;
2222 rd0
= (insn
>> 16) & 0xf;
2223 rd1
= (insn
>> 0) & 0xf;
2224 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2225 switch ((insn
>> 22) & 3) {
2227 if (insn
& (1 << 21))
2228 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2230 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2233 if (insn
& (1 << 21))
2234 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2236 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2239 if (insn
& (1 << 21))
2240 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2242 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2247 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2248 gen_op_iwmmxt_set_mup();
2250 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2251 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2252 wrd
= (insn
>> 12) & 0xf;
2253 rd0
= (insn
>> 16) & 0xf;
2254 rd1
= (insn
>> 0) & 0xf;
2255 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2256 switch ((insn
>> 22) & 3) {
2258 if (insn
& (1 << 21))
2259 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2261 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2264 if (insn
& (1 << 21))
2265 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2267 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2270 if (insn
& (1 << 21))
2271 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2273 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2278 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2279 gen_op_iwmmxt_set_mup();
2281 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2282 case 0x402: case 0x502: case 0x602: case 0x702:
2283 wrd
= (insn
>> 12) & 0xf;
2284 rd0
= (insn
>> 16) & 0xf;
2285 rd1
= (insn
>> 0) & 0xf;
2286 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2287 gen_op_movl_T0_im((insn
>> 20) & 3);
2288 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2289 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2290 gen_op_iwmmxt_set_mup();
2292 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2293 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2294 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2295 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2296 wrd
= (insn
>> 12) & 0xf;
2297 rd0
= (insn
>> 16) & 0xf;
2298 rd1
= (insn
>> 0) & 0xf;
2299 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2300 switch ((insn
>> 20) & 0xf) {
2302 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2305 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2308 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2311 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2314 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2317 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2320 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2323 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2326 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2331 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2332 gen_op_iwmmxt_set_mup();
2333 gen_op_iwmmxt_set_cup();
2335 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2336 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2337 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2338 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2339 wrd
= (insn
>> 12) & 0xf;
2340 rd0
= (insn
>> 16) & 0xf;
2341 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2342 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2343 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2344 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2345 gen_op_iwmmxt_set_mup();
2346 gen_op_iwmmxt_set_cup();
2348 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2349 case 0x418: case 0x518: case 0x618: case 0x718:
2350 case 0x818: case 0x918: case 0xa18: case 0xb18:
2351 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2352 wrd
= (insn
>> 12) & 0xf;
2353 rd0
= (insn
>> 16) & 0xf;
2354 rd1
= (insn
>> 0) & 0xf;
2355 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2356 switch ((insn
>> 20) & 0xf) {
2358 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2361 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2364 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2367 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2370 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2373 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2376 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2379 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2382 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2387 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2388 gen_op_iwmmxt_set_mup();
2389 gen_op_iwmmxt_set_cup();
2391 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2392 case 0x408: case 0x508: case 0x608: case 0x708:
2393 case 0x808: case 0x908: case 0xa08: case 0xb08:
2394 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2395 wrd
= (insn
>> 12) & 0xf;
2396 rd0
= (insn
>> 16) & 0xf;
2397 rd1
= (insn
>> 0) & 0xf;
2398 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2399 if (!(insn
& (1 << 20)))
2401 switch ((insn
>> 22) & 3) {
2405 if (insn
& (1 << 21))
2406 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2408 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2411 if (insn
& (1 << 21))
2412 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2414 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2417 if (insn
& (1 << 21))
2418 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2420 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2423 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2424 gen_op_iwmmxt_set_mup();
2425 gen_op_iwmmxt_set_cup();
2427 case 0x201: case 0x203: case 0x205: case 0x207:
2428 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2429 case 0x211: case 0x213: case 0x215: case 0x217:
2430 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2431 wrd
= (insn
>> 5) & 0xf;
2432 rd0
= (insn
>> 12) & 0xf;
2433 rd1
= (insn
>> 0) & 0xf;
2434 if (rd0
== 0xf || rd1
== 0xf)
2436 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2437 switch ((insn
>> 16) & 0xf) {
2438 case 0x0: /* TMIA */
2439 gen_movl_T0_reg(s
, rd0
);
2440 gen_movl_T1_reg(s
, rd1
);
2441 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2443 case 0x8: /* TMIAPH */
2444 gen_movl_T0_reg(s
, rd0
);
2445 gen_movl_T1_reg(s
, rd1
);
2446 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2448 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2449 gen_movl_T1_reg(s
, rd0
);
2450 if (insn
& (1 << 16))
2451 gen_op_shrl_T1_im(16);
2452 gen_op_movl_T0_T1();
2453 gen_movl_T1_reg(s
, rd1
);
2454 if (insn
& (1 << 17))
2455 gen_op_shrl_T1_im(16);
2456 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2461 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2462 gen_op_iwmmxt_set_mup();
2471 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2472 (ie. an undefined instruction). */
2473 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2475 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2477 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2478 /* Multiply with Internal Accumulate Format */
2479 rd0
= (insn
>> 12) & 0xf;
2481 acc
= (insn
>> 5) & 7;
2486 switch ((insn
>> 16) & 0xf) {
2488 gen_movl_T0_reg(s
, rd0
);
2489 gen_movl_T1_reg(s
, rd1
);
2490 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2492 case 0x8: /* MIAPH */
2493 gen_movl_T0_reg(s
, rd0
);
2494 gen_movl_T1_reg(s
, rd1
);
2495 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2497 case 0xc: /* MIABB */
2498 case 0xd: /* MIABT */
2499 case 0xe: /* MIATB */
2500 case 0xf: /* MIATT */
2501 gen_movl_T1_reg(s
, rd0
);
2502 if (insn
& (1 << 16))
2503 gen_op_shrl_T1_im(16);
2504 gen_op_movl_T0_T1();
2505 gen_movl_T1_reg(s
, rd1
);
2506 if (insn
& (1 << 17))
2507 gen_op_shrl_T1_im(16);
2508 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2514 gen_op_iwmmxt_movq_wRn_M0(acc
);
2518 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2519 /* Internal Accumulator Access Format */
2520 rdhi
= (insn
>> 16) & 0xf;
2521 rdlo
= (insn
>> 12) & 0xf;
2527 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2528 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2529 gen_movl_reg_T0(s
, rdlo
);
2530 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2531 gen_op_andl_T0_T1();
2532 gen_movl_reg_T0(s
, rdhi
);
2534 gen_movl_T0_reg(s
, rdlo
);
2535 gen_movl_T1_reg(s
, rdhi
);
2536 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2544 /* Disassemble system coprocessor instruction. Return nonzero if
2545 instruction is not defined. */
2546 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2549 uint32_t rd
= (insn
>> 12) & 0xf;
2550 uint32_t cp
= (insn
>> 8) & 0xf;
2555 if (insn
& ARM_CP_RW_BIT
) {
2556 if (!env
->cp
[cp
].cp_read
)
2558 gen_set_pc_im(s
->pc
);
2560 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2561 store_reg(s
, rd
, tmp
);
2563 if (!env
->cp
[cp
].cp_write
)
2565 gen_set_pc_im(s
->pc
);
2566 tmp
= load_reg(s
, rd
);
2567 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2572 static int cp15_user_ok(uint32_t insn
)
2574 int cpn
= (insn
>> 16) & 0xf;
2575 int cpm
= insn
& 0xf;
2576 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2578 if (cpn
== 13 && cpm
== 0) {
2580 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2584 /* ISB, DSB, DMB. */
2585 if ((cpm
== 5 && op
== 4)
2586 || (cpm
== 10 && (op
== 4 || op
== 5)))
2592 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2593 instruction is not defined. */
2594 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2599 /* M profile cores use memory mapped registers instead of cp15. */
2600 if (arm_feature(env
, ARM_FEATURE_M
))
2603 if ((insn
& (1 << 25)) == 0) {
2604 if (insn
& (1 << 20)) {
2608 /* mcrr. Used for block cache operations, so implement as no-op. */
2611 if ((insn
& (1 << 4)) == 0) {
2615 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2618 if ((insn
& 0x0fff0fff) == 0x0e070f90
2619 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2620 /* Wait for interrupt. */
2621 gen_set_pc_im(s
->pc
);
2622 s
->is_jmp
= DISAS_WFI
;
2625 rd
= (insn
>> 12) & 0xf;
2626 if (insn
& ARM_CP_RW_BIT
) {
2628 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2629 /* If the destination register is r15 then sets condition codes. */
2631 store_reg(s
, rd
, tmp
);
2635 tmp
= load_reg(s
, rd
);
2636 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2638 /* Normally we would always end the TB here, but Linux
2639 * arch/arm/mach-pxa/sleep.S expects two instructions following
2640 * an MMU enable to execute from cache. Imitate this behaviour. */
2641 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2642 (insn
& 0x0fff0fff) != 0x0e010f10)
2648 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2649 #define VFP_SREG(insn, bigbit, smallbit) \
2650 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2651 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2652 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2653 reg = (((insn) >> (bigbit)) & 0x0f) \
2654 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2656 if (insn & (1 << (smallbit))) \
2658 reg = ((insn) >> (bigbit)) & 0x0f; \
2661 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2662 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2663 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2664 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2665 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2666 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2668 /* Move between integer and VFP cores. */
2669 static TCGv
gen_vfp_mrs(void)
2671 TCGv tmp
= new_tmp();
2672 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2676 static void gen_vfp_msr(TCGv tmp
)
2678 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2683 vfp_enabled(CPUState
* env
)
2685 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2688 static void gen_neon_dup_u8(TCGv var
, int shift
)
2690 TCGv tmp
= new_tmp();
2692 tcg_gen_shri_i32(var
, var
, shift
);
2693 tcg_gen_ext8u_i32(var
, var
);
2694 tcg_gen_shli_i32(tmp
, var
, 8);
2695 tcg_gen_or_i32(var
, var
, tmp
);
2696 tcg_gen_shli_i32(tmp
, var
, 16);
2697 tcg_gen_or_i32(var
, var
, tmp
);
2701 static void gen_neon_dup_low16(TCGv var
)
2703 TCGv tmp
= new_tmp();
2704 tcg_gen_ext16u_i32(var
, var
);
2705 tcg_gen_shli_i32(tmp
, var
, 16);
2706 tcg_gen_or_i32(var
, var
, tmp
);
2710 static void gen_neon_dup_high16(TCGv var
)
2712 TCGv tmp
= new_tmp();
2713 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2714 tcg_gen_shri_i32(tmp
, var
, 16);
2715 tcg_gen_or_i32(var
, var
, tmp
);
2719 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2720 (ie. an undefined instruction). */
2721 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2723 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2728 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2731 if (!vfp_enabled(env
)) {
2732 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2733 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2735 rn
= (insn
>> 16) & 0xf;
2736 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2737 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2740 dp
= ((insn
& 0xf00) == 0xb00);
2741 switch ((insn
>> 24) & 0xf) {
2743 if (insn
& (1 << 4)) {
2744 /* single register transfer */
2745 rd
= (insn
>> 12) & 0xf;
2750 VFP_DREG_N(rn
, insn
);
2753 if (insn
& 0x00c00060
2754 && !arm_feature(env
, ARM_FEATURE_NEON
))
2757 pass
= (insn
>> 21) & 1;
2758 if (insn
& (1 << 22)) {
2760 offset
= ((insn
>> 5) & 3) * 8;
2761 } else if (insn
& (1 << 5)) {
2763 offset
= (insn
& (1 << 6)) ? 16 : 0;
2768 if (insn
& ARM_CP_RW_BIT
) {
2770 tmp
= neon_load_reg(rn
, pass
);
2774 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2775 if (insn
& (1 << 23))
2781 if (insn
& (1 << 23)) {
2783 tcg_gen_shri_i32(tmp
, tmp
, 16);
2789 tcg_gen_sari_i32(tmp
, tmp
, 16);
2798 store_reg(s
, rd
, tmp
);
2801 tmp
= load_reg(s
, rd
);
2802 if (insn
& (1 << 23)) {
2805 gen_neon_dup_u8(tmp
, 0);
2806 } else if (size
== 1) {
2807 gen_neon_dup_low16(tmp
);
2810 tcg_gen_mov_i32(tmp2
, tmp
);
2811 neon_store_reg(rn
, 0, tmp2
);
2812 neon_store_reg(rn
, 0, tmp
);
2817 tmp2
= neon_load_reg(rn
, pass
);
2818 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2822 tmp2
= neon_load_reg(rn
, pass
);
2823 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2829 neon_store_reg(rn
, pass
, tmp
);
2833 if ((insn
& 0x6f) != 0x00)
2835 rn
= VFP_SREG_N(insn
);
2836 if (insn
& ARM_CP_RW_BIT
) {
2838 if (insn
& (1 << 21)) {
2839 /* system register */
2844 /* VFP2 allows access to FSID from userspace.
2845 VFP3 restricts all id registers to privileged
2848 && arm_feature(env
, ARM_FEATURE_VFP3
))
2850 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2855 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2857 case ARM_VFP_FPINST
:
2858 case ARM_VFP_FPINST2
:
2859 /* Not present in VFP3. */
2861 || arm_feature(env
, ARM_FEATURE_VFP3
))
2863 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2867 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2868 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2871 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2877 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2879 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2885 gen_mov_F0_vreg(0, rn
);
2886 tmp
= gen_vfp_mrs();
2889 /* Set the 4 flag bits in the CPSR. */
2893 store_reg(s
, rd
, tmp
);
2897 tmp
= load_reg(s
, rd
);
2898 if (insn
& (1 << 21)) {
2900 /* system register */
2905 /* Writes are ignored. */
2908 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2915 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2918 case ARM_VFP_FPINST
:
2919 case ARM_VFP_FPINST2
:
2920 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2927 gen_mov_vreg_F0(0, rn
);
2932 /* data processing */
2933 /* The opcode is in bits 23, 21, 20 and 6. */
2934 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2938 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2940 /* rn is register number */
2941 VFP_DREG_N(rn
, insn
);
2944 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2945 /* Integer or single precision destination. */
2946 rd
= VFP_SREG_D(insn
);
2948 VFP_DREG_D(rd
, insn
);
2951 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2952 /* Integer source. */
2953 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2955 VFP_DREG_M(rm
, insn
);
2958 rn
= VFP_SREG_N(insn
);
2959 if (op
== 15 && rn
== 15) {
2960 /* Double precision destination. */
2961 VFP_DREG_D(rd
, insn
);
2963 rd
= VFP_SREG_D(insn
);
2965 rm
= VFP_SREG_M(insn
);
2968 veclen
= env
->vfp
.vec_len
;
2969 if (op
== 15 && rn
> 3)
2972 /* Shut up compiler warnings. */
2983 /* Figure out what type of vector operation this is. */
2984 if ((rd
& bank_mask
) == 0) {
2989 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2991 delta_d
= env
->vfp
.vec_stride
+ 1;
2993 if ((rm
& bank_mask
) == 0) {
2994 /* mixed scalar/vector */
3003 /* Load the initial operands. */
3008 /* Integer source */
3009 gen_mov_F0_vreg(0, rm
);
3014 gen_mov_F0_vreg(dp
, rd
);
3015 gen_mov_F1_vreg(dp
, rm
);
3019 /* Compare with zero */
3020 gen_mov_F0_vreg(dp
, rd
);
3027 /* Source and destination the same. */
3028 gen_mov_F0_vreg(dp
, rd
);
3031 /* One source operand. */
3032 gen_mov_F0_vreg(dp
, rm
);
3036 /* Two source operands. */
3037 gen_mov_F0_vreg(dp
, rn
);
3038 gen_mov_F1_vreg(dp
, rm
);
3042 /* Perform the calculation. */
3044 case 0: /* mac: fd + (fn * fm) */
3046 gen_mov_F1_vreg(dp
, rd
);
3049 case 1: /* nmac: fd - (fn * fm) */
3052 gen_mov_F1_vreg(dp
, rd
);
3055 case 2: /* msc: -fd + (fn * fm) */
3057 gen_mov_F1_vreg(dp
, rd
);
3060 case 3: /* nmsc: -fd - (fn * fm) */
3062 gen_mov_F1_vreg(dp
, rd
);
3066 case 4: /* mul: fn * fm */
3069 case 5: /* nmul: -(fn * fm) */
3073 case 6: /* add: fn + fm */
3076 case 7: /* sub: fn - fm */
3079 case 8: /* div: fn / fm */
3082 case 14: /* fconst */
3083 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3086 n
= (insn
<< 12) & 0x80000000;
3087 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3094 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3101 tcg_gen_movi_i32(cpu_F0s
, n
);
3104 case 15: /* extension space */
3127 case 11: /* cmpez */
3131 case 15: /* single<->double conversion */
3133 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3135 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3137 case 16: /* fuito */
3140 case 17: /* fsito */
3143 case 20: /* fshto */
3144 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3146 gen_vfp_shto(dp
, rm
);
3148 case 21: /* fslto */
3149 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3151 gen_vfp_slto(dp
, rm
);
3153 case 22: /* fuhto */
3154 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3156 gen_vfp_uhto(dp
, rm
);
3158 case 23: /* fulto */
3159 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3161 gen_vfp_ulto(dp
, rm
);
3163 case 24: /* ftoui */
3166 case 25: /* ftouiz */
3169 case 26: /* ftosi */
3172 case 27: /* ftosiz */
3175 case 28: /* ftosh */
3176 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3178 gen_vfp_tosh(dp
, rm
);
3180 case 29: /* ftosl */
3181 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3183 gen_vfp_tosl(dp
, rm
);
3185 case 30: /* ftouh */
3186 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3188 gen_vfp_touh(dp
, rm
);
3190 case 31: /* ftoul */
3191 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3193 gen_vfp_toul(dp
, rm
);
3195 default: /* undefined */
3196 printf ("rn:%d\n", rn
);
3200 default: /* undefined */
3201 printf ("op:%d\n", op
);
3205 /* Write back the result. */
3206 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3207 ; /* Comparison, do nothing. */
3208 else if (op
== 15 && rn
> 17)
3209 /* Integer result. */
3210 gen_mov_vreg_F0(0, rd
);
3211 else if (op
== 15 && rn
== 15)
3213 gen_mov_vreg_F0(!dp
, rd
);
3215 gen_mov_vreg_F0(dp
, rd
);
3217 /* break out of the loop if we have finished */
3221 if (op
== 15 && delta_m
== 0) {
3222 /* single source one-many */
3224 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3226 gen_mov_vreg_F0(dp
, rd
);
3230 /* Setup the next operands. */
3232 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3236 /* One source operand. */
3237 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3239 gen_mov_F0_vreg(dp
, rm
);
3241 /* Two source operands. */
3242 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3244 gen_mov_F0_vreg(dp
, rn
);
3246 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3248 gen_mov_F1_vreg(dp
, rm
);
3256 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3257 /* two-register transfer */
3258 rn
= (insn
>> 16) & 0xf;
3259 rd
= (insn
>> 12) & 0xf;
3261 VFP_DREG_M(rm
, insn
);
3263 rm
= VFP_SREG_M(insn
);
3266 if (insn
& ARM_CP_RW_BIT
) {
3269 gen_mov_F0_vreg(0, rm
* 2);
3270 tmp
= gen_vfp_mrs();
3271 store_reg(s
, rd
, tmp
);
3272 gen_mov_F0_vreg(0, rm
* 2 + 1);
3273 tmp
= gen_vfp_mrs();
3274 store_reg(s
, rn
, tmp
);
3276 gen_mov_F0_vreg(0, rm
);
3277 tmp
= gen_vfp_mrs();
3278 store_reg(s
, rn
, tmp
);
3279 gen_mov_F0_vreg(0, rm
+ 1);
3280 tmp
= gen_vfp_mrs();
3281 store_reg(s
, rd
, tmp
);
3286 tmp
= load_reg(s
, rd
);
3288 gen_mov_vreg_F0(0, rm
* 2);
3289 tmp
= load_reg(s
, rn
);
3291 gen_mov_vreg_F0(0, rm
* 2 + 1);
3293 tmp
= load_reg(s
, rn
);
3295 gen_mov_vreg_F0(0, rm
);
3296 tmp
= load_reg(s
, rd
);
3298 gen_mov_vreg_F0(0, rm
+ 1);
3303 rn
= (insn
>> 16) & 0xf;
3305 VFP_DREG_D(rd
, insn
);
3307 rd
= VFP_SREG_D(insn
);
3308 if (s
->thumb
&& rn
== 15) {
3309 gen_op_movl_T1_im(s
->pc
& ~2);
3311 gen_movl_T1_reg(s
, rn
);
3313 if ((insn
& 0x01200000) == 0x01000000) {
3314 /* Single load/store */
3315 offset
= (insn
& 0xff) << 2;
3316 if ((insn
& (1 << 23)) == 0)
3318 gen_op_addl_T1_im(offset
);
3319 if (insn
& (1 << 20)) {
3321 gen_mov_vreg_F0(dp
, rd
);
3323 gen_mov_F0_vreg(dp
, rd
);
3327 /* load/store multiple */
3329 n
= (insn
>> 1) & 0x7f;
3333 if (insn
& (1 << 24)) /* pre-decrement */
3334 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3340 for (i
= 0; i
< n
; i
++) {
3341 if (insn
& ARM_CP_RW_BIT
) {
3344 gen_mov_vreg_F0(dp
, rd
+ i
);
3347 gen_mov_F0_vreg(dp
, rd
+ i
);
3350 gen_op_addl_T1_im(offset
);
3352 if (insn
& (1 << 21)) {
3354 if (insn
& (1 << 24))
3355 offset
= -offset
* n
;
3356 else if (dp
&& (insn
& 1))
3362 gen_op_addl_T1_im(offset
);
3363 gen_movl_reg_T1(s
, rn
);
3369 /* Should never happen. */
3375 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3377 TranslationBlock
*tb
;
3380 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3382 gen_set_pc_im(dest
);
3383 tcg_gen_exit_tb((long)tb
+ n
);
3385 gen_set_pc_im(dest
);
3390 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3392 if (__builtin_expect(s
->singlestep_enabled
, 0)) {
3393 /* An indirect jump so that we still trigger the debug exception. */
3398 gen_goto_tb(s
, 0, dest
);
3399 s
->is_jmp
= DISAS_TB_JUMP
;
3403 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3406 tcg_gen_sari_i32(t0
, t0
, 16);
3410 tcg_gen_sari_i32(t1
, t1
, 16);
3413 tcg_gen_mul_i32(t0
, t0
, t1
);
3416 /* Return the mask of PSR bits set by a MSR instruction. */
3417 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3421 if (flags
& (1 << 0))
3423 if (flags
& (1 << 1))
3425 if (flags
& (1 << 2))
3427 if (flags
& (1 << 3))
3430 /* Mask out undefined bits. */
3431 mask
&= ~CPSR_RESERVED
;
3432 if (!arm_feature(env
, ARM_FEATURE_V6
))
3433 mask
&= ~(CPSR_E
| CPSR_GE
);
3434 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3436 /* Mask out execution state bits. */
3439 /* Mask out privileged bits. */
3445 /* Returns nonzero if access to the PSR is not permitted. */
3446 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3450 /* ??? This is also undefined in system mode. */
3454 tmp
= load_cpu_field(spsr
);
3455 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3456 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3457 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3458 store_cpu_field(tmp
, spsr
);
3460 gen_set_cpsr(cpu_T
[0], mask
);
3466 /* Generate an old-style exception return. */
3467 static void gen_exception_return(DisasContext
*s
)
3470 gen_movl_reg_T0(s
, 15);
3471 tmp
= load_cpu_field(spsr
);
3472 gen_set_cpsr(tmp
, 0xffffffff);
3474 s
->is_jmp
= DISAS_UPDATE
;
3477 /* Generate a v6 exception return. Marks both values as dead. */
3478 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3480 gen_set_cpsr(cpsr
, 0xffffffff);
3482 store_reg(s
, 15, pc
);
3483 s
->is_jmp
= DISAS_UPDATE
;
3487 gen_set_condexec (DisasContext
*s
)
3489 if (s
->condexec_mask
) {
3490 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3491 TCGv tmp
= new_tmp();
3492 tcg_gen_movi_i32(tmp
, val
);
3493 store_cpu_field(tmp
, condexec_bits
);
3497 static void gen_nop_hint(DisasContext
*s
, int val
)
3501 gen_set_pc_im(s
->pc
);
3502 s
->is_jmp
= DISAS_WFI
;
3506 /* TODO: Implement SEV and WFE. May help SMP performance. */
3512 /* These macros help make the code more readable when migrating from the
3513 old dyngen helpers. They should probably be removed when
3514 T0/T1 are removed. */
3515 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3516 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3518 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3520 static inline int gen_neon_add(int size
)
3523 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3524 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3525 case 2: gen_op_addl_T0_T1(); break;
3531 static inline void gen_neon_rsb(int size
)
3534 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3535 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3536 case 2: gen_op_rsbl_T0_T1(); break;
3541 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3542 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3543 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3544 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3545 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3547 /* FIXME: This is wrong. They set the wrong overflow bit. */
3548 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3549 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3550 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3551 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3553 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3554 switch ((size << 1) | u) { \
3556 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3559 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3562 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3565 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3568 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3571 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3573 default: return 1; \
3576 #define GEN_NEON_INTEGER_OP(name) do { \
3577 switch ((size << 1) | u) { \
3579 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3582 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3585 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3588 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3591 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3594 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3596 default: return 1; \
3600 gen_neon_movl_scratch_T0(int scratch
)
3604 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3605 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3609 gen_neon_movl_scratch_T1(int scratch
)
3613 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3614 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3618 gen_neon_movl_T0_scratch(int scratch
)
3622 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3623 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3627 gen_neon_movl_T1_scratch(int scratch
)
3631 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3632 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3635 static inline void gen_neon_get_scalar(int size
, int reg
)
3638 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3640 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3642 gen_neon_dup_low16(cpu_T
[0]);
3644 gen_neon_dup_high16(cpu_T
[0]);
3648 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3652 for (n
= 0; n
< q
+ 1; n
+= 2) {
3653 NEON_GET_REG(T0
, reg
, n
);
3654 NEON_GET_REG(T0
, reg
, n
+ n
);
3656 case 0: gen_helper_neon_unzip_u8(); break;
3657 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3658 case 2: /* no-op */; break;
3661 gen_neon_movl_scratch_T0(tmp
+ n
);
3662 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3670 } neon_ls_element_type
[11] = {
3684 /* Translate a NEON load/store element instruction. Return nonzero if the
3685 instruction is invalid. */
3686 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3702 if (!vfp_enabled(env
))
3704 VFP_DREG_D(rd
, insn
);
3705 rn
= (insn
>> 16) & 0xf;
3707 load
= (insn
& (1 << 21)) != 0;
3708 if ((insn
& (1 << 23)) == 0) {
3709 /* Load store all elements. */
3710 op
= (insn
>> 8) & 0xf;
3711 size
= (insn
>> 6) & 3;
3712 if (op
> 10 || size
== 3)
3714 nregs
= neon_ls_element_type
[op
].nregs
;
3715 interleave
= neon_ls_element_type
[op
].interleave
;
3716 gen_movl_T1_reg(s
, rn
);
3717 stride
= (1 << size
) * interleave
;
3718 for (reg
= 0; reg
< nregs
; reg
++) {
3719 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3720 gen_movl_T1_reg(s
, rn
);
3721 gen_op_addl_T1_im((1 << size
) * reg
);
3722 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3723 gen_movl_T1_reg(s
, rn
);
3724 gen_op_addl_T1_im(1 << size
);
3726 for (pass
= 0; pass
< 2; pass
++) {
3729 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3730 neon_store_reg(rd
, pass
, tmp
);
3732 tmp
= neon_load_reg(rd
, pass
);
3733 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3735 gen_op_addl_T1_im(stride
);
3736 } else if (size
== 1) {
3738 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3739 gen_op_addl_T1_im(stride
);
3740 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3741 gen_op_addl_T1_im(stride
);
3742 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3744 neon_store_reg(rd
, pass
, tmp
);
3746 tmp
= neon_load_reg(rd
, pass
);
3748 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3749 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3750 gen_op_addl_T1_im(stride
);
3751 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3752 gen_op_addl_T1_im(stride
);
3754 } else /* size == 0 */ {
3756 for (n
= 0; n
< 4; n
++) {
3757 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3758 gen_op_addl_T1_im(stride
);
3762 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3766 neon_store_reg(rd
, pass
, tmp2
);
3768 tmp2
= neon_load_reg(rd
, pass
);
3769 for (n
= 0; n
< 4; n
++) {
3772 tcg_gen_mov_i32(tmp
, tmp2
);
3774 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3776 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3777 gen_op_addl_T1_im(stride
);
3783 rd
+= neon_ls_element_type
[op
].spacing
;
3787 size
= (insn
>> 10) & 3;
3789 /* Load single element to all lanes. */
3792 size
= (insn
>> 6) & 3;
3793 nregs
= ((insn
>> 8) & 3) + 1;
3794 stride
= (insn
& (1 << 5)) ? 2 : 1;
3795 gen_movl_T1_reg(s
, rn
);
3796 for (reg
= 0; reg
< nregs
; reg
++) {
3799 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3800 gen_neon_dup_u8(tmp
, 0);
3803 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3804 gen_neon_dup_low16(tmp
);
3807 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3812 gen_op_addl_T1_im(1 << size
);
3814 tcg_gen_mov_i32(tmp2
, tmp
);
3815 neon_store_reg(rd
, 0, tmp2
);
3816 neon_store_reg(rd
, 0, tmp
);
3819 stride
= (1 << size
) * nregs
;
3821 /* Single element. */
3822 pass
= (insn
>> 7) & 1;
3825 shift
= ((insn
>> 5) & 3) * 8;
3829 shift
= ((insn
>> 6) & 1) * 16;
3830 stride
= (insn
& (1 << 5)) ? 2 : 1;
3834 stride
= (insn
& (1 << 6)) ? 2 : 1;
3839 nregs
= ((insn
>> 8) & 3) + 1;
3840 gen_movl_T1_reg(s
, rn
);
3841 for (reg
= 0; reg
< nregs
; reg
++) {
3845 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3848 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3851 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3855 tmp2
= neon_load_reg(rd
, pass
);
3856 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3859 neon_store_reg(rd
, pass
, tmp
);
3860 } else { /* Store */
3861 tmp
= neon_load_reg(rd
, pass
);
3863 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3866 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3869 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3872 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3877 gen_op_addl_T1_im(1 << size
);
3879 stride
= nregs
* (1 << size
);
3885 base
= load_reg(s
, rn
);
3887 tcg_gen_addi_i32(base
, base
, stride
);
3890 index
= load_reg(s
, rm
);
3891 tcg_gen_add_i32(base
, base
, index
);
3894 store_reg(s
, rn
, base
);
3899 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3900 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3902 tcg_gen_and_i32(t
, t
, c
);
3903 tcg_gen_bic_i32(f
, f
, c
);
3904 tcg_gen_or_i32(dest
, t
, f
);
3907 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv src
)
3910 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3911 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3912 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3917 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv src
)
3920 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3921 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3922 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3927 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv src
)
3930 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3931 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3932 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3937 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3943 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3944 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3949 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3950 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3957 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3958 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3963 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3964 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3971 static inline void gen_neon_widen(TCGv dest
, TCGv src
, int size
, int u
)
3975 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3976 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3977 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3982 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3983 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3984 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3991 static inline void gen_neon_addl(int size
)
3994 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
3995 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
3996 case 2: tcg_gen_add_i64(CPU_V001
); break;
4001 static inline void gen_neon_subl(int size
)
4004 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4005 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4006 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4011 static inline void gen_neon_negl(TCGv var
, int size
)
4014 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4015 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4016 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4021 static inline void gen_neon_addl_saturate(TCGv op0
, TCGv op1
, int size
)
4024 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4025 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4030 static inline void gen_neon_mull(TCGv dest
, TCGv a
, TCGv b
, int size
, int u
)
4034 switch ((size
<< 1) | u
) {
4035 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4036 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4037 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4038 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4040 tmp
= gen_muls_i64_i32(a
, b
);
4041 tcg_gen_mov_i64(dest
, tmp
);
4044 tmp
= gen_mulu_i64_i32(a
, b
);
4045 tcg_gen_mov_i64(dest
, tmp
);
4055 /* Translate a NEON data processing instruction. Return nonzero if the
4056 instruction is invalid.
4057 We process data in a mixture of 32-bit and 64-bit chunks.
4058 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4060 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4077 if (!vfp_enabled(env
))
4079 q
= (insn
& (1 << 6)) != 0;
4080 u
= (insn
>> 24) & 1;
4081 VFP_DREG_D(rd
, insn
);
4082 VFP_DREG_N(rn
, insn
);
4083 VFP_DREG_M(rm
, insn
);
4084 size
= (insn
>> 20) & 3;
4085 if ((insn
& (1 << 23)) == 0) {
4086 /* Three register same length. */
4087 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4088 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4089 || op
== 10 || op
== 11 || op
== 16)) {
4090 /* 64-bit element instructions. */
4091 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4092 neon_load_reg64(cpu_V0
, rn
+ pass
);
4093 neon_load_reg64(cpu_V1
, rm
+ pass
);
4097 gen_helper_neon_add_saturate_u64(CPU_V001
);
4099 gen_helper_neon_add_saturate_s64(CPU_V001
);
4104 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4106 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4111 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4113 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4118 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4121 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4125 case 10: /* VRSHL */
4127 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4129 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4132 case 11: /* VQRSHL */
4134 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4137 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4143 tcg_gen_sub_i64(CPU_V001
);
4145 tcg_gen_add_i64(CPU_V001
);
4151 neon_store_reg64(cpu_V0
, rd
+ pass
);
4158 case 10: /* VRSHL */
4159 case 11: /* VQRSHL */
4162 /* Shift instruction operands are reversed. */
4169 case 20: /* VPMAX */
4170 case 21: /* VPMIN */
4171 case 23: /* VPADD */
4174 case 26: /* VPADD (float) */
4175 pairwise
= (u
&& size
< 2);
4177 case 30: /* VPMIN/VPMAX (float) */
4184 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4193 NEON_GET_REG(T0
, rn
, n
);
4194 NEON_GET_REG(T1
, rn
, n
+ 1);
4196 NEON_GET_REG(T0
, rm
, n
);
4197 NEON_GET_REG(T1
, rm
, n
+ 1);
4201 NEON_GET_REG(T0
, rn
, pass
);
4202 NEON_GET_REG(T1
, rm
, pass
);
4206 GEN_NEON_INTEGER_OP(hadd
);
4209 GEN_NEON_INTEGER_OP_ENV(qadd
);
4211 case 2: /* VRHADD */
4212 GEN_NEON_INTEGER_OP(rhadd
);
4214 case 3: /* Logic ops. */
4215 switch ((u
<< 2) | size
) {
4217 gen_op_andl_T0_T1();
4220 gen_op_bicl_T0_T1();
4230 gen_op_xorl_T0_T1();
4233 tmp
= neon_load_reg(rd
, pass
);
4234 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4238 tmp
= neon_load_reg(rd
, pass
);
4239 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4243 tmp
= neon_load_reg(rd
, pass
);
4244 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4250 GEN_NEON_INTEGER_OP(hsub
);
4253 GEN_NEON_INTEGER_OP_ENV(qsub
);
4256 GEN_NEON_INTEGER_OP(cgt
);
4259 GEN_NEON_INTEGER_OP(cge
);
4262 GEN_NEON_INTEGER_OP(shl
);
4265 GEN_NEON_INTEGER_OP_ENV(qshl
);
4267 case 10: /* VRSHL */
4268 GEN_NEON_INTEGER_OP(rshl
);
4270 case 11: /* VQRSHL */
4271 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4274 GEN_NEON_INTEGER_OP(max
);
4277 GEN_NEON_INTEGER_OP(min
);
4280 GEN_NEON_INTEGER_OP(abd
);
4283 GEN_NEON_INTEGER_OP(abd
);
4284 NEON_GET_REG(T1
, rd
, pass
);
4288 if (!u
) { /* VADD */
4289 if (gen_neon_add(size
))
4293 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4294 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4295 case 2: gen_op_subl_T0_T1(); break;
4301 if (!u
) { /* VTST */
4303 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4304 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4305 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4310 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4311 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4312 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4317 case 18: /* Multiply. */
4319 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4320 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4321 case 2: gen_op_mul_T0_T1(); break;
4324 NEON_GET_REG(T1
, rd
, pass
);
4332 if (u
) { /* polynomial */
4333 gen_helper_neon_mul_p8(CPU_T001
);
4334 } else { /* Integer */
4336 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4337 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4338 case 2: gen_op_mul_T0_T1(); break;
4343 case 20: /* VPMAX */
4344 GEN_NEON_INTEGER_OP(pmax
);
4346 case 21: /* VPMIN */
4347 GEN_NEON_INTEGER_OP(pmin
);
4349 case 22: /* Hultiply high. */
4350 if (!u
) { /* VQDMULH */
4352 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4353 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4356 } else { /* VQRDHMUL */
4358 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4359 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4364 case 23: /* VPADD */
4368 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4369 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4370 case 2: gen_op_addl_T0_T1(); break;
4374 case 26: /* Floating point arithnetic. */
4375 switch ((u
<< 2) | size
) {
4377 gen_helper_neon_add_f32(CPU_T001
);
4380 gen_helper_neon_sub_f32(CPU_T001
);
4383 gen_helper_neon_add_f32(CPU_T001
);
4386 gen_helper_neon_abd_f32(CPU_T001
);
4392 case 27: /* Float multiply. */
4393 gen_helper_neon_mul_f32(CPU_T001
);
4395 NEON_GET_REG(T1
, rd
, pass
);
4397 gen_helper_neon_add_f32(CPU_T001
);
4399 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4403 case 28: /* Float compare. */
4405 gen_helper_neon_ceq_f32(CPU_T001
);
4408 gen_helper_neon_cge_f32(CPU_T001
);
4410 gen_helper_neon_cgt_f32(CPU_T001
);
4413 case 29: /* Float compare absolute. */
4417 gen_helper_neon_acge_f32(CPU_T001
);
4419 gen_helper_neon_acgt_f32(CPU_T001
);
4421 case 30: /* Float min/max. */
4423 gen_helper_neon_max_f32(CPU_T001
);
4425 gen_helper_neon_min_f32(CPU_T001
);
4429 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4431 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4436 /* Save the result. For elementwise operations we can put it
4437 straight into the destination register. For pairwise operations
4438 we have to be careful to avoid clobbering the source operands. */
4439 if (pairwise
&& rd
== rm
) {
4440 gen_neon_movl_scratch_T0(pass
);
4442 NEON_SET_REG(T0
, rd
, pass
);
4446 if (pairwise
&& rd
== rm
) {
4447 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4448 gen_neon_movl_T0_scratch(pass
);
4449 NEON_SET_REG(T0
, rd
, pass
);
4452 /* End of 3 register same size operations. */
4453 } else if (insn
& (1 << 4)) {
4454 if ((insn
& 0x00380080) != 0) {
4455 /* Two registers and shift. */
4456 op
= (insn
>> 8) & 0xf;
4457 if (insn
& (1 << 7)) {
4462 while ((insn
& (1 << (size
+ 19))) == 0)
4465 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4466 /* To avoid excessive dumplication of ops we implement shift
4467 by immediate using the variable shift operations. */
4469 /* Shift by immediate:
4470 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4471 /* Right shifts are encoded as N - shift, where N is the
4472 element size in bits. */
4474 shift
= shift
- (1 << (size
+ 3));
4482 imm
= (uint8_t) shift
;
4487 imm
= (uint16_t) shift
;
4498 for (pass
= 0; pass
< count
; pass
++) {
4500 neon_load_reg64(cpu_V0
, rm
+ pass
);
4501 tcg_gen_movi_i64(cpu_V1
, imm
);
4506 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4508 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4513 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4515 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4520 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4522 case 5: /* VSHL, VSLI */
4523 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4527 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4529 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4531 case 7: /* VQSHLU */
4532 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4535 if (op
== 1 || op
== 3) {
4537 neon_load_reg64(cpu_V0
, rd
+ pass
);
4538 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4539 } else if (op
== 4 || (op
== 5 && u
)) {
4541 cpu_abort(env
, "VS[LR]I.64 not implemented");
4543 neon_store_reg64(cpu_V0
, rd
+ pass
);
4544 } else { /* size < 3 */
4545 /* Operands in T0 and T1. */
4546 gen_op_movl_T1_im(imm
);
4547 NEON_GET_REG(T0
, rm
, pass
);
4551 GEN_NEON_INTEGER_OP(shl
);
4555 GEN_NEON_INTEGER_OP(rshl
);
4560 GEN_NEON_INTEGER_OP(shl
);
4562 case 5: /* VSHL, VSLI */
4564 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4565 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4566 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4571 GEN_NEON_INTEGER_OP_ENV(qshl
);
4573 case 7: /* VQSHLU */
4575 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4576 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4577 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4583 if (op
== 1 || op
== 3) {
4585 NEON_GET_REG(T1
, rd
, pass
);
4587 } else if (op
== 4 || (op
== 5 && u
)) {
4592 imm
= 0xff >> -shift
;
4594 imm
= (uint8_t)(0xff << shift
);
4600 imm
= 0xffff >> -shift
;
4602 imm
= (uint16_t)(0xffff << shift
);
4607 imm
= 0xffffffffu
>> -shift
;
4609 imm
= 0xffffffffu
<< shift
;
4614 tmp
= neon_load_reg(rd
, pass
);
4615 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4616 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4617 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4619 NEON_SET_REG(T0
, rd
, pass
);
4622 } else if (op
< 10) {
4623 /* Shift by immediate and narrow:
4624 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4625 shift
= shift
- (1 << (size
+ 3));
4629 imm
= (uint16_t)shift
;
4631 tmp2
= tcg_const_i32(imm
);
4634 imm
= (uint32_t)shift
;
4635 tmp2
= tcg_const_i32(imm
);
4637 tmp2
= tcg_const_i64(shift
);
4643 for (pass
= 0; pass
< 2; pass
++) {
4645 neon_load_reg64(cpu_V0
, rm
+ pass
);
4648 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp2
);
4650 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp2
);
4653 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp2
);
4655 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp2
);
4658 tmp
= neon_load_reg(rm
+ pass
, 0);
4659 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4660 tcg_gen_extu_i32_i64(cpu_V0
, tmp
);
4662 tmp
= neon_load_reg(rm
+ pass
, 1);
4663 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4664 tcg_gen_extu_i32_i64(cpu_V1
, tmp
);
4666 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 32);
4667 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4670 if (op
== 8 && !u
) {
4671 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4674 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4676 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4681 neon_store_reg(rd
, 0, tmp2
);
4682 neon_store_reg(rd
, 1, tmp
);
4685 } else if (op
== 10) {
4689 tmp
= neon_load_reg(rm
, 0);
4690 tmp2
= neon_load_reg(rm
, 1);
4691 for (pass
= 0; pass
< 2; pass
++) {
4695 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4698 /* The shift is less than the width of the source
4699 type, so we can just shift the whole register. */
4700 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4701 if (size
< 2 || !u
) {
4704 imm
= (0xffu
>> (8 - shift
));
4707 imm
= 0xffff >> (16 - shift
);
4709 imm64
= imm
| (((uint64_t)imm
) << 32);
4710 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4713 neon_store_reg64(cpu_V0
, rd
+ pass
);
4715 } else if (op
== 15 || op
== 16) {
4716 /* VCVT fixed-point. */
4717 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4718 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4721 gen_vfp_ulto(0, shift
);
4723 gen_vfp_slto(0, shift
);
4726 gen_vfp_toul(0, shift
);
4728 gen_vfp_tosl(0, shift
);
4730 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4735 } else { /* (insn & 0x00380080) == 0 */
4738 op
= (insn
>> 8) & 0xf;
4739 /* One register and immediate. */
4740 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4741 invert
= (insn
& (1 << 5)) != 0;
4759 imm
= (imm
<< 8) | (imm
<< 24);
4762 imm
= (imm
< 8) | 0xff;
4765 imm
= (imm
<< 16) | 0xffff;
4768 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4773 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4774 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4780 if (op
!= 14 || !invert
)
4781 gen_op_movl_T1_im(imm
);
4783 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4784 if (op
& 1 && op
< 12) {
4785 tmp
= neon_load_reg(rd
, pass
);
4787 /* The immediate value has already been inverted, so
4789 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4791 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4796 if (op
== 14 && invert
) {
4799 for (n
= 0; n
< 4; n
++) {
4800 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4801 val
|= 0xff << (n
* 8);
4803 tcg_gen_movi_i32(tmp
, val
);
4805 tcg_gen_movi_i32(tmp
, imm
);
4808 neon_store_reg(rd
, pass
, tmp
);
4811 } else { /* (insn & 0x00800010 == 0x00800010) */
4813 op
= (insn
>> 8) & 0xf;
4814 if ((insn
& (1 << 6)) == 0) {
4815 /* Three registers of different lengths. */
4819 /* prewiden, src1_wide, src2_wide */
4820 static const int neon_3reg_wide
[16][3] = {
4821 {1, 0, 0}, /* VADDL */
4822 {1, 1, 0}, /* VADDW */
4823 {1, 0, 0}, /* VSUBL */
4824 {1, 1, 0}, /* VSUBW */
4825 {0, 1, 1}, /* VADDHN */
4826 {0, 0, 0}, /* VABAL */
4827 {0, 1, 1}, /* VSUBHN */
4828 {0, 0, 0}, /* VABDL */
4829 {0, 0, 0}, /* VMLAL */
4830 {0, 0, 0}, /* VQDMLAL */
4831 {0, 0, 0}, /* VMLSL */
4832 {0, 0, 0}, /* VQDMLSL */
4833 {0, 0, 0}, /* Integer VMULL */
4834 {0, 0, 0}, /* VQDMULL */
4835 {0, 0, 0} /* Polynomial VMULL */
4838 prewiden
= neon_3reg_wide
[op
][0];
4839 src1_wide
= neon_3reg_wide
[op
][1];
4840 src2_wide
= neon_3reg_wide
[op
][2];
4842 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4845 /* Avoid overlapping operands. Wide source operands are
4846 always aligned so will never overlap with wide
4847 destinations in problematic ways. */
4848 if (rd
== rm
&& !src2_wide
) {
4849 NEON_GET_REG(T0
, rm
, 1);
4850 gen_neon_movl_scratch_T0(2);
4851 } else if (rd
== rn
&& !src1_wide
) {
4852 NEON_GET_REG(T0
, rn
, 1);
4853 gen_neon_movl_scratch_T0(2);
4855 for (pass
= 0; pass
< 2; pass
++) {
4857 neon_load_reg64(cpu_V0
, rn
+ pass
);
4859 if (pass
== 1 && rd
== rn
) {
4860 gen_neon_movl_T0_scratch(2);
4862 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4864 tmp
= neon_load_reg(rn
, pass
);
4867 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4871 neon_load_reg64(cpu_V1
, rm
+ pass
);
4873 if (pass
== 1 && rd
== rm
) {
4874 gen_neon_movl_T0_scratch(2);
4876 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4878 tmp2
= neon_load_reg(rm
, pass
);
4881 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4885 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4886 gen_neon_addl(size
);
4888 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4889 gen_neon_subl(size
);
4891 case 5: case 7: /* VABAL, VABDL */
4892 switch ((size
<< 1) | u
) {
4894 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4897 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4900 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4903 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4906 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4909 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4916 case 8: case 9: case 10: case 11: case 12: case 13:
4917 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4918 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4920 case 14: /* Polynomial VMULL */
4921 cpu_abort(env
, "Polynomial VMULL not implemented");
4923 default: /* 15 is RESERVED. */
4926 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4928 if (op
== 10 || op
== 11) {
4929 gen_neon_negl(cpu_V0
, size
);
4933 neon_load_reg64(cpu_V1
, rd
+ pass
);
4937 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4938 gen_neon_addl(size
);
4940 case 9: case 11: /* VQDMLAL, VQDMLSL */
4941 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4942 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4945 case 13: /* VQDMULL */
4946 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4951 neon_store_reg64(cpu_V0
, rd
+ pass
);
4952 } else if (op
== 4 || op
== 6) {
4953 /* Narrowing operation. */
4958 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4961 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4964 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4965 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4972 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4975 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4978 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4979 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4980 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4988 neon_store_reg(rd
, 0, tmp3
);
4989 neon_store_reg(rd
, 1, tmp
);
4992 /* Write back the result. */
4993 neon_store_reg64(cpu_V0
, rd
+ pass
);
4997 /* Two registers and a scalar. */
4999 case 0: /* Integer VMLA scalar */
5000 case 1: /* Float VMLA scalar */
5001 case 4: /* Integer VMLS scalar */
5002 case 5: /* Floating point VMLS scalar */
5003 case 8: /* Integer VMUL scalar */
5004 case 9: /* Floating point VMUL scalar */
5005 case 12: /* VQDMULH scalar */
5006 case 13: /* VQRDMULH scalar */
5007 gen_neon_get_scalar(size
, rm
);
5008 gen_neon_movl_scratch_T0(0);
5009 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5011 gen_neon_movl_T0_scratch(0);
5012 NEON_GET_REG(T1
, rn
, pass
);
5015 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5017 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5019 } else if (op
== 13) {
5021 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5023 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5025 } else if (op
& 1) {
5026 gen_helper_neon_mul_f32(CPU_T001
);
5029 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5030 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5031 case 2: gen_op_mul_T0_T1(); break;
5037 NEON_GET_REG(T1
, rd
, pass
);
5043 gen_helper_neon_add_f32(CPU_T001
);
5049 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5055 NEON_SET_REG(T0
, rd
, pass
);
5058 case 2: /* VMLAL sclar */
5059 case 3: /* VQDMLAL scalar */
5060 case 6: /* VMLSL scalar */
5061 case 7: /* VQDMLSL scalar */
5062 case 10: /* VMULL scalar */
5063 case 11: /* VQDMULL scalar */
5064 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5067 gen_neon_get_scalar(size
, rm
);
5068 NEON_GET_REG(T1
, rn
, 1);
5070 for (pass
= 0; pass
< 2; pass
++) {
5072 tmp
= neon_load_reg(rn
, 0);
5075 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5078 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5079 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5080 if (op
== 6 || op
== 7) {
5081 gen_neon_negl(cpu_V0
, size
);
5084 neon_load_reg64(cpu_V1
, rd
+ pass
);
5088 gen_neon_addl(size
);
5091 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5092 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5098 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5103 neon_store_reg64(cpu_V0
, rd
+ pass
);
5106 default: /* 14 and 15 are RESERVED */
5110 } else { /* size == 3 */
5113 imm
= (insn
>> 8) & 0xf;
5120 neon_load_reg64(cpu_V0
, rn
);
5122 neon_load_reg64(cpu_V1
, rn
+ 1);
5124 } else if (imm
== 8) {
5125 neon_load_reg64(cpu_V0
, rn
+ 1);
5127 neon_load_reg64(cpu_V1
, rm
);
5130 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5132 neon_load_reg64(cpu_V0
, rn
);
5133 neon_load_reg64(tmp
, rn
+ 1);
5135 neon_load_reg64(cpu_V0
, rn
+ 1);
5136 neon_load_reg64(tmp
, rm
);
5138 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5139 tcg_gen_shli_i64(cpu_V1
, tmp
, 64 - ((imm
& 7) * 8));
5140 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5142 neon_load_reg64(cpu_V1
, rm
);
5144 neon_load_reg64(cpu_V1
, rm
+ 1);
5147 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5148 tcg_gen_shri_i64(tmp
, tmp
, imm
* 8);
5149 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp
);
5151 neon_load_reg64(cpu_V0
, rn
);
5152 tcg_gen_shri_i32(cpu_V0
, cpu_V0
, imm
* 8);
5153 neon_load_reg64(cpu_V1
, rm
);
5154 tcg_gen_shli_i32(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5155 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5157 neon_store_reg64(cpu_V0
, rd
);
5159 neon_store_reg64(cpu_V1
, rd
+ 1);
5161 } else if ((insn
& (1 << 11)) == 0) {
5162 /* Two register misc. */
5163 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5164 size
= (insn
>> 18) & 3;
5166 case 0: /* VREV64 */
5169 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5170 NEON_GET_REG(T0
, rm
, pass
* 2);
5171 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5173 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5174 case 1: gen_swap_half(cpu_T
[0]); break;
5175 case 2: /* no-op */ break;
5178 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5180 NEON_SET_REG(T1
, rd
, pass
* 2);
5182 gen_op_movl_T0_T1();
5184 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5185 case 1: gen_swap_half(cpu_T
[0]); break;
5188 NEON_SET_REG(T0
, rd
, pass
* 2);
5192 case 4: case 5: /* VPADDL */
5193 case 12: case 13: /* VPADAL */
5196 for (pass
= 0; pass
< q
+ 1; pass
++) {
5197 tmp
= neon_load_reg(rm
, pass
* 2);
5198 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5199 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5200 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5202 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5203 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5204 case 2: tcg_gen_add_i64(CPU_V001
); break;
5209 neon_load_reg64(cpu_V1
, rd
+ pass
);
5210 gen_neon_addl(size
);
5212 neon_store_reg64(cpu_V0
, rd
+ pass
);
5217 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5218 NEON_GET_REG(T0
, rm
, n
);
5219 NEON_GET_REG(T1
, rd
, n
+ 1);
5220 NEON_SET_REG(T1
, rm
, n
);
5221 NEON_SET_REG(T0
, rd
, n
+ 1);
5229 Rd A3 A2 A1 A0 B2 B0 A2 A0
5230 Rm B3 B2 B1 B0 B3 B1 A3 A1
5234 gen_neon_unzip(rd
, q
, 0, size
);
5235 gen_neon_unzip(rm
, q
, 4, size
);
5237 static int unzip_order_q
[8] =
5238 {0, 2, 4, 6, 1, 3, 5, 7};
5239 for (n
= 0; n
< 8; n
++) {
5240 int reg
= (n
< 4) ? rd
: rm
;
5241 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5242 NEON_SET_REG(T0
, reg
, n
% 4);
5245 static int unzip_order
[4] =
5247 for (n
= 0; n
< 4; n
++) {
5248 int reg
= (n
< 2) ? rd
: rm
;
5249 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5250 NEON_SET_REG(T0
, reg
, n
% 2);
5256 Rd A3 A2 A1 A0 B1 A1 B0 A0
5257 Rm B3 B2 B1 B0 B3 A3 B2 A2
5261 count
= (q
? 4 : 2);
5262 for (n
= 0; n
< count
; n
++) {
5263 NEON_GET_REG(T0
, rd
, n
);
5264 NEON_GET_REG(T1
, rd
, n
);
5266 case 0: gen_helper_neon_zip_u8(); break;
5267 case 1: gen_helper_neon_zip_u16(); break;
5268 case 2: /* no-op */; break;
5271 gen_neon_movl_scratch_T0(n
* 2);
5272 gen_neon_movl_scratch_T1(n
* 2 + 1);
5274 for (n
= 0; n
< count
* 2; n
++) {
5275 int reg
= (n
< count
) ? rd
: rm
;
5276 gen_neon_movl_T0_scratch(n
);
5277 NEON_SET_REG(T0
, reg
, n
% count
);
5280 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5283 for (pass
= 0; pass
< 2; pass
++) {
5284 neon_load_reg64(cpu_V0
, rm
+ pass
);
5286 if (op
== 36 && q
== 0) {
5287 gen_neon_narrow(size
, tmp
, cpu_V0
);
5289 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5291 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5296 neon_store_reg(rd
, 0, tmp2
);
5297 neon_store_reg(rd
, 1, tmp
);
5301 case 38: /* VSHLL */
5304 tmp
= neon_load_reg(rm
, 0);
5305 tmp2
= neon_load_reg(rm
, 1);
5306 for (pass
= 0; pass
< 2; pass
++) {
5309 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5310 neon_store_reg64(cpu_V0
, rd
+ pass
);
5315 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5316 if (op
== 30 || op
== 31 || op
>= 58) {
5317 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5318 neon_reg_offset(rm
, pass
));
5320 NEON_GET_REG(T0
, rm
, pass
);
5323 case 1: /* VREV32 */
5325 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5326 case 1: gen_swap_half(cpu_T
[0]); break;
5330 case 2: /* VREV16 */
5333 gen_rev16(cpu_T
[0]);
5337 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5338 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5339 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5345 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5346 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5347 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5354 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5361 case 14: /* VQABS */
5363 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5364 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5365 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5369 case 15: /* VQNEG */
5371 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5372 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5373 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5377 case 16: case 19: /* VCGT #0, VCLE #0 */
5378 gen_op_movl_T1_im(0);
5380 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5381 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5382 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5388 case 17: case 20: /* VCGE #0, VCLT #0 */
5389 gen_op_movl_T1_im(0);
5391 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5392 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5393 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5399 case 18: /* VCEQ #0 */
5400 gen_op_movl_T1_im(0);
5402 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5403 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5404 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5410 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5411 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5412 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5417 gen_op_movl_T1_im(0);
5422 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5423 gen_op_movl_T1_im(0);
5424 gen_helper_neon_cgt_f32(CPU_T001
);
5428 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5429 gen_op_movl_T1_im(0);
5430 gen_helper_neon_cge_f32(CPU_T001
);
5434 case 26: /* Float VCEQ #0 */
5435 gen_op_movl_T1_im(0);
5436 gen_helper_neon_ceq_f32(CPU_T001
);
5438 case 30: /* Float VABS */
5441 case 31: /* Float VNEG */
5445 NEON_GET_REG(T1
, rd
, pass
);
5446 NEON_SET_REG(T1
, rm
, pass
);
5449 NEON_GET_REG(T1
, rd
, pass
);
5451 case 0: gen_helper_neon_trn_u8(); break;
5452 case 1: gen_helper_neon_trn_u16(); break;
5456 NEON_SET_REG(T1
, rm
, pass
);
5458 case 56: /* Integer VRECPE */
5459 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5461 case 57: /* Integer VRSQRTE */
5462 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5464 case 58: /* Float VRECPE */
5465 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5467 case 59: /* Float VRSQRTE */
5468 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5470 case 60: /* VCVT.F32.S32 */
5473 case 61: /* VCVT.F32.U32 */
5476 case 62: /* VCVT.S32.F32 */
5479 case 63: /* VCVT.U32.F32 */
5483 /* Reserved: 21, 29, 39-56 */
5486 if (op
== 30 || op
== 31 || op
>= 58) {
5487 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5488 neon_reg_offset(rd
, pass
));
5490 NEON_SET_REG(T0
, rd
, pass
);
5495 } else if ((insn
& (1 << 10)) == 0) {
5497 n
= (insn
>> 5) & 0x18;
5498 if (insn
& (1 << 6)) {
5499 tmp
= neon_load_reg(rd
, 0);
5502 tcg_gen_movi_i32(tmp
, 0);
5504 tmp2
= neon_load_reg(rm
, 0);
5505 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5507 if (insn
& (1 << 6)) {
5508 tmp
= neon_load_reg(rd
, 1);
5511 tcg_gen_movi_i32(tmp
, 0);
5513 tmp3
= neon_load_reg(rm
, 1);
5514 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5516 neon_store_reg(rd
, 0, tmp2
);
5517 neon_store_reg(rd
, 1, tmp2
);
5518 } else if ((insn
& 0x380) == 0) {
5520 if (insn
& (1 << 19)) {
5521 NEON_SET_REG(T0
, rm
, 1);
5523 NEON_SET_REG(T0
, rm
, 0);
5525 if (insn
& (1 << 16)) {
5526 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5527 } else if (insn
& (1 << 17)) {
5528 if ((insn
>> 18) & 1)
5529 gen_neon_dup_high16(cpu_T
[0]);
5531 gen_neon_dup_low16(cpu_T
[0]);
5533 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5534 NEON_SET_REG(T0
, rd
, pass
);
5544 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5548 cpnum
= (insn
>> 8) & 0xf;
5549 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5550 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5556 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5557 return disas_iwmmxt_insn(env
, s
, insn
);
5558 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5559 return disas_dsp_insn(env
, s
, insn
);
5564 return disas_vfp_insn (env
, s
, insn
);
5566 return disas_cp15_insn (env
, s
, insn
);
5568 /* Unknown coprocessor. See if the board has hooked it. */
5569 return disas_cp_insn (env
, s
, insn
);
5574 /* Store a 64-bit value to a register pair. Clobbers val. */
5575 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv val
)
5579 tcg_gen_trunc_i64_i32(tmp
, val
);
5580 store_reg(s
, rlow
, tmp
);
5582 tcg_gen_shri_i64(val
, val
, 32);
5583 tcg_gen_trunc_i64_i32(tmp
, val
);
5584 store_reg(s
, rhigh
, tmp
);
5587 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5588 static void gen_addq_lo(DisasContext
*s
, TCGv val
, int rlow
)
5593 /* Load 64-bit value rd:rn. */
5594 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5595 tmp2
= load_reg(s
, rlow
);
5596 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5598 tcg_gen_add_i64(val
, val
, tmp
);
5601 /* load and add a 64-bit value from a register pair. */
5602 static void gen_addq(DisasContext
*s
, TCGv val
, int rlow
, int rhigh
)
5607 /* Load 64-bit value rd:rn. */
5608 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5609 tmp2
= load_reg(s
, rhigh
);
5610 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5612 tcg_gen_shli_i64(tmp
, tmp
, 32);
5613 tcg_gen_add_i64(val
, val
, tmp
);
5615 tmp2
= load_reg(s
, rlow
);
5616 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5618 tcg_gen_add_i64(val
, val
, tmp
);
5621 /* Set N and Z flags from a 64-bit value. */
5622 static void gen_logicq_cc(TCGv val
)
5624 TCGv tmp
= new_tmp();
5625 gen_helper_logicq_cc(tmp
, val
);
5630 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5632 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5638 insn
= ldl_code(s
->pc
);
5641 /* M variants do not implement ARM mode. */
5646 /* Unconditional instructions. */
5647 if (((insn
>> 25) & 7) == 1) {
5648 /* NEON Data processing. */
5649 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5652 if (disas_neon_data_insn(env
, s
, insn
))
5656 if ((insn
& 0x0f100000) == 0x04000000) {
5657 /* NEON load/store. */
5658 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5661 if (disas_neon_ls_insn(env
, s
, insn
))
5665 if ((insn
& 0x0d70f000) == 0x0550f000)
5667 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5670 if (insn
& (1 << 9)) {
5671 /* BE8 mode not implemented. */
5675 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5676 switch ((insn
>> 4) & 0xf) {
5679 gen_helper_clrex(cpu_env
);
5685 /* We don't emulate caches so these are a no-op. */
5690 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5696 op1
= (insn
& 0x1f);
5697 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5698 addr
= load_reg(s
, 13);
5701 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5703 i
= (insn
>> 23) & 3;
5705 case 0: offset
= -4; break; /* DA */
5706 case 1: offset
= -8; break; /* DB */
5707 case 2: offset
= 0; break; /* IA */
5708 case 3: offset
= 4; break; /* IB */
5712 tcg_gen_addi_i32(addr
, addr
, offset
);
5713 tmp
= load_reg(s
, 14);
5714 gen_st32(tmp
, addr
, 0);
5716 gen_helper_cpsr_read(tmp
);
5717 tcg_gen_addi_i32(addr
, addr
, 4);
5718 gen_st32(tmp
, addr
, 0);
5719 if (insn
& (1 << 21)) {
5720 /* Base writeback. */
5722 case 0: offset
= -8; break;
5723 case 1: offset
= -4; break;
5724 case 2: offset
= 4; break;
5725 case 3: offset
= 0; break;
5729 tcg_gen_addi_i32(addr
, tmp
, offset
);
5730 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5731 gen_movl_reg_T1(s
, 13);
5733 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5738 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5744 rn
= (insn
>> 16) & 0xf;
5745 addr
= load_reg(s
, rn
);
5746 i
= (insn
>> 23) & 3;
5748 case 0: offset
= -4; break; /* DA */
5749 case 1: offset
= -8; break; /* DB */
5750 case 2: offset
= 0; break; /* IA */
5751 case 3: offset
= 4; break; /* IB */
5755 tcg_gen_addi_i32(addr
, addr
, offset
);
5756 /* Load PC into tmp and CPSR into tmp2. */
5757 tmp
= gen_ld32(addr
, 0);
5758 tcg_gen_addi_i32(addr
, addr
, 4);
5759 tmp2
= gen_ld32(addr
, 0);
5760 if (insn
& (1 << 21)) {
5761 /* Base writeback. */
5763 case 0: offset
= -8; break;
5764 case 1: offset
= -4; break;
5765 case 2: offset
= 4; break;
5766 case 3: offset
= 0; break;
5770 tcg_gen_addi_i32(addr
, addr
, offset
);
5771 store_reg(s
, rn
, addr
);
5775 gen_rfe(s
, tmp
, tmp2
);
5776 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5777 /* branch link and change to thumb (blx <offset>) */
5780 val
= (uint32_t)s
->pc
;
5782 tcg_gen_movi_i32(tmp
, val
);
5783 store_reg(s
, 14, tmp
);
5784 /* Sign-extend the 24-bit offset */
5785 offset
= (((int32_t)insn
) << 8) >> 8;
5786 /* offset * 4 + bit24 * 2 + (thumb bit) */
5787 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5788 /* pipeline offset */
5792 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5793 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5794 /* iWMMXt register transfer. */
5795 if (env
->cp15
.c15_cpar
& (1 << 1))
5796 if (!disas_iwmmxt_insn(env
, s
, insn
))
5799 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5800 /* Coprocessor double register transfer. */
5801 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5802 /* Additional coprocessor register transfer. */
5803 } else if ((insn
& 0x0ff10010) == 0x01000000) {
5806 /* cps (privileged) */
5810 if (insn
& (1 << 19)) {
5811 if (insn
& (1 << 8))
5813 if (insn
& (1 << 7))
5815 if (insn
& (1 << 6))
5817 if (insn
& (1 << 18))
5820 if (insn
& (1 << 14)) {
5822 val
|= (insn
& 0x1f);
5825 gen_op_movl_T0_im(val
);
5826 gen_set_psr_T0(s
, mask
, 0);
5833 /* if not always execute, we generate a conditional jump to
5835 s
->condlabel
= gen_new_label();
5836 gen_test_cc(cond
^ 1, s
->condlabel
);
5839 if ((insn
& 0x0f900000) == 0x03000000) {
5840 if ((insn
& (1 << 21)) == 0) {
5842 rd
= (insn
>> 12) & 0xf;
5843 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5844 if ((insn
& (1 << 22)) == 0) {
5847 tcg_gen_movi_i32(tmp
, val
);
5850 tmp
= load_reg(s
, rd
);
5851 tcg_gen_ext16u_i32(tmp
, tmp
);
5852 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5854 store_reg(s
, rd
, tmp
);
5856 if (((insn
>> 12) & 0xf) != 0xf)
5858 if (((insn
>> 16) & 0xf) == 0) {
5859 gen_nop_hint(s
, insn
& 0xff);
5861 /* CPSR = immediate */
5863 shift
= ((insn
>> 8) & 0xf) * 2;
5865 val
= (val
>> shift
) | (val
<< (32 - shift
));
5866 gen_op_movl_T0_im(val
);
5867 i
= ((insn
& (1 << 22)) != 0);
5868 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5872 } else if ((insn
& 0x0f900000) == 0x01000000
5873 && (insn
& 0x00000090) != 0x00000090) {
5874 /* miscellaneous instructions */
5875 op1
= (insn
>> 21) & 3;
5876 sh
= (insn
>> 4) & 0xf;
5879 case 0x0: /* move program status register */
5882 gen_movl_T0_reg(s
, rm
);
5883 i
= ((op1
& 2) != 0);
5884 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5888 rd
= (insn
>> 12) & 0xf;
5892 tmp
= load_cpu_field(spsr
);
5895 gen_helper_cpsr_read(tmp
);
5897 store_reg(s
, rd
, tmp
);
5902 /* branch/exchange thumb (bx). */
5903 tmp
= load_reg(s
, rm
);
5905 } else if (op1
== 3) {
5907 rd
= (insn
>> 12) & 0xf;
5908 tmp
= load_reg(s
, rm
);
5909 gen_helper_clz(tmp
, tmp
);
5910 store_reg(s
, rd
, tmp
);
5918 /* Trivial implementation equivalent to bx. */
5919 tmp
= load_reg(s
, rm
);
5929 /* branch link/exchange thumb (blx) */
5930 tmp
= load_reg(s
, rm
);
5932 tcg_gen_movi_i32(tmp2
, s
->pc
);
5933 store_reg(s
, 14, tmp2
);
5936 case 0x5: /* saturating add/subtract */
5937 rd
= (insn
>> 12) & 0xf;
5938 rn
= (insn
>> 16) & 0xf;
5939 tmp
= load_reg(s
, rn
);
5940 tmp2
= load_reg(s
, rn
);
5942 gen_helper_double_saturate(tmp2
, tmp2
);
5944 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
5946 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
5948 store_reg(s
, rd
, tmp
);
5951 gen_set_condexec(s
);
5952 gen_set_pc_im(s
->pc
- 4);
5953 gen_exception(EXCP_BKPT
);
5954 s
->is_jmp
= DISAS_JUMP
;
5956 case 0x8: /* signed multiply */
5960 rs
= (insn
>> 8) & 0xf;
5961 rn
= (insn
>> 12) & 0xf;
5962 rd
= (insn
>> 16) & 0xf;
5964 /* (32 * 16) >> 16 */
5965 tmp
= load_reg(s
, rm
);
5966 tmp2
= load_reg(s
, rs
);
5968 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
5971 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
5972 tcg_gen_shri_i64(tmp2
, tmp2
, 16);
5974 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
5975 if ((sh
& 2) == 0) {
5976 tmp2
= load_reg(s
, rn
);
5977 gen_helper_add_setq(tmp
, tmp
, tmp2
);
5980 store_reg(s
, rd
, tmp
);
5983 tmp
= load_reg(s
, rm
);
5984 tmp2
= load_reg(s
, rs
);
5985 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
5988 tmp
= tcg_temp_new(TCG_TYPE_I64
);
5989 tcg_gen_ext_i32_i64(tmp
, cpu_T
[0]);
5990 gen_addq(s
, tmp
, rn
, rd
);
5991 gen_storeq_reg(s
, rn
, rd
, tmp
);
5994 tmp2
= load_reg(s
, rn
);
5995 gen_helper_add_setq(tmp
, tmp
, tmp2
);
5998 store_reg(s
, rd
, tmp
);
6005 } else if (((insn
& 0x0e000000) == 0 &&
6006 (insn
& 0x00000090) != 0x90) ||
6007 ((insn
& 0x0e000000) == (1 << 25))) {
6008 int set_cc
, logic_cc
, shiftop
;
6010 op1
= (insn
>> 21) & 0xf;
6011 set_cc
= (insn
>> 20) & 1;
6012 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6014 /* data processing instruction */
6015 if (insn
& (1 << 25)) {
6016 /* immediate operand */
6018 shift
= ((insn
>> 8) & 0xf) * 2;
6020 val
= (val
>> shift
) | (val
<< (32 - shift
));
6021 gen_op_movl_T1_im(val
);
6022 if (logic_cc
&& shift
)
6023 gen_set_CF_bit31(cpu_T
[1]);
6027 gen_movl_T1_reg(s
, rm
);
6028 shiftop
= (insn
>> 5) & 3;
6029 if (!(insn
& (1 << 4))) {
6030 shift
= (insn
>> 7) & 0x1f;
6031 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
6033 rs
= (insn
>> 8) & 0xf;
6034 tmp
= load_reg(s
, rs
);
6035 gen_arm_shift_reg(cpu_T
[1], shiftop
, tmp
, logic_cc
);
6038 if (op1
!= 0x0f && op1
!= 0x0d) {
6039 rn
= (insn
>> 16) & 0xf;
6040 gen_movl_T0_reg(s
, rn
);
6042 rd
= (insn
>> 12) & 0xf;
6045 gen_op_andl_T0_T1();
6046 gen_movl_reg_T0(s
, rd
);
6048 gen_op_logic_T0_cc();
6051 gen_op_xorl_T0_T1();
6052 gen_movl_reg_T0(s
, rd
);
6054 gen_op_logic_T0_cc();
6057 if (set_cc
&& rd
== 15) {
6058 /* SUBS r15, ... is used for exception return. */
6061 gen_op_subl_T0_T1_cc();
6062 gen_exception_return(s
);
6065 gen_op_subl_T0_T1_cc();
6067 gen_op_subl_T0_T1();
6068 gen_movl_reg_T0(s
, rd
);
6073 gen_op_rsbl_T0_T1_cc();
6075 gen_op_rsbl_T0_T1();
6076 gen_movl_reg_T0(s
, rd
);
6080 gen_op_addl_T0_T1_cc();
6082 gen_op_addl_T0_T1();
6083 gen_movl_reg_T0(s
, rd
);
6087 gen_op_adcl_T0_T1_cc();
6090 gen_movl_reg_T0(s
, rd
);
6094 gen_op_sbcl_T0_T1_cc();
6097 gen_movl_reg_T0(s
, rd
);
6101 gen_op_rscl_T0_T1_cc();
6104 gen_movl_reg_T0(s
, rd
);
6108 gen_op_andl_T0_T1();
6109 gen_op_logic_T0_cc();
6114 gen_op_xorl_T0_T1();
6115 gen_op_logic_T0_cc();
6120 gen_op_subl_T0_T1_cc();
6125 gen_op_addl_T0_T1_cc();
6130 gen_movl_reg_T0(s
, rd
);
6132 gen_op_logic_T0_cc();
6135 if (logic_cc
&& rd
== 15) {
6136 /* MOVS r15, ... is used for exception return. */
6139 gen_op_movl_T0_T1();
6140 gen_exception_return(s
);
6142 gen_movl_reg_T1(s
, rd
);
6144 gen_op_logic_T1_cc();
6148 gen_op_bicl_T0_T1();
6149 gen_movl_reg_T0(s
, rd
);
6151 gen_op_logic_T0_cc();
6156 gen_movl_reg_T1(s
, rd
);
6158 gen_op_logic_T1_cc();
6162 /* other instructions */
6163 op1
= (insn
>> 24) & 0xf;
6167 /* multiplies, extra load/stores */
6168 sh
= (insn
>> 5) & 3;
6171 rd
= (insn
>> 16) & 0xf;
6172 rn
= (insn
>> 12) & 0xf;
6173 rs
= (insn
>> 8) & 0xf;
6175 op1
= (insn
>> 20) & 0xf;
6177 case 0: case 1: case 2: case 3: case 6:
6179 tmp
= load_reg(s
, rs
);
6180 tmp2
= load_reg(s
, rm
);
6181 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6183 if (insn
& (1 << 22)) {
6184 /* Subtract (mls) */
6186 tmp2
= load_reg(s
, rn
);
6187 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6189 } else if (insn
& (1 << 21)) {
6191 tmp2
= load_reg(s
, rn
);
6192 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6195 if (insn
& (1 << 20))
6197 store_reg(s
, rd
, tmp
);
6201 tmp
= load_reg(s
, rs
);
6202 tmp2
= load_reg(s
, rm
);
6203 if (insn
& (1 << 22))
6204 tmp
= gen_muls_i64_i32(tmp
, tmp2
);
6206 tmp
= gen_mulu_i64_i32(tmp
, tmp2
);
6207 if (insn
& (1 << 21)) /* mult accumulate */
6208 gen_addq(s
, tmp
, rn
, rd
);
6209 if (!(insn
& (1 << 23))) { /* double accumulate */
6211 gen_addq_lo(s
, tmp
, rn
);
6212 gen_addq_lo(s
, tmp
, rd
);
6214 if (insn
& (1 << 20))
6216 gen_storeq_reg(s
, rn
, rd
, tmp
);
6220 rn
= (insn
>> 16) & 0xf;
6221 rd
= (insn
>> 12) & 0xf;
6222 if (insn
& (1 << 23)) {
6223 /* load/store exclusive */
6224 gen_movl_T1_reg(s
, rn
);
6226 if (insn
& (1 << 20)) {
6227 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6228 tmp
= gen_ld32(addr
, IS_USER(s
));
6229 store_reg(s
, rd
, tmp
);
6231 int label
= gen_new_label();
6233 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6234 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6236 tmp
= load_reg(s
,rm
);
6237 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
6238 gen_set_label(label
);
6239 gen_movl_reg_T0(s
, rd
);
6242 /* SWP instruction */
6245 /* ??? This is not really atomic. However we know
6246 we never have multiple CPUs running in parallel,
6247 so it is good enough. */
6248 addr
= load_reg(s
, rn
);
6249 tmp
= load_reg(s
, rm
);
6250 if (insn
& (1 << 22)) {
6251 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6252 gen_st8(tmp
, addr
, IS_USER(s
));
6254 tmp2
= gen_ld32(addr
, IS_USER(s
));
6255 gen_st32(tmp
, addr
, IS_USER(s
));
6258 store_reg(s
, rd
, tmp2
);
6264 /* Misc load/store */
6265 rn
= (insn
>> 16) & 0xf;
6266 rd
= (insn
>> 12) & 0xf;
6267 addr
= load_reg(s
, rn
);
6268 if (insn
& (1 << 24))
6269 gen_add_datah_offset(s
, insn
, 0, addr
);
6271 if (insn
& (1 << 20)) {
6275 tmp
= gen_ld16u(addr
, IS_USER(s
));
6278 tmp
= gen_ld8s(addr
, IS_USER(s
));
6282 tmp
= gen_ld16s(addr
, IS_USER(s
));
6286 } else if (sh
& 2) {
6290 tmp
= load_reg(s
, rd
);
6291 gen_st32(tmp
, addr
, IS_USER(s
));
6292 tcg_gen_addi_i32(addr
, addr
, 4);
6293 tmp
= load_reg(s
, rd
+ 1);
6294 gen_st32(tmp
, addr
, IS_USER(s
));
6298 tmp
= gen_ld32(addr
, IS_USER(s
));
6299 store_reg(s
, rd
, tmp
);
6300 tcg_gen_addi_i32(addr
, addr
, 4);
6301 tmp
= gen_ld32(addr
, IS_USER(s
));
6305 address_offset
= -4;
6308 tmp
= load_reg(s
, rd
);
6309 gen_st16(tmp
, addr
, IS_USER(s
));
6312 /* Perform base writeback before the loaded value to
6313 ensure correct behavior with overlapping index registers.
6314 ldrd with base writeback is is undefined if the
6315 destination and index registers overlap. */
6316 if (!(insn
& (1 << 24))) {
6317 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6318 store_reg(s
, rn
, addr
);
6319 } else if (insn
& (1 << 21)) {
6321 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6322 store_reg(s
, rn
, addr
);
6327 /* Complete the load. */
6328 store_reg(s
, rd
, tmp
);
6337 if (insn
& (1 << 4)) {
6339 /* Armv6 Media instructions. */
6341 rn
= (insn
>> 16) & 0xf;
6342 rd
= (insn
>> 12) & 0xf;
6343 rs
= (insn
>> 8) & 0xf;
6344 switch ((insn
>> 23) & 3) {
6345 case 0: /* Parallel add/subtract. */
6346 op1
= (insn
>> 20) & 7;
6347 tmp
= load_reg(s
, rn
);
6348 tmp2
= load_reg(s
, rm
);
6349 sh
= (insn
>> 5) & 7;
6350 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6352 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6354 store_reg(s
, rd
, tmp
);
6357 if ((insn
& 0x00700020) == 0) {
6358 /* Halfword pack. */
6359 tmp
= load_reg(s
, rn
);
6360 tmp2
= load_reg(s
, rm
);
6361 shift
= (insn
>> 7) & 0x1f;
6363 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6364 if (insn
& (1 << 6)) {
6366 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6367 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6370 tcg_gen_ext16u_i32(tmp
, tmp
);
6371 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6373 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6374 store_reg(s
, rd
, tmp
);
6375 } else if ((insn
& 0x00200020) == 0x00200000) {
6377 tmp
= load_reg(s
, rm
);
6378 shift
= (insn
>> 7) & 0x1f;
6379 if (insn
& (1 << 6)) {
6382 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6384 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6386 sh
= (insn
>> 16) & 0x1f;
6388 if (insn
& (1 << 22))
6389 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6391 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6393 store_reg(s
, rd
, tmp
);
6394 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6396 tmp
= load_reg(s
, rm
);
6397 sh
= (insn
>> 16) & 0x1f;
6399 if (insn
& (1 << 22))
6400 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6402 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6404 store_reg(s
, rd
, tmp
);
6405 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6407 tmp
= load_reg(s
, rn
);
6408 tmp2
= load_reg(s
, rm
);
6410 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6411 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6414 store_reg(s
, rd
, tmp
);
6415 } else if ((insn
& 0x000003e0) == 0x00000060) {
6416 tmp
= load_reg(s
, rm
);
6417 shift
= (insn
>> 10) & 3;
6418 /* ??? In many cases it's not neccessary to do a
6419 rotate, a shift is sufficient. */
6421 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6422 op1
= (insn
>> 20) & 7;
6424 case 0: gen_sxtb16(tmp
); break;
6425 case 2: gen_sxtb(tmp
); break;
6426 case 3: gen_sxth(tmp
); break;
6427 case 4: gen_uxtb16(tmp
); break;
6428 case 6: gen_uxtb(tmp
); break;
6429 case 7: gen_uxth(tmp
); break;
6430 default: goto illegal_op
;
6433 tmp2
= load_reg(s
, rn
);
6434 if ((op1
& 3) == 0) {
6435 gen_add16(tmp
, tmp2
);
6437 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6441 store_reg(s
, rd
, tmp
);
6442 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6444 tmp
= load_reg(s
, rm
);
6445 if (insn
& (1 << 22)) {
6446 if (insn
& (1 << 7)) {
6450 gen_helper_rbit(tmp
, tmp
);
6453 if (insn
& (1 << 7))
6456 tcg_gen_bswap_i32(tmp
, tmp
);
6458 store_reg(s
, rd
, tmp
);
6463 case 2: /* Multiplies (Type 3). */
6464 tmp
= load_reg(s
, rm
);
6465 tmp2
= load_reg(s
, rs
);
6466 if (insn
& (1 << 20)) {
6467 /* Signed multiply most significant [accumulate]. */
6468 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
6469 if (insn
& (1 << 5))
6470 tcg_gen_addi_i64(tmp2
, tmp2
, 0x80000000u
);
6471 tcg_gen_shri_i64(tmp2
, tmp2
, 32);
6473 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
6475 tmp2
= load_reg(s
, rn
);
6476 if (insn
& (1 << 6)) {
6477 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6479 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6483 store_reg(s
, rd
, tmp
);
6485 if (insn
& (1 << 5))
6486 gen_swap_half(tmp2
);
6487 gen_smul_dual(tmp
, tmp2
);
6488 /* This addition cannot overflow. */
6489 if (insn
& (1 << 6)) {
6490 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6492 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6495 if (insn
& (1 << 22)) {
6496 /* smlald, smlsld */
6497 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
6498 tcg_gen_ext_i32_i64(tmp2
, tmp
);
6500 gen_addq(s
, tmp2
, rn
, rd
);
6501 gen_storeq_reg(s
, rn
, rd
, tmp2
);
6503 /* smuad, smusd, smlad, smlsd */
6506 tmp2
= load_reg(s
, rn
);
6507 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6510 store_reg(s
, rd
, tmp
);
6515 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6517 case 0: /* Unsigned sum of absolute differences. */
6519 tmp
= load_reg(s
, rm
);
6520 tmp2
= load_reg(s
, rs
);
6521 gen_helper_usad8(tmp
, tmp
, tmp2
);
6524 tmp2
= load_reg(s
, rn
);
6525 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6528 store_reg(s
, rd
, tmp
);
6530 case 0x20: case 0x24: case 0x28: case 0x2c:
6531 /* Bitfield insert/clear. */
6533 shift
= (insn
>> 7) & 0x1f;
6534 i
= (insn
>> 16) & 0x1f;
6538 tcg_gen_movi_i32(tmp
, 0);
6540 tmp
= load_reg(s
, rm
);
6543 tmp2
= load_reg(s
, rd
);
6544 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6547 store_reg(s
, rd
, tmp
);
6549 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6550 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6551 tmp
= load_reg(s
, rm
);
6552 shift
= (insn
>> 7) & 0x1f;
6553 i
= ((insn
>> 16) & 0x1f) + 1;
6558 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6560 gen_sbfx(tmp
, shift
, i
);
6563 store_reg(s
, rd
, tmp
);
6573 /* Check for undefined extension instructions
6574 * per the ARM Bible IE:
6575 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6577 sh
= (0xf << 20) | (0xf << 4);
6578 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6582 /* load/store byte/word */
6583 rn
= (insn
>> 16) & 0xf;
6584 rd
= (insn
>> 12) & 0xf;
6585 tmp2
= load_reg(s
, rn
);
6586 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6587 if (insn
& (1 << 24))
6588 gen_add_data_offset(s
, insn
, tmp2
);
6589 if (insn
& (1 << 20)) {
6592 if (insn
& (1 << 22)) {
6593 tmp
= gen_ld8u(tmp2
, i
);
6595 tmp
= gen_ld32(tmp2
, i
);
6599 tmp
= load_reg(s
, rd
);
6600 if (insn
& (1 << 22))
6601 gen_st8(tmp
, tmp2
, i
);
6603 gen_st32(tmp
, tmp2
, i
);
6605 if (!(insn
& (1 << 24))) {
6606 gen_add_data_offset(s
, insn
, tmp2
);
6607 store_reg(s
, rn
, tmp2
);
6608 } else if (insn
& (1 << 21)) {
6609 store_reg(s
, rn
, tmp2
);
6613 if (insn
& (1 << 20)) {
6614 /* Complete the load. */
6618 store_reg(s
, rd
, tmp
);
6624 int j
, n
, user
, loaded_base
;
6626 /* load/store multiple words */
6627 /* XXX: store correct base if write back */
6629 if (insn
& (1 << 22)) {
6631 goto illegal_op
; /* only usable in supervisor mode */
6633 if ((insn
& (1 << 15)) == 0)
6636 rn
= (insn
>> 16) & 0xf;
6637 addr
= load_reg(s
, rn
);
6639 /* compute total size */
6643 if (insn
& (1 << i
))
6646 /* XXX: test invalid n == 0 case ? */
6647 if (insn
& (1 << 23)) {
6648 if (insn
& (1 << 24)) {
6650 tcg_gen_addi_i32(addr
, addr
, 4);
6652 /* post increment */
6655 if (insn
& (1 << 24)) {
6657 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6659 /* post decrement */
6661 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6666 if (insn
& (1 << i
)) {
6667 if (insn
& (1 << 20)) {
6669 tmp
= gen_ld32(addr
, IS_USER(s
));
6673 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6675 } else if (i
== rn
) {
6679 store_reg(s
, i
, tmp
);
6684 /* special case: r15 = PC + 8 */
6685 val
= (long)s
->pc
+ 4;
6687 tcg_gen_movi_i32(tmp
, val
);
6690 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6692 tmp
= load_reg(s
, i
);
6694 gen_st32(tmp
, addr
, IS_USER(s
));
6697 /* no need to add after the last transfer */
6699 tcg_gen_addi_i32(addr
, addr
, 4);
6702 if (insn
& (1 << 21)) {
6704 if (insn
& (1 << 23)) {
6705 if (insn
& (1 << 24)) {
6708 /* post increment */
6709 tcg_gen_addi_i32(addr
, addr
, 4);
6712 if (insn
& (1 << 24)) {
6715 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6717 /* post decrement */
6718 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6721 store_reg(s
, rn
, addr
);
6726 store_reg(s
, rn
, loaded_var
);
6728 if ((insn
& (1 << 22)) && !user
) {
6729 /* Restore CPSR from SPSR. */
6730 tmp
= load_cpu_field(spsr
);
6731 gen_set_cpsr(tmp
, 0xffffffff);
6733 s
->is_jmp
= DISAS_UPDATE
;
6742 /* branch (and link) */
6743 val
= (int32_t)s
->pc
;
6744 if (insn
& (1 << 24)) {
6746 tcg_gen_movi_i32(tmp
, val
);
6747 store_reg(s
, 14, tmp
);
6749 offset
= (((int32_t)insn
<< 8) >> 8);
6750 val
+= (offset
<< 2) + 4;
6758 if (disas_coproc_insn(env
, s
, insn
))
6763 gen_set_pc_im(s
->pc
);
6764 s
->is_jmp
= DISAS_SWI
;
6768 gen_set_condexec(s
);
6769 gen_set_pc_im(s
->pc
- 4);
6770 gen_exception(EXCP_UDEF
);
6771 s
->is_jmp
= DISAS_JUMP
;
6777 /* Return true if this is a Thumb-2 logical op. */
6779 thumb2_logic_op(int op
)
6784 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6785 then set condition code flags based on the result of the operation.
6786 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6787 to the high bit of T1.
6788 Returns zero if the opcode is valid. */
6791 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6798 gen_op_andl_T0_T1();
6802 gen_op_bicl_T0_T1();
6815 gen_op_xorl_T0_T1();
6820 gen_op_addl_T0_T1_cc();
6822 gen_op_addl_T0_T1();
6826 gen_op_adcl_T0_T1_cc();
6832 gen_op_sbcl_T0_T1_cc();
6838 gen_op_subl_T0_T1_cc();
6840 gen_op_subl_T0_T1();
6844 gen_op_rsbl_T0_T1_cc();
6846 gen_op_rsbl_T0_T1();
6848 default: /* 5, 6, 7, 9, 12, 15. */
6852 gen_op_logic_T0_cc();
6854 gen_set_CF_bit31(cpu_T
[1]);
6859 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6861 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6863 uint32_t insn
, imm
, shift
, offset
;
6864 uint32_t rd
, rn
, rm
, rs
;
6874 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
6875 || arm_feature (env
, ARM_FEATURE_M
))) {
6876 /* Thumb-1 cores may need to treat bl and blx as a pair of
6877 16-bit instructions to get correct prefetch abort behavior. */
6879 if ((insn
& (1 << 12)) == 0) {
6880 /* Second half of blx. */
6881 offset
= ((insn
& 0x7ff) << 1);
6882 tmp
= load_reg(s
, 14);
6883 tcg_gen_addi_i32(tmp
, tmp
, offset
);
6884 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
6887 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6888 store_reg(s
, 14, tmp2
);
6892 if (insn
& (1 << 11)) {
6893 /* Second half of bl. */
6894 offset
= ((insn
& 0x7ff) << 1) | 1;
6895 tmp
= load_reg(s
, 14);
6896 tcg_gen_addi_i32(tmp
, tmp
, offset
);
6899 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6900 store_reg(s
, 14, tmp2
);
6904 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
6905 /* Instruction spans a page boundary. Implement it as two
6906 16-bit instructions in case the second half causes an
6908 offset
= ((int32_t)insn
<< 21) >> 9;
6909 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
6910 gen_movl_reg_T0(s
, 14);
6913 /* Fall through to 32-bit decode. */
6916 insn
= lduw_code(s
->pc
);
6918 insn
|= (uint32_t)insn_hw1
<< 16;
6920 if ((insn
& 0xf800e800) != 0xf000e800) {
6924 rn
= (insn
>> 16) & 0xf;
6925 rs
= (insn
>> 12) & 0xf;
6926 rd
= (insn
>> 8) & 0xf;
6928 switch ((insn
>> 25) & 0xf) {
6929 case 0: case 1: case 2: case 3:
6930 /* 16-bit instructions. Should never happen. */
6933 if (insn
& (1 << 22)) {
6934 /* Other load/store, table branch. */
6935 if (insn
& 0x01200000) {
6936 /* Load/store doubleword. */
6939 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
6941 addr
= load_reg(s
, rn
);
6943 offset
= (insn
& 0xff) * 4;
6944 if ((insn
& (1 << 23)) == 0)
6946 if (insn
& (1 << 24)) {
6947 tcg_gen_addi_i32(addr
, addr
, offset
);
6950 if (insn
& (1 << 20)) {
6952 tmp
= gen_ld32(addr
, IS_USER(s
));
6953 store_reg(s
, rs
, tmp
);
6954 tcg_gen_addi_i32(addr
, addr
, 4);
6955 tmp
= gen_ld32(addr
, IS_USER(s
));
6956 store_reg(s
, rd
, tmp
);
6959 tmp
= load_reg(s
, rs
);
6960 gen_st32(tmp
, addr
, IS_USER(s
));
6961 tcg_gen_addi_i32(addr
, addr
, 4);
6962 tmp
= load_reg(s
, rd
);
6963 gen_st32(tmp
, addr
, IS_USER(s
));
6965 if (insn
& (1 << 21)) {
6966 /* Base writeback. */
6969 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
6970 store_reg(s
, rn
, addr
);
6974 } else if ((insn
& (1 << 23)) == 0) {
6975 /* Load/store exclusive word. */
6976 gen_movl_T1_reg(s
, rn
);
6978 if (insn
& (1 << 20)) {
6979 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6980 tmp
= gen_ld32(addr
, IS_USER(s
));
6981 store_reg(s
, rd
, tmp
);
6983 int label
= gen_new_label();
6984 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6985 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6987 tmp
= load_reg(s
, rs
);
6988 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
6989 gen_set_label(label
);
6990 gen_movl_reg_T0(s
, rd
);
6992 } else if ((insn
& (1 << 6)) == 0) {
6996 tcg_gen_movi_i32(addr
, s
->pc
);
6998 addr
= load_reg(s
, rn
);
7000 tmp
= load_reg(s
, rm
);
7001 tcg_gen_add_i32(addr
, addr
, tmp
);
7002 if (insn
& (1 << 4)) {
7004 tcg_gen_add_i32(addr
, addr
, tmp
);
7006 tmp
= gen_ld16u(addr
, IS_USER(s
));
7009 tmp
= gen_ld8u(addr
, IS_USER(s
));
7012 tcg_gen_shli_i32(tmp
, tmp
, 1);
7013 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7014 store_reg(s
, 15, tmp
);
7016 /* Load/store exclusive byte/halfword/doubleword. */
7017 /* ??? These are not really atomic. However we know
7018 we never have multiple CPUs running in parallel,
7019 so it is good enough. */
7020 op
= (insn
>> 4) & 0x3;
7021 /* Must use a global reg for the address because we have
7022 a conditional branch in the store instruction. */
7023 gen_movl_T1_reg(s
, rn
);
7025 if (insn
& (1 << 20)) {
7026 gen_helper_mark_exclusive(cpu_env
, addr
);
7029 tmp
= gen_ld8u(addr
, IS_USER(s
));
7032 tmp
= gen_ld16u(addr
, IS_USER(s
));
7035 tmp
= gen_ld32(addr
, IS_USER(s
));
7036 tcg_gen_addi_i32(addr
, addr
, 4);
7037 tmp2
= gen_ld32(addr
, IS_USER(s
));
7038 store_reg(s
, rd
, tmp2
);
7043 store_reg(s
, rs
, tmp
);
7045 int label
= gen_new_label();
7046 /* Must use a global that is not killed by the branch. */
7047 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7048 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7049 tmp
= load_reg(s
, rs
);
7052 gen_st8(tmp
, addr
, IS_USER(s
));
7055 gen_st16(tmp
, addr
, IS_USER(s
));
7058 gen_st32(tmp
, addr
, IS_USER(s
));
7059 tcg_gen_addi_i32(addr
, addr
, 4);
7060 tmp
= load_reg(s
, rd
);
7061 gen_st32(tmp
, addr
, IS_USER(s
));
7066 gen_set_label(label
);
7067 gen_movl_reg_T0(s
, rm
);
7071 /* Load/store multiple, RFE, SRS. */
7072 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7073 /* Not available in user mode. */
7076 if (insn
& (1 << 20)) {
7078 addr
= load_reg(s
, rn
);
7079 if ((insn
& (1 << 24)) == 0)
7080 tcg_gen_addi_i32(addr
, addr
, -8);
7081 /* Load PC into tmp and CPSR into tmp2. */
7082 tmp
= gen_ld32(addr
, 0);
7083 tcg_gen_addi_i32(addr
, addr
, 4);
7084 tmp2
= gen_ld32(addr
, 0);
7085 if (insn
& (1 << 21)) {
7086 /* Base writeback. */
7087 if (insn
& (1 << 24)) {
7088 tcg_gen_addi_i32(addr
, addr
, 4);
7090 tcg_gen_addi_i32(addr
, addr
, -4);
7092 store_reg(s
, rn
, addr
);
7096 gen_rfe(s
, tmp
, tmp2
);
7100 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7101 addr
= load_reg(s
, 13);
7104 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7106 if ((insn
& (1 << 24)) == 0) {
7107 tcg_gen_addi_i32(addr
, addr
, -8);
7109 tmp
= load_reg(s
, 14);
7110 gen_st32(tmp
, addr
, 0);
7111 tcg_gen_addi_i32(addr
, addr
, 4);
7113 gen_helper_cpsr_read(tmp
);
7114 gen_st32(tmp
, addr
, 0);
7115 if (insn
& (1 << 21)) {
7116 if ((insn
& (1 << 24)) == 0) {
7117 tcg_gen_addi_i32(addr
, addr
, -4);
7119 tcg_gen_addi_i32(addr
, addr
, 4);
7121 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7122 store_reg(s
, 13, addr
);
7124 gen_helper_set_r13_banked(cpu_env
,
7125 tcg_const_i32(op
), addr
);
7133 /* Load/store multiple. */
7134 addr
= load_reg(s
, rn
);
7136 for (i
= 0; i
< 16; i
++) {
7137 if (insn
& (1 << i
))
7140 if (insn
& (1 << 24)) {
7141 tcg_gen_addi_i32(addr
, addr
, -offset
);
7144 for (i
= 0; i
< 16; i
++) {
7145 if ((insn
& (1 << i
)) == 0)
7147 if (insn
& (1 << 20)) {
7149 tmp
= gen_ld32(addr
, IS_USER(s
));
7153 store_reg(s
, i
, tmp
);
7157 tmp
= load_reg(s
, i
);
7158 gen_st32(tmp
, addr
, IS_USER(s
));
7160 tcg_gen_addi_i32(addr
, addr
, 4);
7162 if (insn
& (1 << 21)) {
7163 /* Base register writeback. */
7164 if (insn
& (1 << 24)) {
7165 tcg_gen_addi_i32(addr
, addr
, -offset
);
7167 /* Fault if writeback register is in register list. */
7168 if (insn
& (1 << rn
))
7170 store_reg(s
, rn
, addr
);
7177 case 5: /* Data processing register constant shift. */
7179 gen_op_movl_T0_im(0);
7181 gen_movl_T0_reg(s
, rn
);
7182 gen_movl_T1_reg(s
, rm
);
7183 op
= (insn
>> 21) & 0xf;
7184 shiftop
= (insn
>> 4) & 3;
7185 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7186 conds
= (insn
& (1 << 20)) != 0;
7187 logic_cc
= (conds
&& thumb2_logic_op(op
));
7188 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7189 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7192 gen_movl_reg_T0(s
, rd
);
7194 case 13: /* Misc data processing. */
7195 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7196 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7199 case 0: /* Register controlled shift. */
7200 tmp
= load_reg(s
, rn
);
7201 tmp2
= load_reg(s
, rm
);
7202 if ((insn
& 0x70) != 0)
7204 op
= (insn
>> 21) & 3;
7205 logic_cc
= (insn
& (1 << 20)) != 0;
7206 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7209 store_reg(s
, rd
, tmp
);
7211 case 1: /* Sign/zero extend. */
7212 tmp
= load_reg(s
, rm
);
7213 shift
= (insn
>> 4) & 3;
7214 /* ??? In many cases it's not neccessary to do a
7215 rotate, a shift is sufficient. */
7217 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7218 op
= (insn
>> 20) & 7;
7220 case 0: gen_sxth(tmp
); break;
7221 case 1: gen_uxth(tmp
); break;
7222 case 2: gen_sxtb16(tmp
); break;
7223 case 3: gen_uxtb16(tmp
); break;
7224 case 4: gen_sxtb(tmp
); break;
7225 case 5: gen_uxtb(tmp
); break;
7226 default: goto illegal_op
;
7229 tmp2
= load_reg(s
, rn
);
7230 if ((op
>> 1) == 1) {
7231 gen_add16(tmp
, tmp2
);
7233 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7237 store_reg(s
, rd
, tmp
);
7239 case 2: /* SIMD add/subtract. */
7240 op
= (insn
>> 20) & 7;
7241 shift
= (insn
>> 4) & 7;
7242 if ((op
& 3) == 3 || (shift
& 3) == 3)
7244 tmp
= load_reg(s
, rn
);
7245 tmp2
= load_reg(s
, rm
);
7246 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7248 store_reg(s
, rd
, tmp
);
7250 case 3: /* Other data processing. */
7251 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7253 /* Saturating add/subtract. */
7254 tmp
= load_reg(s
, rn
);
7255 tmp2
= load_reg(s
, rm
);
7257 gen_helper_double_saturate(tmp
, tmp
);
7259 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7261 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7264 tmp
= load_reg(s
, rn
);
7266 case 0x0a: /* rbit */
7267 gen_helper_rbit(tmp
, tmp
);
7269 case 0x08: /* rev */
7270 tcg_gen_bswap_i32(tmp
, tmp
);
7272 case 0x09: /* rev16 */
7275 case 0x0b: /* revsh */
7278 case 0x10: /* sel */
7279 tmp2
= load_reg(s
, rm
);
7281 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7282 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7286 case 0x18: /* clz */
7287 gen_helper_clz(tmp
, tmp
);
7293 store_reg(s
, rd
, tmp
);
7295 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7296 op
= (insn
>> 4) & 0xf;
7297 tmp
= load_reg(s
, rn
);
7298 tmp2
= load_reg(s
, rm
);
7299 switch ((insn
>> 20) & 7) {
7300 case 0: /* 32 x 32 -> 32 */
7301 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7304 tmp2
= load_reg(s
, rs
);
7306 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7308 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7312 case 1: /* 16 x 16 -> 32 */
7313 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7316 tmp2
= load_reg(s
, rs
);
7317 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7321 case 2: /* Dual multiply add. */
7322 case 4: /* Dual multiply subtract. */
7324 gen_swap_half(tmp2
);
7325 gen_smul_dual(tmp
, tmp2
);
7326 /* This addition cannot overflow. */
7327 if (insn
& (1 << 22)) {
7328 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7330 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7335 tmp2
= load_reg(s
, rs
);
7336 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7340 case 3: /* 32 * 16 -> 32msb */
7342 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7345 tmp2
= gen_muls_i64_i32(tmp
, tmp2
);
7346 tcg_gen_shri_i64(tmp2
, tmp2
, 16);
7348 tcg_gen_trunc_i64_i32(tmp
, tmp2
);
7351 tmp2
= load_reg(s
, rs
);
7352 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7356 case 5: case 6: /* 32 * 32 -> 32msb */
7357 gen_imull(tmp
, tmp2
);
7358 if (insn
& (1 << 5)) {
7359 gen_roundqd(tmp
, tmp2
);
7366 tmp2
= load_reg(s
, rs
);
7367 if (insn
& (1 << 21)) {
7368 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7370 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7375 case 7: /* Unsigned sum of absolute differences. */
7376 gen_helper_usad8(tmp
, tmp
, tmp2
);
7379 tmp2
= load_reg(s
, rs
);
7380 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7385 store_reg(s
, rd
, tmp
);
7387 case 6: case 7: /* 64-bit multiply, Divide. */
7388 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7389 tmp
= load_reg(s
, rn
);
7390 tmp2
= load_reg(s
, rm
);
7391 if ((op
& 0x50) == 0x10) {
7393 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7396 gen_helper_udiv(tmp
, tmp
, tmp2
);
7398 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7400 store_reg(s
, rd
, tmp
);
7401 } else if ((op
& 0xe) == 0xc) {
7402 /* Dual multiply accumulate long. */
7404 gen_swap_half(tmp2
);
7405 gen_smul_dual(tmp
, tmp2
);
7407 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7409 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7412 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
7413 gen_addq(s
, tmp
, rs
, rd
);
7414 gen_storeq_reg(s
, rs
, rd
, tmp
);
7417 /* Unsigned 64-bit multiply */
7418 tmp
= gen_mulu_i64_i32(tmp
, tmp2
);
7422 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7424 tmp2
= tcg_temp_new(TCG_TYPE_I64
);
7425 tcg_gen_ext_i32_i64(tmp2
, tmp
);
7429 /* Signed 64-bit multiply */
7430 tmp
= gen_muls_i64_i32(tmp
, tmp2
);
7435 gen_addq_lo(s
, tmp
, rs
);
7436 gen_addq_lo(s
, tmp
, rd
);
7437 } else if (op
& 0x40) {
7438 /* 64-bit accumulate. */
7439 gen_addq(s
, tmp
, rs
, rd
);
7441 gen_storeq_reg(s
, rs
, rd
, tmp
);
7446 case 6: case 7: case 14: case 15:
7448 if (((insn
>> 24) & 3) == 3) {
7449 /* Translate into the equivalent ARM encoding. */
7450 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7451 if (disas_neon_data_insn(env
, s
, insn
))
7454 if (insn
& (1 << 28))
7456 if (disas_coproc_insn (env
, s
, insn
))
7460 case 8: case 9: case 10: case 11:
7461 if (insn
& (1 << 15)) {
7462 /* Branches, misc control. */
7463 if (insn
& 0x5000) {
7464 /* Unconditional branch. */
7465 /* signextend(hw1[10:0]) -> offset[:12]. */
7466 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7467 /* hw1[10:0] -> offset[11:1]. */
7468 offset
|= (insn
& 0x7ff) << 1;
7469 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7470 offset[24:22] already have the same value because of the
7471 sign extension above. */
7472 offset
^= ((~insn
) & (1 << 13)) << 10;
7473 offset
^= ((~insn
) & (1 << 11)) << 11;
7475 if (insn
& (1 << 14)) {
7476 /* Branch and link. */
7477 gen_op_movl_T1_im(s
->pc
| 1);
7478 gen_movl_reg_T1(s
, 14);
7482 if (insn
& (1 << 12)) {
7487 offset
&= ~(uint32_t)2;
7488 gen_bx_im(s
, offset
);
7490 } else if (((insn
>> 23) & 7) == 7) {
7492 if (insn
& (1 << 13))
7495 if (insn
& (1 << 26)) {
7496 /* Secure monitor call (v6Z) */
7497 goto illegal_op
; /* not implemented. */
7499 op
= (insn
>> 20) & 7;
7501 case 0: /* msr cpsr. */
7503 tmp
= load_reg(s
, rn
);
7504 addr
= tcg_const_i32(insn
& 0xff);
7505 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7510 case 1: /* msr spsr. */
7513 gen_movl_T0_reg(s
, rn
);
7514 if (gen_set_psr_T0(s
,
7515 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7519 case 2: /* cps, nop-hint. */
7520 if (((insn
>> 8) & 7) == 0) {
7521 gen_nop_hint(s
, insn
& 0xff);
7523 /* Implemented as NOP in user mode. */
7528 if (insn
& (1 << 10)) {
7529 if (insn
& (1 << 7))
7531 if (insn
& (1 << 6))
7533 if (insn
& (1 << 5))
7535 if (insn
& (1 << 9))
7536 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7538 if (insn
& (1 << 8)) {
7540 imm
|= (insn
& 0x1f);
7543 gen_op_movl_T0_im(imm
);
7544 gen_set_psr_T0(s
, offset
, 0);
7547 case 3: /* Special control operations. */
7548 op
= (insn
>> 4) & 0xf;
7551 gen_helper_clrex(cpu_env
);
7556 /* These execute as NOPs. */
7564 /* Trivial implementation equivalent to bx. */
7565 tmp
= load_reg(s
, rn
);
7568 case 5: /* Exception return. */
7569 /* Unpredictable in user mode. */
7571 case 6: /* mrs cpsr. */
7574 addr
= tcg_const_i32(insn
& 0xff);
7575 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7577 gen_helper_cpsr_read(tmp
);
7579 store_reg(s
, rd
, tmp
);
7581 case 7: /* mrs spsr. */
7582 /* Not accessible in user mode. */
7583 if (IS_USER(s
) || IS_M(env
))
7585 tmp
= load_cpu_field(spsr
);
7586 store_reg(s
, rd
, tmp
);
7591 /* Conditional branch. */
7592 op
= (insn
>> 22) & 0xf;
7593 /* Generate a conditional jump to next instruction. */
7594 s
->condlabel
= gen_new_label();
7595 gen_test_cc(op
^ 1, s
->condlabel
);
7598 /* offset[11:1] = insn[10:0] */
7599 offset
= (insn
& 0x7ff) << 1;
7600 /* offset[17:12] = insn[21:16]. */
7601 offset
|= (insn
& 0x003f0000) >> 4;
7602 /* offset[31:20] = insn[26]. */
7603 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7604 /* offset[18] = insn[13]. */
7605 offset
|= (insn
& (1 << 13)) << 5;
7606 /* offset[19] = insn[11]. */
7607 offset
|= (insn
& (1 << 11)) << 8;
7609 /* jump to the offset */
7610 gen_jmp(s
, s
->pc
+ offset
);
7613 /* Data processing immediate. */
7614 if (insn
& (1 << 25)) {
7615 if (insn
& (1 << 24)) {
7616 if (insn
& (1 << 20))
7618 /* Bitfield/Saturate. */
7619 op
= (insn
>> 21) & 7;
7621 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7624 tcg_gen_movi_i32(tmp
, 0);
7626 tmp
= load_reg(s
, rn
);
7629 case 2: /* Signed bitfield extract. */
7631 if (shift
+ imm
> 32)
7634 gen_sbfx(tmp
, shift
, imm
);
7636 case 6: /* Unsigned bitfield extract. */
7638 if (shift
+ imm
> 32)
7641 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7643 case 3: /* Bitfield insert/clear. */
7646 imm
= imm
+ 1 - shift
;
7648 tmp2
= load_reg(s
, rd
);
7649 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7655 default: /* Saturate. */
7658 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7660 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7662 tmp2
= tcg_const_i32(imm
);
7665 if ((op
& 1) && shift
== 0)
7666 gen_helper_usat16(tmp
, tmp
, tmp2
);
7668 gen_helper_usat(tmp
, tmp
, tmp2
);
7671 if ((op
& 1) && shift
== 0)
7672 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7674 gen_helper_ssat(tmp
, tmp
, tmp2
);
7678 store_reg(s
, rd
, tmp
);
7680 imm
= ((insn
& 0x04000000) >> 15)
7681 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7682 if (insn
& (1 << 22)) {
7683 /* 16-bit immediate. */
7684 imm
|= (insn
>> 4) & 0xf000;
7685 if (insn
& (1 << 23)) {
7687 tmp
= load_reg(s
, rd
);
7688 tcg_gen_ext16u_i32(tmp
, tmp
);
7689 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7693 tcg_gen_movi_i32(tmp
, imm
);
7696 /* Add/sub 12-bit immediate. */
7698 offset
= s
->pc
& ~(uint32_t)3;
7699 if (insn
& (1 << 23))
7704 tcg_gen_movi_i32(tmp
, offset
);
7706 tmp
= load_reg(s
, rn
);
7707 if (insn
& (1 << 23))
7708 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7710 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7713 store_reg(s
, rd
, tmp
);
7716 int shifter_out
= 0;
7717 /* modified 12-bit immediate. */
7718 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7719 imm
= (insn
& 0xff);
7722 /* Nothing to do. */
7724 case 1: /* 00XY00XY */
7727 case 2: /* XY00XY00 */
7731 case 3: /* XYXYXYXY */
7735 default: /* Rotated constant. */
7736 shift
= (shift
<< 1) | (imm
>> 7);
7738 imm
= imm
<< (32 - shift
);
7742 gen_op_movl_T1_im(imm
);
7743 rn
= (insn
>> 16) & 0xf;
7745 gen_op_movl_T0_im(0);
7747 gen_movl_T0_reg(s
, rn
);
7748 op
= (insn
>> 21) & 0xf;
7749 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7752 rd
= (insn
>> 8) & 0xf;
7754 gen_movl_reg_T0(s
, rd
);
7759 case 12: /* Load/store single data item. */
7764 if ((insn
& 0x01100000) == 0x01000000) {
7765 if (disas_neon_ls_insn(env
, s
, insn
))
7773 /* s->pc has already been incremented by 4. */
7774 imm
= s
->pc
& 0xfffffffc;
7775 if (insn
& (1 << 23))
7776 imm
+= insn
& 0xfff;
7778 imm
-= insn
& 0xfff;
7779 tcg_gen_movi_i32(addr
, imm
);
7781 addr
= load_reg(s
, rn
);
7782 if (insn
& (1 << 23)) {
7783 /* Positive offset. */
7785 tcg_gen_addi_i32(addr
, addr
, imm
);
7787 op
= (insn
>> 8) & 7;
7790 case 0: case 8: /* Shifted Register. */
7791 shift
= (insn
>> 4) & 0xf;
7794 tmp
= load_reg(s
, rm
);
7796 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7797 tcg_gen_add_i32(addr
, addr
, tmp
);
7800 case 4: /* Negative offset. */
7801 tcg_gen_addi_i32(addr
, addr
, -imm
);
7803 case 6: /* User privilege. */
7804 tcg_gen_addi_i32(addr
, addr
, imm
);
7807 case 1: /* Post-decrement. */
7810 case 3: /* Post-increment. */
7814 case 5: /* Pre-decrement. */
7817 case 7: /* Pre-increment. */
7818 tcg_gen_addi_i32(addr
, addr
, imm
);
7826 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7827 if (insn
& (1 << 20)) {
7829 if (rs
== 15 && op
!= 2) {
7832 /* Memory hint. Implemented as NOP. */
7835 case 0: tmp
= gen_ld8u(addr
, user
); break;
7836 case 4: tmp
= gen_ld8s(addr
, user
); break;
7837 case 1: tmp
= gen_ld16u(addr
, user
); break;
7838 case 5: tmp
= gen_ld16s(addr
, user
); break;
7839 case 2: tmp
= gen_ld32(addr
, user
); break;
7840 default: goto illegal_op
;
7845 store_reg(s
, rs
, tmp
);
7852 tmp
= load_reg(s
, rs
);
7854 case 0: gen_st8(tmp
, addr
, user
); break;
7855 case 1: gen_st16(tmp
, addr
, user
); break;
7856 case 2: gen_st32(tmp
, addr
, user
); break;
7857 default: goto illegal_op
;
7861 tcg_gen_addi_i32(addr
, addr
, imm
);
7863 store_reg(s
, rn
, addr
);
7877 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
7879 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
7886 if (s
->condexec_mask
) {
7887 cond
= s
->condexec_cond
;
7888 s
->condlabel
= gen_new_label();
7889 gen_test_cc(cond
^ 1, s
->condlabel
);
7893 insn
= lduw_code(s
->pc
);
7896 switch (insn
>> 12) {
7899 op
= (insn
>> 11) & 3;
7902 rn
= (insn
>> 3) & 7;
7903 gen_movl_T0_reg(s
, rn
);
7904 if (insn
& (1 << 10)) {
7906 gen_op_movl_T1_im((insn
>> 6) & 7);
7909 rm
= (insn
>> 6) & 7;
7910 gen_movl_T1_reg(s
, rm
);
7912 if (insn
& (1 << 9)) {
7913 if (s
->condexec_mask
)
7914 gen_op_subl_T0_T1();
7916 gen_op_subl_T0_T1_cc();
7918 if (s
->condexec_mask
)
7919 gen_op_addl_T0_T1();
7921 gen_op_addl_T0_T1_cc();
7923 gen_movl_reg_T0(s
, rd
);
7925 /* shift immediate */
7926 rm
= (insn
>> 3) & 7;
7927 shift
= (insn
>> 6) & 0x1f;
7928 tmp
= load_reg(s
, rm
);
7929 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
7930 if (!s
->condexec_mask
)
7932 store_reg(s
, rd
, tmp
);
7936 /* arithmetic large immediate */
7937 op
= (insn
>> 11) & 3;
7938 rd
= (insn
>> 8) & 0x7;
7940 gen_op_movl_T0_im(insn
& 0xff);
7942 gen_movl_T0_reg(s
, rd
);
7943 gen_op_movl_T1_im(insn
& 0xff);
7947 if (!s
->condexec_mask
)
7948 gen_op_logic_T0_cc();
7951 gen_op_subl_T0_T1_cc();
7954 if (s
->condexec_mask
)
7955 gen_op_addl_T0_T1();
7957 gen_op_addl_T0_T1_cc();
7960 if (s
->condexec_mask
)
7961 gen_op_subl_T0_T1();
7963 gen_op_subl_T0_T1_cc();
7967 gen_movl_reg_T0(s
, rd
);
7970 if (insn
& (1 << 11)) {
7971 rd
= (insn
>> 8) & 7;
7972 /* load pc-relative. Bit 1 of PC is ignored. */
7973 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
7974 val
&= ~(uint32_t)2;
7976 tcg_gen_movi_i32(addr
, val
);
7977 tmp
= gen_ld32(addr
, IS_USER(s
));
7979 store_reg(s
, rd
, tmp
);
7982 if (insn
& (1 << 10)) {
7983 /* data processing extended or blx */
7984 rd
= (insn
& 7) | ((insn
>> 4) & 8);
7985 rm
= (insn
>> 3) & 0xf;
7986 op
= (insn
>> 8) & 3;
7989 gen_movl_T0_reg(s
, rd
);
7990 gen_movl_T1_reg(s
, rm
);
7991 gen_op_addl_T0_T1();
7992 gen_movl_reg_T0(s
, rd
);
7995 gen_movl_T0_reg(s
, rd
);
7996 gen_movl_T1_reg(s
, rm
);
7997 gen_op_subl_T0_T1_cc();
7999 case 2: /* mov/cpy */
8000 gen_movl_T0_reg(s
, rm
);
8001 gen_movl_reg_T0(s
, rd
);
8003 case 3:/* branch [and link] exchange thumb register */
8004 tmp
= load_reg(s
, rm
);
8005 if (insn
& (1 << 7)) {
8006 val
= (uint32_t)s
->pc
| 1;
8008 tcg_gen_movi_i32(tmp2
, val
);
8009 store_reg(s
, 14, tmp2
);
8017 /* data processing register */
8019 rm
= (insn
>> 3) & 7;
8020 op
= (insn
>> 6) & 0xf;
8021 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8022 /* the shift/rotate ops want the operands backwards */
8031 if (op
== 9) /* neg */
8032 gen_op_movl_T0_im(0);
8033 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8034 gen_movl_T0_reg(s
, rd
);
8036 gen_movl_T1_reg(s
, rm
);
8039 gen_op_andl_T0_T1();
8040 if (!s
->condexec_mask
)
8041 gen_op_logic_T0_cc();
8044 gen_op_xorl_T0_T1();
8045 if (!s
->condexec_mask
)
8046 gen_op_logic_T0_cc();
8049 if (s
->condexec_mask
) {
8050 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8052 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8053 gen_op_logic_T1_cc();
8057 if (s
->condexec_mask
) {
8058 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8060 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8061 gen_op_logic_T1_cc();
8065 if (s
->condexec_mask
) {
8066 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8068 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8069 gen_op_logic_T1_cc();
8073 if (s
->condexec_mask
)
8076 gen_op_adcl_T0_T1_cc();
8079 if (s
->condexec_mask
)
8082 gen_op_sbcl_T0_T1_cc();
8085 if (s
->condexec_mask
) {
8086 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8088 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8089 gen_op_logic_T1_cc();
8093 gen_op_andl_T0_T1();
8094 gen_op_logic_T0_cc();
8098 if (s
->condexec_mask
)
8099 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8101 gen_op_subl_T0_T1_cc();
8104 gen_op_subl_T0_T1_cc();
8108 gen_op_addl_T0_T1_cc();
8113 if (!s
->condexec_mask
)
8114 gen_op_logic_T0_cc();
8117 gen_op_mull_T0_T1();
8118 if (!s
->condexec_mask
)
8119 gen_op_logic_T0_cc();
8122 gen_op_bicl_T0_T1();
8123 if (!s
->condexec_mask
)
8124 gen_op_logic_T0_cc();
8128 if (!s
->condexec_mask
)
8129 gen_op_logic_T1_cc();
8136 gen_movl_reg_T1(s
, rm
);
8138 gen_movl_reg_T0(s
, rd
);
8143 /* load/store register offset. */
8145 rn
= (insn
>> 3) & 7;
8146 rm
= (insn
>> 6) & 7;
8147 op
= (insn
>> 9) & 7;
8148 addr
= load_reg(s
, rn
);
8149 tmp
= load_reg(s
, rm
);
8150 tcg_gen_add_i32(addr
, addr
, tmp
);
8153 if (op
< 3) /* store */
8154 tmp
= load_reg(s
, rd
);
8158 gen_st32(tmp
, addr
, IS_USER(s
));
8161 gen_st16(tmp
, addr
, IS_USER(s
));
8164 gen_st8(tmp
, addr
, IS_USER(s
));
8167 tmp
= gen_ld8s(addr
, IS_USER(s
));
8170 tmp
= gen_ld32(addr
, IS_USER(s
));
8173 tmp
= gen_ld16u(addr
, IS_USER(s
));
8176 tmp
= gen_ld8u(addr
, IS_USER(s
));
8179 tmp
= gen_ld16s(addr
, IS_USER(s
));
8182 if (op
>= 3) /* load */
8183 store_reg(s
, rd
, tmp
);
8188 /* load/store word immediate offset */
8190 rn
= (insn
>> 3) & 7;
8191 addr
= load_reg(s
, rn
);
8192 val
= (insn
>> 4) & 0x7c;
8193 tcg_gen_addi_i32(addr
, addr
, val
);
8195 if (insn
& (1 << 11)) {
8197 tmp
= gen_ld32(addr
, IS_USER(s
));
8198 store_reg(s
, rd
, tmp
);
8201 tmp
= load_reg(s
, rd
);
8202 gen_st32(tmp
, addr
, IS_USER(s
));
8208 /* load/store byte immediate offset */
8210 rn
= (insn
>> 3) & 7;
8211 addr
= load_reg(s
, rn
);
8212 val
= (insn
>> 6) & 0x1f;
8213 tcg_gen_addi_i32(addr
, addr
, val
);
8215 if (insn
& (1 << 11)) {
8217 tmp
= gen_ld8u(addr
, IS_USER(s
));
8218 store_reg(s
, rd
, tmp
);
8221 tmp
= load_reg(s
, rd
);
8222 gen_st8(tmp
, addr
, IS_USER(s
));
8228 /* load/store halfword immediate offset */
8230 rn
= (insn
>> 3) & 7;
8231 addr
= load_reg(s
, rn
);
8232 val
= (insn
>> 5) & 0x3e;
8233 tcg_gen_addi_i32(addr
, addr
, val
);
8235 if (insn
& (1 << 11)) {
8237 tmp
= gen_ld16u(addr
, IS_USER(s
));
8238 store_reg(s
, rd
, tmp
);
8241 tmp
= load_reg(s
, rd
);
8242 gen_st16(tmp
, addr
, IS_USER(s
));
8248 /* load/store from stack */
8249 rd
= (insn
>> 8) & 7;
8250 addr
= load_reg(s
, 13);
8251 val
= (insn
& 0xff) * 4;
8252 tcg_gen_addi_i32(addr
, addr
, val
);
8254 if (insn
& (1 << 11)) {
8256 tmp
= gen_ld32(addr
, IS_USER(s
));
8257 store_reg(s
, rd
, tmp
);
8260 tmp
= load_reg(s
, rd
);
8261 gen_st32(tmp
, addr
, IS_USER(s
));
8267 /* add to high reg */
8268 rd
= (insn
>> 8) & 7;
8269 if (insn
& (1 << 11)) {
8271 tmp
= load_reg(s
, 13);
8273 /* PC. bit 1 is ignored. */
8275 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8277 val
= (insn
& 0xff) * 4;
8278 tcg_gen_addi_i32(tmp
, tmp
, val
);
8279 store_reg(s
, rd
, tmp
);
8284 op
= (insn
>> 8) & 0xf;
8287 /* adjust stack pointer */
8288 tmp
= load_reg(s
, 13);
8289 val
= (insn
& 0x7f) * 4;
8290 if (insn
& (1 << 7))
8291 val
= -(int32_t)val
;
8292 tcg_gen_addi_i32(tmp
, tmp
, val
);
8293 store_reg(s
, 13, tmp
);
8296 case 2: /* sign/zero extend. */
8299 rm
= (insn
>> 3) & 7;
8300 tmp
= load_reg(s
, rm
);
8301 switch ((insn
>> 6) & 3) {
8302 case 0: gen_sxth(tmp
); break;
8303 case 1: gen_sxtb(tmp
); break;
8304 case 2: gen_uxth(tmp
); break;
8305 case 3: gen_uxtb(tmp
); break;
8307 store_reg(s
, rd
, tmp
);
8309 case 4: case 5: case 0xc: case 0xd:
8311 addr
= load_reg(s
, 13);
8312 if (insn
& (1 << 8))
8316 for (i
= 0; i
< 8; i
++) {
8317 if (insn
& (1 << i
))
8320 if ((insn
& (1 << 11)) == 0) {
8321 tcg_gen_addi_i32(addr
, addr
, -offset
);
8323 for (i
= 0; i
< 8; i
++) {
8324 if (insn
& (1 << i
)) {
8325 if (insn
& (1 << 11)) {
8327 tmp
= gen_ld32(addr
, IS_USER(s
));
8328 store_reg(s
, i
, tmp
);
8331 tmp
= load_reg(s
, i
);
8332 gen_st32(tmp
, addr
, IS_USER(s
));
8334 /* advance to the next address. */
8335 tcg_gen_addi_i32(addr
, addr
, 4);
8338 if (insn
& (1 << 8)) {
8339 if (insn
& (1 << 11)) {
8341 tmp
= gen_ld32(addr
, IS_USER(s
));
8342 /* don't set the pc until the rest of the instruction
8346 tmp
= load_reg(s
, 14);
8347 gen_st32(tmp
, addr
, IS_USER(s
));
8349 tcg_gen_addi_i32(addr
, addr
, 4);
8351 if ((insn
& (1 << 11)) == 0) {
8352 tcg_gen_addi_i32(addr
, addr
, -offset
);
8354 /* write back the new stack pointer */
8355 store_reg(s
, 13, addr
);
8356 /* set the new PC value */
8357 if ((insn
& 0x0900) == 0x0900)
8361 case 1: case 3: case 9: case 11: /* czb */
8363 tmp
= load_reg(s
, rm
);
8364 s
->condlabel
= gen_new_label();
8366 if (insn
& (1 << 11))
8367 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8369 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8371 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8372 val
= (uint32_t)s
->pc
+ 2;
8377 case 15: /* IT, nop-hint. */
8378 if ((insn
& 0xf) == 0) {
8379 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8383 s
->condexec_cond
= (insn
>> 4) & 0xe;
8384 s
->condexec_mask
= insn
& 0x1f;
8385 /* No actual code generated for this insn, just setup state. */
8388 case 0xe: /* bkpt */
8389 gen_set_condexec(s
);
8390 gen_set_pc_im(s
->pc
- 2);
8391 gen_exception(EXCP_BKPT
);
8392 s
->is_jmp
= DISAS_JUMP
;
8397 rn
= (insn
>> 3) & 0x7;
8399 tmp
= load_reg(s
, rn
);
8400 switch ((insn
>> 6) & 3) {
8401 case 0: tcg_gen_bswap_i32(tmp
, tmp
); break;
8402 case 1: gen_rev16(tmp
); break;
8403 case 3: gen_revsh(tmp
); break;
8404 default: goto illegal_op
;
8406 store_reg(s
, rd
, tmp
);
8414 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8417 addr
= tcg_const_i32(16);
8418 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8422 addr
= tcg_const_i32(17);
8423 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8427 if (insn
& (1 << 4))
8428 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8432 val
= ((insn
& 7) << 6) & shift
;
8433 gen_op_movl_T0_im(val
);
8434 gen_set_psr_T0(s
, shift
, 0);
8444 /* load/store multiple */
8445 rn
= (insn
>> 8) & 0x7;
8446 addr
= load_reg(s
, rn
);
8447 for (i
= 0; i
< 8; i
++) {
8448 if (insn
& (1 << i
)) {
8449 if (insn
& (1 << 11)) {
8451 tmp
= gen_ld32(addr
, IS_USER(s
));
8452 store_reg(s
, i
, tmp
);
8455 tmp
= load_reg(s
, i
);
8456 gen_st32(tmp
, addr
, IS_USER(s
));
8458 /* advance to the next address */
8459 tcg_gen_addi_i32(addr
, addr
, 4);
8462 /* Base register writeback. */
8463 if ((insn
& (1 << rn
)) == 0) {
8464 store_reg(s
, rn
, addr
);
8471 /* conditional branch or swi */
8472 cond
= (insn
>> 8) & 0xf;
8478 gen_set_condexec(s
);
8479 gen_set_pc_im(s
->pc
);
8480 s
->is_jmp
= DISAS_SWI
;
8483 /* generate a conditional jump to next instruction */
8484 s
->condlabel
= gen_new_label();
8485 gen_test_cc(cond
^ 1, s
->condlabel
);
8487 gen_movl_T1_reg(s
, 15);
8489 /* jump to the offset */
8490 val
= (uint32_t)s
->pc
+ 2;
8491 offset
= ((int32_t)insn
<< 24) >> 24;
8497 if (insn
& (1 << 11)) {
8498 if (disas_thumb2_insn(env
, s
, insn
))
8502 /* unconditional branch */
8503 val
= (uint32_t)s
->pc
;
8504 offset
= ((int32_t)insn
<< 21) >> 21;
8505 val
+= (offset
<< 1) + 2;
8510 if (disas_thumb2_insn(env
, s
, insn
))
8516 gen_set_condexec(s
);
8517 gen_set_pc_im(s
->pc
- 4);
8518 gen_exception(EXCP_UDEF
);
8519 s
->is_jmp
= DISAS_JUMP
;
8523 gen_set_condexec(s
);
8524 gen_set_pc_im(s
->pc
- 2);
8525 gen_exception(EXCP_UDEF
);
8526 s
->is_jmp
= DISAS_JUMP
;
8529 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8530 basic block 'tb'. If search_pc is TRUE, also generate PC
8531 information for each intermediate instruction. */
8532 static inline int gen_intermediate_code_internal(CPUState
*env
,
8533 TranslationBlock
*tb
,
8536 DisasContext dc1
, *dc
= &dc1
;
8537 uint16_t *gen_opc_end
;
8539 target_ulong pc_start
;
8540 uint32_t next_page_start
;
8542 /* generate intermediate code */
8544 memset(temps
, 0, sizeof(temps
));
8550 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8552 dc
->is_jmp
= DISAS_NEXT
;
8554 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8556 dc
->thumb
= env
->thumb
;
8557 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8558 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8560 #if !defined(CONFIG_USER_ONLY)
8562 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8564 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8567 cpu_F0s
= tcg_temp_new(TCG_TYPE_I32
);
8568 cpu_F1s
= tcg_temp_new(TCG_TYPE_I32
);
8569 cpu_F0d
= tcg_temp_new(TCG_TYPE_I64
);
8570 cpu_F1d
= tcg_temp_new(TCG_TYPE_I64
);
8573 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8574 cpu_M0
= tcg_temp_new(TCG_TYPE_I64
);
8575 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8577 /* Reset the conditional execution bits immediately. This avoids
8578 complications trying to do it at the end of the block. */
8579 if (env
->condexec_bits
)
8581 TCGv tmp
= new_tmp();
8582 tcg_gen_movi_i32(tmp
, 0);
8583 store_cpu_field(tmp
, condexec_bits
);
8586 #ifdef CONFIG_USER_ONLY
8587 /* Intercept jump to the magic kernel page. */
8588 if (dc
->pc
>= 0xffff0000) {
8589 /* We always get here via a jump, so know we are not in a
8590 conditional execution block. */
8591 gen_exception(EXCP_KERNEL_TRAP
);
8592 dc
->is_jmp
= DISAS_UPDATE
;
8596 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8597 /* We always get here via a jump, so know we are not in a
8598 conditional execution block. */
8599 gen_exception(EXCP_EXCEPTION_EXIT
);
8603 if (env
->nb_breakpoints
> 0) {
8604 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
8605 if (env
->breakpoints
[j
] == dc
->pc
) {
8606 gen_set_condexec(dc
);
8607 gen_set_pc_im(dc
->pc
);
8608 gen_exception(EXCP_DEBUG
);
8609 dc
->is_jmp
= DISAS_JUMP
;
8610 /* Advance PC so that clearing the breakpoint will
8611 invalidate this TB. */
8613 goto done_generating
;
8619 j
= gen_opc_ptr
- gen_opc_buf
;
8623 gen_opc_instr_start
[lj
++] = 0;
8625 gen_opc_pc
[lj
] = dc
->pc
;
8626 gen_opc_instr_start
[lj
] = 1;
8630 disas_thumb_insn(env
, dc
);
8631 if (dc
->condexec_mask
) {
8632 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8633 | ((dc
->condexec_mask
>> 4) & 1);
8634 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8635 if (dc
->condexec_mask
== 0) {
8636 dc
->condexec_cond
= 0;
8640 disas_arm_insn(env
, dc
);
8643 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8647 if (dc
->condjmp
&& !dc
->is_jmp
) {
8648 gen_set_label(dc
->condlabel
);
8651 /* Terminate the TB on memory ops if watchpoints are present. */
8652 /* FIXME: This should be replacd by the deterministic execution
8653 * IRQ raising bits. */
8654 if (dc
->is_mem
&& env
->nb_watchpoints
)
8657 /* Translation stops when a conditional branch is enoutered.
8658 * Otherwise the subsequent code could get translated several times.
8659 * Also stop translation when a page boundary is reached. This
8660 * ensures prefech aborts occur at the right place. */
8661 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8662 !env
->singlestep_enabled
&&
8663 dc
->pc
< next_page_start
);
8665 /* At this stage dc->condjmp will only be set when the skipped
8666 instruction was a conditional branch or trap, and the PC has
8667 already been written. */
8668 if (__builtin_expect(env
->singlestep_enabled
, 0)) {
8669 /* Make sure the pc is updated, and raise a debug exception. */
8671 gen_set_condexec(dc
);
8672 if (dc
->is_jmp
== DISAS_SWI
) {
8673 gen_exception(EXCP_SWI
);
8675 gen_exception(EXCP_DEBUG
);
8677 gen_set_label(dc
->condlabel
);
8679 if (dc
->condjmp
|| !dc
->is_jmp
) {
8680 gen_set_pc_im(dc
->pc
);
8683 gen_set_condexec(dc
);
8684 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8685 gen_exception(EXCP_SWI
);
8687 /* FIXME: Single stepping a WFI insn will not halt
8689 gen_exception(EXCP_DEBUG
);
8692 /* While branches must always occur at the end of an IT block,
8693 there are a few other things that can cause us to terminate
8694 the TB in the middel of an IT block:
8695 - Exception generating instructions (bkpt, swi, undefined).
8697 - Hardware watchpoints.
8698 Hardware breakpoints have already been handled and skip this code.
8700 gen_set_condexec(dc
);
8701 switch(dc
->is_jmp
) {
8703 gen_goto_tb(dc
, 1, dc
->pc
);
8708 /* indicate that the hash table must be used to find the next TB */
8712 /* nothing more to generate */
8718 gen_exception(EXCP_SWI
);
8722 gen_set_label(dc
->condlabel
);
8723 gen_set_condexec(dc
);
8724 gen_goto_tb(dc
, 1, dc
->pc
);
8729 *gen_opc_ptr
= INDEX_op_end
;
8732 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
8733 fprintf(logfile
, "----------------\n");
8734 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
8735 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8736 fprintf(logfile
, "\n");
8740 j
= gen_opc_ptr
- gen_opc_buf
;
8743 gen_opc_instr_start
[lj
++] = 0;
8745 tb
->size
= dc
->pc
- pc_start
;
8750 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8752 return gen_intermediate_code_internal(env
, tb
, 0);
8755 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8757 return gen_intermediate_code_internal(env
, tb
, 1);
8760 static const char *cpu_mode_names
[16] = {
8761 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8762 "???", "???", "???", "und", "???", "???", "???", "sys"
8765 void cpu_dump_state(CPUState
*env
, FILE *f
,
8766 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8775 /* ??? This assumes float64 and double have the same layout.
8776 Oh well, it's only debug dumps. */
8784 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8786 cpu_fprintf(f
, "\n");
8788 cpu_fprintf(f
, " ");
8790 psr
= cpsr_read(env
);
8791 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8793 psr
& (1 << 31) ? 'N' : '-',
8794 psr
& (1 << 30) ? 'Z' : '-',
8795 psr
& (1 << 29) ? 'C' : '-',
8796 psr
& (1 << 28) ? 'V' : '-',
8797 psr
& CPSR_T
? 'T' : 'A',
8798 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8801 for (i
= 0; i
< 16; i
++) {
8802 d
.d
= env
->vfp
.regs
[i
];
8806 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8807 i
* 2, (int)s0
.i
, s0
.s
,
8808 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8809 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8812 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
8816 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
8817 unsigned long searched_pc
, int pc_pos
, void *puc
)
8819 env
->regs
[15] = gen_opc_pc
[pc_pos
];