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
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext
{
50 /* Nonzero if this instruction has been conditionally skipped. */
52 /* The label that will be jumped to when the instruction is skipped. */
54 /* Thumb-2 condtional execution bits. */
57 struct TranslationBlock
*tb
;
58 int singlestep_enabled
;
61 #if !defined(CONFIG_USER_ONLY)
66 #if defined(CONFIG_USER_ONLY)
69 #define IS_USER(s) (s->user)
72 /* These instructions trap after executing, so defer them until after the
73 conditional executions state has been updated. */
77 static TCGv_ptr cpu_env
;
78 /* We reuse the same 64-bit temporaries for efficiency. */
79 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
81 /* FIXME: These should be removed. */
83 static TCGv cpu_F0s
, cpu_F1s
;
84 static TCGv_i64 cpu_F0d
, cpu_F1d
;
86 #define ICOUNT_TEMP cpu_T[0]
87 #include "gen-icount.h"
89 /* initialize TCG globals. */
90 void arm_translate_init(void)
92 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
94 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
95 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
101 /* The code generator doesn't like lots of temporaries, so maintain our own
102 cache for reuse within a function. */
104 static int num_temps
;
105 static TCGv temps
[MAX_TEMPS
];
107 /* Allocate a temporary variable. */
108 static TCGv_i32
new_tmp(void)
111 if (num_temps
== MAX_TEMPS
)
114 if (GET_TCGV_I32(temps
[num_temps
]))
115 return temps
[num_temps
++];
117 tmp
= tcg_temp_new_i32();
118 temps
[num_temps
++] = tmp
;
122 /* Release a temporary variable. */
123 static void dead_tmp(TCGv tmp
)
128 if (TCGV_EQUAL(temps
[i
], tmp
))
131 /* Shuffle this temp to the last slot. */
132 while (!TCGV_EQUAL(temps
[i
], tmp
))
134 while (i
< num_temps
) {
135 temps
[i
] = temps
[i
+ 1];
141 static inline TCGv
load_cpu_offset(int offset
)
143 TCGv tmp
= new_tmp();
144 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
148 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
150 static inline void store_cpu_offset(TCGv var
, int offset
)
152 tcg_gen_st_i32(var
, cpu_env
, offset
);
156 #define store_cpu_field(var, name) \
157 store_cpu_offset(var, offsetof(CPUState, name))
159 /* Set a variable to the value of a CPU register. */
160 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
164 /* normaly, since we updated PC, we need only to add one insn */
166 addr
= (long)s
->pc
+ 2;
168 addr
= (long)s
->pc
+ 4;
169 tcg_gen_movi_i32(var
, addr
);
171 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
175 /* Create a new temporary and set it to the value of a CPU register. */
176 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
178 TCGv tmp
= new_tmp();
179 load_reg_var(s
, tmp
, reg
);
183 /* Set a CPU register. The source must be a temporary and will be
185 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
188 tcg_gen_andi_i32(var
, var
, ~1);
189 s
->is_jmp
= DISAS_JUMP
;
191 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
196 /* Basic operations. */
197 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
198 #define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
199 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
200 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
202 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
203 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
204 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
205 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
207 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
209 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
210 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
212 #define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
214 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
215 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
216 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
217 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
218 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
219 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
220 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
222 #define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
223 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
224 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
225 #define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
226 #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
228 /* Value extensions. */
229 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
230 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
231 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
232 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
234 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
235 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
237 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
239 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
240 /* Set NZCV flags from the high 4 bits of var. */
241 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
243 static void gen_exception(int excp
)
245 TCGv tmp
= new_tmp();
246 tcg_gen_movi_i32(tmp
, excp
);
247 gen_helper_exception(tmp
);
251 static void gen_smul_dual(TCGv a
, TCGv b
)
253 TCGv tmp1
= new_tmp();
254 TCGv tmp2
= new_tmp();
255 tcg_gen_ext16s_i32(tmp1
, a
);
256 tcg_gen_ext16s_i32(tmp2
, b
);
257 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
259 tcg_gen_sari_i32(a
, a
, 16);
260 tcg_gen_sari_i32(b
, b
, 16);
261 tcg_gen_mul_i32(b
, b
, a
);
262 tcg_gen_mov_i32(a
, tmp1
);
266 /* Byteswap each halfword. */
267 static void gen_rev16(TCGv var
)
269 TCGv tmp
= new_tmp();
270 tcg_gen_shri_i32(tmp
, var
, 8);
271 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
272 tcg_gen_shli_i32(var
, var
, 8);
273 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
274 tcg_gen_or_i32(var
, var
, tmp
);
278 /* Byteswap low halfword and sign extend. */
279 static void gen_revsh(TCGv var
)
281 TCGv tmp
= new_tmp();
282 tcg_gen_shri_i32(tmp
, var
, 8);
283 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
284 tcg_gen_shli_i32(var
, var
, 8);
285 tcg_gen_ext8s_i32(var
, var
);
286 tcg_gen_or_i32(var
, var
, tmp
);
290 /* Unsigned bitfield extract. */
291 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
294 tcg_gen_shri_i32(var
, var
, shift
);
295 tcg_gen_andi_i32(var
, var
, mask
);
298 /* Signed bitfield extract. */
299 static void gen_sbfx(TCGv var
, int shift
, int width
)
304 tcg_gen_sari_i32(var
, var
, shift
);
305 if (shift
+ width
< 32) {
306 signbit
= 1u << (width
- 1);
307 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
308 tcg_gen_xori_i32(var
, var
, signbit
);
309 tcg_gen_subi_i32(var
, var
, signbit
);
313 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
314 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
316 tcg_gen_andi_i32(val
, val
, mask
);
317 tcg_gen_shli_i32(val
, val
, shift
);
318 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
319 tcg_gen_or_i32(dest
, base
, val
);
322 /* Round the top 32 bits of a 64-bit value. */
323 static void gen_roundqd(TCGv a
, TCGv b
)
325 tcg_gen_shri_i32(a
, a
, 31);
326 tcg_gen_add_i32(a
, a
, b
);
329 /* FIXME: Most targets have native widening multiplication.
330 It would be good to use that instead of a full wide multiply. */
331 /* 32x32->64 multiply. Marks inputs as dead. */
332 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
334 TCGv_i64 tmp1
= tcg_temp_new_i64();
335 TCGv_i64 tmp2
= tcg_temp_new_i64();
337 tcg_gen_extu_i32_i64(tmp1
, a
);
339 tcg_gen_extu_i32_i64(tmp2
, b
);
341 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
345 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
347 TCGv_i64 tmp1
= tcg_temp_new_i64();
348 TCGv_i64 tmp2
= tcg_temp_new_i64();
350 tcg_gen_ext_i32_i64(tmp1
, a
);
352 tcg_gen_ext_i32_i64(tmp2
, b
);
354 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
358 /* Unsigned 32x32->64 multiply. */
359 static void gen_op_mull_T0_T1(void)
361 TCGv_i64 tmp1
= tcg_temp_new_i64();
362 TCGv_i64 tmp2
= tcg_temp_new_i64();
364 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
365 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
366 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
367 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
368 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
369 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
372 /* Signed 32x32->64 multiply. */
373 static void gen_imull(TCGv a
, TCGv b
)
375 TCGv_i64 tmp1
= tcg_temp_new_i64();
376 TCGv_i64 tmp2
= tcg_temp_new_i64();
378 tcg_gen_ext_i32_i64(tmp1
, a
);
379 tcg_gen_ext_i32_i64(tmp2
, b
);
380 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
381 tcg_gen_trunc_i64_i32(a
, tmp1
);
382 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
383 tcg_gen_trunc_i64_i32(b
, tmp1
);
385 #define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
387 /* Swap low and high halfwords. */
388 static void gen_swap_half(TCGv var
)
390 TCGv tmp
= new_tmp();
391 tcg_gen_shri_i32(tmp
, var
, 16);
392 tcg_gen_shli_i32(var
, var
, 16);
393 tcg_gen_or_i32(var
, var
, tmp
);
397 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
398 tmp = (t0 ^ t1) & 0x8000;
401 t0 = (t0 + t1) ^ tmp;
404 static void gen_add16(TCGv t0
, TCGv t1
)
406 TCGv tmp
= new_tmp();
407 tcg_gen_xor_i32(tmp
, t0
, t1
);
408 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
409 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
410 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
411 tcg_gen_add_i32(t0
, t0
, t1
);
412 tcg_gen_xor_i32(t0
, t0
, tmp
);
417 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
419 /* Set CF to the top bit of var. */
420 static void gen_set_CF_bit31(TCGv var
)
422 TCGv tmp
= new_tmp();
423 tcg_gen_shri_i32(tmp
, var
, 31);
428 /* Set N and Z flags from var. */
429 static inline void gen_logic_CC(TCGv var
)
431 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
432 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
436 static void gen_adc_T0_T1(void)
440 tmp
= load_cpu_field(CF
);
441 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
445 /* dest = T0 - T1 + CF - 1. */
446 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
449 tcg_gen_sub_i32(dest
, t0
, t1
);
450 tmp
= load_cpu_field(CF
);
451 tcg_gen_add_i32(dest
, dest
, tmp
);
452 tcg_gen_subi_i32(dest
, dest
, 1);
456 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
457 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
459 /* T0 &= ~T1. Clobbers T1. */
460 /* FIXME: Implement bic natively. */
461 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
463 TCGv tmp
= new_tmp();
464 tcg_gen_not_i32(tmp
, t1
);
465 tcg_gen_and_i32(dest
, t0
, tmp
);
468 static inline void gen_op_bicl_T0_T1(void)
474 /* FIXME: Implement this natively. */
475 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
477 /* FIXME: Implement this natively. */
478 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
486 tcg_gen_shri_i32(tmp
, t1
, i
);
487 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
488 tcg_gen_or_i32(t0
, t1
, tmp
);
492 static void shifter_out_im(TCGv var
, int shift
)
494 TCGv tmp
= new_tmp();
496 tcg_gen_andi_i32(tmp
, var
, 1);
498 tcg_gen_shri_i32(tmp
, var
, shift
);
500 tcg_gen_andi_i32(tmp
, tmp
, 1);
506 /* Shift by immediate. Includes special handling for shift == 0. */
507 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
513 shifter_out_im(var
, 32 - shift
);
514 tcg_gen_shli_i32(var
, var
, shift
);
520 tcg_gen_shri_i32(var
, var
, 31);
523 tcg_gen_movi_i32(var
, 0);
526 shifter_out_im(var
, shift
- 1);
527 tcg_gen_shri_i32(var
, var
, shift
);
534 shifter_out_im(var
, shift
- 1);
537 tcg_gen_sari_i32(var
, var
, shift
);
539 case 3: /* ROR/RRX */
542 shifter_out_im(var
, shift
- 1);
543 tcg_gen_rori_i32(var
, var
, shift
); break;
545 TCGv tmp
= load_cpu_field(CF
);
547 shifter_out_im(var
, 0);
548 tcg_gen_shri_i32(var
, var
, 1);
549 tcg_gen_shli_i32(tmp
, tmp
, 31);
550 tcg_gen_or_i32(var
, var
, tmp
);
556 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
557 TCGv shift
, int flags
)
561 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
562 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
563 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
564 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
568 case 0: gen_helper_shl(var
, var
, shift
); break;
569 case 1: gen_helper_shr(var
, var
, shift
); break;
570 case 2: gen_helper_sar(var
, var
, shift
); break;
571 case 3: gen_helper_ror(var
, var
, shift
); break;
577 #define PAS_OP(pfx) \
579 case 0: gen_pas_helper(glue(pfx,add16)); break; \
580 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
581 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
582 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
583 case 4: gen_pas_helper(glue(pfx,add8)); break; \
584 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
586 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
591 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
593 tmp
= tcg_temp_new_ptr();
594 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
598 tmp
= tcg_temp_new_ptr();
599 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
602 #undef gen_pas_helper
603 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
616 #undef gen_pas_helper
621 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
622 #define PAS_OP(pfx) \
624 case 0: gen_pas_helper(glue(pfx,add8)); break; \
625 case 1: gen_pas_helper(glue(pfx,add16)); break; \
626 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
627 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
628 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
629 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
631 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
636 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
638 tmp
= tcg_temp_new_ptr();
639 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
643 tmp
= tcg_temp_new_ptr();
644 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
647 #undef gen_pas_helper
648 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
661 #undef gen_pas_helper
666 static void gen_test_cc(int cc
, int label
)
674 tmp
= load_cpu_field(ZF
);
675 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
678 tmp
= load_cpu_field(ZF
);
679 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
682 tmp
= load_cpu_field(CF
);
683 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
686 tmp
= load_cpu_field(CF
);
687 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
690 tmp
= load_cpu_field(NF
);
691 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
694 tmp
= load_cpu_field(NF
);
695 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
698 tmp
= load_cpu_field(VF
);
699 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
702 tmp
= load_cpu_field(VF
);
703 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
705 case 8: /* hi: C && !Z */
706 inv
= gen_new_label();
707 tmp
= load_cpu_field(CF
);
708 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
710 tmp
= load_cpu_field(ZF
);
711 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
714 case 9: /* ls: !C || Z */
715 tmp
= load_cpu_field(CF
);
716 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
718 tmp
= load_cpu_field(ZF
);
719 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
721 case 10: /* ge: N == V -> N ^ V == 0 */
722 tmp
= load_cpu_field(VF
);
723 tmp2
= load_cpu_field(NF
);
724 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
726 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
728 case 11: /* lt: N != V -> N ^ V != 0 */
729 tmp
= load_cpu_field(VF
);
730 tmp2
= load_cpu_field(NF
);
731 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
733 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
735 case 12: /* gt: !Z && N == V */
736 inv
= gen_new_label();
737 tmp
= load_cpu_field(ZF
);
738 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
740 tmp
= load_cpu_field(VF
);
741 tmp2
= load_cpu_field(NF
);
742 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
744 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
747 case 13: /* le: Z || N != V */
748 tmp
= load_cpu_field(ZF
);
749 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
751 tmp
= load_cpu_field(VF
);
752 tmp2
= load_cpu_field(NF
);
753 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
755 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
758 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
764 static const uint8_t table_logic_cc
[16] = {
783 /* Set PC and Thumb state from an immediate address. */
784 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
788 s
->is_jmp
= DISAS_UPDATE
;
790 if (s
->thumb
!= (addr
& 1)) {
791 tcg_gen_movi_i32(tmp
, addr
& 1);
792 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
794 tcg_gen_movi_i32(tmp
, addr
& ~1);
795 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[15]));
799 /* Set PC and Thumb state from var. var is marked as dead. */
800 static inline void gen_bx(DisasContext
*s
, TCGv var
)
804 s
->is_jmp
= DISAS_UPDATE
;
806 tcg_gen_andi_i32(tmp
, var
, 1);
807 store_cpu_field(tmp
, thumb
);
808 tcg_gen_andi_i32(var
, var
, ~1);
809 store_cpu_field(var
, regs
[15]);
812 /* TODO: This should be removed. Use gen_bx instead. */
813 static inline void gen_bx_T0(DisasContext
*s
)
815 TCGv tmp
= new_tmp();
816 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
820 #if defined(CONFIG_USER_ONLY)
821 #define gen_ldst(name, s) gen_op_##name##_raw()
823 #define gen_ldst(name, s) do { \
826 gen_op_##name##_user(); \
828 gen_op_##name##_kernel(); \
831 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
833 TCGv tmp
= new_tmp();
834 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
837 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
839 TCGv tmp
= new_tmp();
840 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
843 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
845 TCGv tmp
= new_tmp();
846 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
849 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
851 TCGv tmp
= new_tmp();
852 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
855 static inline TCGv
gen_ld32(TCGv addr
, int index
)
857 TCGv tmp
= new_tmp();
858 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
861 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
863 tcg_gen_qemu_st8(val
, addr
, index
);
866 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
868 tcg_gen_qemu_st16(val
, addr
, index
);
871 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
873 tcg_gen_qemu_st32(val
, addr
, index
);
877 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
879 load_reg_var(s
, cpu_T
[0], reg
);
882 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
884 load_reg_var(s
, cpu_T
[1], reg
);
887 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
889 load_reg_var(s
, cpu_T
[2], reg
);
892 static inline void gen_set_pc_im(uint32_t val
)
894 TCGv tmp
= new_tmp();
895 tcg_gen_movi_i32(tmp
, val
);
896 store_cpu_field(tmp
, regs
[15]);
899 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
904 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
908 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
911 s
->is_jmp
= DISAS_JUMP
;
915 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
917 gen_movl_reg_TN(s
, reg
, 0);
920 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
922 gen_movl_reg_TN(s
, reg
, 1);
925 /* Force a TB lookup after an instruction that changes the CPU state. */
926 static inline void gen_lookup_tb(DisasContext
*s
)
928 gen_op_movl_T0_im(s
->pc
);
929 gen_movl_reg_T0(s
, 15);
930 s
->is_jmp
= DISAS_UPDATE
;
933 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
936 int val
, rm
, shift
, shiftop
;
939 if (!(insn
& (1 << 25))) {
942 if (!(insn
& (1 << 23)))
945 tcg_gen_addi_i32(var
, var
, val
);
949 shift
= (insn
>> 7) & 0x1f;
950 shiftop
= (insn
>> 5) & 3;
951 offset
= load_reg(s
, rm
);
952 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
953 if (!(insn
& (1 << 23)))
954 tcg_gen_sub_i32(var
, var
, offset
);
956 tcg_gen_add_i32(var
, var
, offset
);
961 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
967 if (insn
& (1 << 22)) {
969 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
970 if (!(insn
& (1 << 23)))
974 tcg_gen_addi_i32(var
, var
, val
);
978 tcg_gen_addi_i32(var
, var
, extra
);
980 offset
= load_reg(s
, rm
);
981 if (!(insn
& (1 << 23)))
982 tcg_gen_sub_i32(var
, var
, offset
);
984 tcg_gen_add_i32(var
, var
, offset
);
989 #define VFP_OP2(name) \
990 static inline void gen_vfp_##name(int dp) \
993 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
995 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
998 #define VFP_OP1(name) \
999 static inline void gen_vfp_##name(int dp, int arg) \
1002 gen_op_vfp_##name##d(arg); \
1004 gen_op_vfp_##name##s(arg); \
1014 static inline void gen_vfp_abs(int dp
)
1017 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1019 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1022 static inline void gen_vfp_neg(int dp
)
1025 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1027 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1030 static inline void gen_vfp_sqrt(int dp
)
1033 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1035 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1038 static inline void gen_vfp_cmp(int dp
)
1041 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1043 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1046 static inline void gen_vfp_cmpe(int dp
)
1049 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1051 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1054 static inline void gen_vfp_F1_ld0(int dp
)
1057 tcg_gen_movi_i64(cpu_F1d
, 0);
1059 tcg_gen_movi_i32(cpu_F1s
, 0);
1062 static inline void gen_vfp_uito(int dp
)
1065 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1067 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1070 static inline void gen_vfp_sito(int dp
)
1073 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1075 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1078 static inline void gen_vfp_toui(int dp
)
1081 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1083 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1086 static inline void gen_vfp_touiz(int dp
)
1089 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1091 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1094 static inline void gen_vfp_tosi(int dp
)
1097 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1099 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1102 static inline void gen_vfp_tosiz(int dp
)
1105 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1107 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1110 #define VFP_GEN_FIX(name) \
1111 static inline void gen_vfp_##name(int dp, int shift) \
1114 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1116 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1128 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1131 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1133 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1136 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1139 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1141 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1145 vfp_reg_offset (int dp
, int reg
)
1148 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1150 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1151 + offsetof(CPU_DoubleU
, l
.upper
);
1153 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1154 + offsetof(CPU_DoubleU
, l
.lower
);
1158 /* Return the offset of a 32-bit piece of a NEON register.
1159 zero is the least significant end of the register. */
1161 neon_reg_offset (int reg
, int n
)
1165 return vfp_reg_offset(0, sreg
);
1168 /* FIXME: Remove these. */
1169 #define neon_T0 cpu_T[0]
1170 #define neon_T1 cpu_T[1]
1171 #define NEON_GET_REG(T, reg, n) \
1172 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1173 #define NEON_SET_REG(T, reg, n) \
1174 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1176 static TCGv
neon_load_reg(int reg
, int pass
)
1178 TCGv tmp
= new_tmp();
1179 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1183 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1185 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1189 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1191 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1194 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1196 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1199 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1200 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1201 #define tcg_gen_st_f32 tcg_gen_st_i32
1202 #define tcg_gen_st_f64 tcg_gen_st_i64
1204 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1207 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1209 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1212 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1215 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1217 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1220 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1223 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1225 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1228 #define ARM_CP_RW_BIT (1 << 20)
1230 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1232 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1235 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1237 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1240 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1242 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1245 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1247 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1250 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1252 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1255 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1257 iwmmxt_store_reg(cpu_M0
, rn
);
1260 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1262 iwmmxt_load_reg(cpu_M0
, rn
);
1265 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1267 iwmmxt_load_reg(cpu_V1
, rn
);
1268 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1271 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1273 iwmmxt_load_reg(cpu_V1
, rn
);
1274 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1277 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1279 iwmmxt_load_reg(cpu_V1
, rn
);
1280 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1283 #define IWMMXT_OP(name) \
1284 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1286 iwmmxt_load_reg(cpu_V1, rn); \
1287 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1290 #define IWMMXT_OP_ENV(name) \
1291 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1293 iwmmxt_load_reg(cpu_V1, rn); \
1294 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1297 #define IWMMXT_OP_ENV_SIZE(name) \
1298 IWMMXT_OP_ENV(name##b) \
1299 IWMMXT_OP_ENV(name##w) \
1300 IWMMXT_OP_ENV(name##l)
1302 #define IWMMXT_OP_ENV1(name) \
1303 static inline void gen_op_iwmmxt_##name##_M0(void) \
1305 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1319 IWMMXT_OP_ENV_SIZE(unpackl
)
1320 IWMMXT_OP_ENV_SIZE(unpackh
)
1322 IWMMXT_OP_ENV1(unpacklub
)
1323 IWMMXT_OP_ENV1(unpackluw
)
1324 IWMMXT_OP_ENV1(unpacklul
)
1325 IWMMXT_OP_ENV1(unpackhub
)
1326 IWMMXT_OP_ENV1(unpackhuw
)
1327 IWMMXT_OP_ENV1(unpackhul
)
1328 IWMMXT_OP_ENV1(unpacklsb
)
1329 IWMMXT_OP_ENV1(unpacklsw
)
1330 IWMMXT_OP_ENV1(unpacklsl
)
1331 IWMMXT_OP_ENV1(unpackhsb
)
1332 IWMMXT_OP_ENV1(unpackhsw
)
1333 IWMMXT_OP_ENV1(unpackhsl
)
1335 IWMMXT_OP_ENV_SIZE(cmpeq
)
1336 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1337 IWMMXT_OP_ENV_SIZE(cmpgts
)
1339 IWMMXT_OP_ENV_SIZE(mins
)
1340 IWMMXT_OP_ENV_SIZE(minu
)
1341 IWMMXT_OP_ENV_SIZE(maxs
)
1342 IWMMXT_OP_ENV_SIZE(maxu
)
1344 IWMMXT_OP_ENV_SIZE(subn
)
1345 IWMMXT_OP_ENV_SIZE(addn
)
1346 IWMMXT_OP_ENV_SIZE(subu
)
1347 IWMMXT_OP_ENV_SIZE(addu
)
1348 IWMMXT_OP_ENV_SIZE(subs
)
1349 IWMMXT_OP_ENV_SIZE(adds
)
1351 IWMMXT_OP_ENV(avgb0
)
1352 IWMMXT_OP_ENV(avgb1
)
1353 IWMMXT_OP_ENV(avgw0
)
1354 IWMMXT_OP_ENV(avgw1
)
1358 IWMMXT_OP_ENV(packuw
)
1359 IWMMXT_OP_ENV(packul
)
1360 IWMMXT_OP_ENV(packuq
)
1361 IWMMXT_OP_ENV(packsw
)
1362 IWMMXT_OP_ENV(packsl
)
1363 IWMMXT_OP_ENV(packsq
)
1365 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1367 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1370 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1372 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1375 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1377 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1380 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1382 iwmmxt_load_reg(cpu_V1
, rn
);
1383 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1386 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1388 TCGv tmp
= tcg_const_i32(shift
);
1389 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1392 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1394 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1395 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1396 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1399 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1401 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1402 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1403 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1406 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1408 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1409 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1411 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1414 static void gen_op_iwmmxt_set_mup(void)
1417 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1418 tcg_gen_ori_i32(tmp
, tmp
, 2);
1419 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1422 static void gen_op_iwmmxt_set_cup(void)
1425 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1426 tcg_gen_ori_i32(tmp
, tmp
, 1);
1427 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1430 static void gen_op_iwmmxt_setpsr_nz(void)
1432 TCGv tmp
= new_tmp();
1433 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1434 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1437 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1439 iwmmxt_load_reg(cpu_V1
, rn
);
1440 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1441 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1445 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1447 iwmmxt_load_reg(cpu_V0
, rn
);
1448 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1449 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1450 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1453 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1455 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1456 iwmmxt_store_reg(cpu_V0
, rn
);
1459 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1464 rd
= (insn
>> 16) & 0xf;
1465 gen_movl_T1_reg(s
, rd
);
1467 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1468 if (insn
& (1 << 24)) {
1470 if (insn
& (1 << 23))
1471 gen_op_addl_T1_im(offset
);
1473 gen_op_addl_T1_im(-offset
);
1475 if (insn
& (1 << 21))
1476 gen_movl_reg_T1(s
, rd
);
1477 } else if (insn
& (1 << 21)) {
1479 if (insn
& (1 << 23))
1480 gen_op_movl_T0_im(offset
);
1482 gen_op_movl_T0_im(- offset
);
1483 gen_op_addl_T0_T1();
1484 gen_movl_reg_T0(s
, rd
);
1485 } else if (!(insn
& (1 << 23)))
1490 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1492 int rd
= (insn
>> 0) & 0xf;
1494 if (insn
& (1 << 8))
1495 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1498 gen_op_iwmmxt_movl_T0_wCx(rd
);
1500 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1502 gen_op_movl_T1_im(mask
);
1503 gen_op_andl_T0_T1();
1507 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1508 (ie. an undefined instruction). */
1509 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1512 int rdhi
, rdlo
, rd0
, rd1
, i
;
1515 if ((insn
& 0x0e000e00) == 0x0c000000) {
1516 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1518 rdlo
= (insn
>> 12) & 0xf;
1519 rdhi
= (insn
>> 16) & 0xf;
1520 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1521 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1522 gen_movl_reg_T0(s
, rdlo
);
1523 gen_movl_reg_T1(s
, rdhi
);
1524 } else { /* TMCRR */
1525 gen_movl_T0_reg(s
, rdlo
);
1526 gen_movl_T1_reg(s
, rdhi
);
1527 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1528 gen_op_iwmmxt_set_mup();
1533 wrd
= (insn
>> 12) & 0xf;
1534 if (gen_iwmmxt_address(s
, insn
))
1536 if (insn
& ARM_CP_RW_BIT
) {
1537 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1538 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1539 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1541 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1544 if (insn
& (1 << 8)) {
1545 if (insn
& (1 << 22)) { /* WLDRD */
1546 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1548 } else { /* WLDRW wRd */
1549 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1552 if (insn
& (1 << 22)) { /* WLDRH */
1553 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1554 } else { /* WLDRB */
1555 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1559 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1562 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1565 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1566 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1568 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1569 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1571 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1573 if (insn
& (1 << 8)) {
1574 if (insn
& (1 << 22)) { /* WSTRD */
1576 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1577 } else { /* WSTRW wRd */
1578 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1579 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1582 if (insn
& (1 << 22)) { /* WSTRH */
1583 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1584 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1585 } else { /* WSTRB */
1586 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1587 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1595 if ((insn
& 0x0f000000) != 0x0e000000)
1598 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1599 case 0x000: /* WOR */
1600 wrd
= (insn
>> 12) & 0xf;
1601 rd0
= (insn
>> 0) & 0xf;
1602 rd1
= (insn
>> 16) & 0xf;
1603 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1604 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1605 gen_op_iwmmxt_setpsr_nz();
1606 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1607 gen_op_iwmmxt_set_mup();
1608 gen_op_iwmmxt_set_cup();
1610 case 0x011: /* TMCR */
1613 rd
= (insn
>> 12) & 0xf;
1614 wrd
= (insn
>> 16) & 0xf;
1616 case ARM_IWMMXT_wCID
:
1617 case ARM_IWMMXT_wCASF
:
1619 case ARM_IWMMXT_wCon
:
1620 gen_op_iwmmxt_set_cup();
1622 case ARM_IWMMXT_wCSSF
:
1623 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1624 gen_movl_T1_reg(s
, rd
);
1625 gen_op_bicl_T0_T1();
1626 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1628 case ARM_IWMMXT_wCGR0
:
1629 case ARM_IWMMXT_wCGR1
:
1630 case ARM_IWMMXT_wCGR2
:
1631 case ARM_IWMMXT_wCGR3
:
1632 gen_op_iwmmxt_set_cup();
1633 gen_movl_reg_T0(s
, rd
);
1634 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1640 case 0x100: /* WXOR */
1641 wrd
= (insn
>> 12) & 0xf;
1642 rd0
= (insn
>> 0) & 0xf;
1643 rd1
= (insn
>> 16) & 0xf;
1644 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1645 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1646 gen_op_iwmmxt_setpsr_nz();
1647 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1648 gen_op_iwmmxt_set_mup();
1649 gen_op_iwmmxt_set_cup();
1651 case 0x111: /* TMRC */
1654 rd
= (insn
>> 12) & 0xf;
1655 wrd
= (insn
>> 16) & 0xf;
1656 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1657 gen_movl_reg_T0(s
, rd
);
1659 case 0x300: /* WANDN */
1660 wrd
= (insn
>> 12) & 0xf;
1661 rd0
= (insn
>> 0) & 0xf;
1662 rd1
= (insn
>> 16) & 0xf;
1663 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1664 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1665 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1666 gen_op_iwmmxt_setpsr_nz();
1667 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1668 gen_op_iwmmxt_set_mup();
1669 gen_op_iwmmxt_set_cup();
1671 case 0x200: /* WAND */
1672 wrd
= (insn
>> 12) & 0xf;
1673 rd0
= (insn
>> 0) & 0xf;
1674 rd1
= (insn
>> 16) & 0xf;
1675 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1676 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1677 gen_op_iwmmxt_setpsr_nz();
1678 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1679 gen_op_iwmmxt_set_mup();
1680 gen_op_iwmmxt_set_cup();
1682 case 0x810: case 0xa10: /* WMADD */
1683 wrd
= (insn
>> 12) & 0xf;
1684 rd0
= (insn
>> 0) & 0xf;
1685 rd1
= (insn
>> 16) & 0xf;
1686 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1687 if (insn
& (1 << 21))
1688 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1690 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1691 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1692 gen_op_iwmmxt_set_mup();
1694 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1695 wrd
= (insn
>> 12) & 0xf;
1696 rd0
= (insn
>> 16) & 0xf;
1697 rd1
= (insn
>> 0) & 0xf;
1698 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1699 switch ((insn
>> 22) & 3) {
1701 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1704 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1707 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1712 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1713 gen_op_iwmmxt_set_mup();
1714 gen_op_iwmmxt_set_cup();
1716 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1717 wrd
= (insn
>> 12) & 0xf;
1718 rd0
= (insn
>> 16) & 0xf;
1719 rd1
= (insn
>> 0) & 0xf;
1720 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1721 switch ((insn
>> 22) & 3) {
1723 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1726 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1729 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1734 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1735 gen_op_iwmmxt_set_mup();
1736 gen_op_iwmmxt_set_cup();
1738 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1739 wrd
= (insn
>> 12) & 0xf;
1740 rd0
= (insn
>> 16) & 0xf;
1741 rd1
= (insn
>> 0) & 0xf;
1742 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1743 if (insn
& (1 << 22))
1744 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1746 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1747 if (!(insn
& (1 << 20)))
1748 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1749 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1750 gen_op_iwmmxt_set_mup();
1752 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1753 wrd
= (insn
>> 12) & 0xf;
1754 rd0
= (insn
>> 16) & 0xf;
1755 rd1
= (insn
>> 0) & 0xf;
1756 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1757 if (insn
& (1 << 21)) {
1758 if (insn
& (1 << 20))
1759 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1761 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1763 if (insn
& (1 << 20))
1764 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1766 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1768 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1769 gen_op_iwmmxt_set_mup();
1771 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1772 wrd
= (insn
>> 12) & 0xf;
1773 rd0
= (insn
>> 16) & 0xf;
1774 rd1
= (insn
>> 0) & 0xf;
1775 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1776 if (insn
& (1 << 21))
1777 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1779 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1780 if (!(insn
& (1 << 20))) {
1781 iwmmxt_load_reg(cpu_V1
, wrd
);
1782 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1784 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1785 gen_op_iwmmxt_set_mup();
1787 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1788 wrd
= (insn
>> 12) & 0xf;
1789 rd0
= (insn
>> 16) & 0xf;
1790 rd1
= (insn
>> 0) & 0xf;
1791 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1792 switch ((insn
>> 22) & 3) {
1794 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1797 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1800 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1805 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1806 gen_op_iwmmxt_set_mup();
1807 gen_op_iwmmxt_set_cup();
1809 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1810 wrd
= (insn
>> 12) & 0xf;
1811 rd0
= (insn
>> 16) & 0xf;
1812 rd1
= (insn
>> 0) & 0xf;
1813 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1814 if (insn
& (1 << 22)) {
1815 if (insn
& (1 << 20))
1816 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1818 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1820 if (insn
& (1 << 20))
1821 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1823 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1825 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1826 gen_op_iwmmxt_set_mup();
1827 gen_op_iwmmxt_set_cup();
1829 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1830 wrd
= (insn
>> 12) & 0xf;
1831 rd0
= (insn
>> 16) & 0xf;
1832 rd1
= (insn
>> 0) & 0xf;
1833 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1834 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1835 gen_op_movl_T1_im(7);
1836 gen_op_andl_T0_T1();
1837 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1838 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1839 gen_op_iwmmxt_set_mup();
1841 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1842 rd
= (insn
>> 12) & 0xf;
1843 wrd
= (insn
>> 16) & 0xf;
1844 gen_movl_T0_reg(s
, rd
);
1845 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1846 switch ((insn
>> 6) & 3) {
1848 gen_op_movl_T1_im(0xff);
1849 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1852 gen_op_movl_T1_im(0xffff);
1853 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1856 gen_op_movl_T1_im(0xffffffff);
1857 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1862 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1863 gen_op_iwmmxt_set_mup();
1865 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1866 rd
= (insn
>> 12) & 0xf;
1867 wrd
= (insn
>> 16) & 0xf;
1870 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1871 switch ((insn
>> 22) & 3) {
1874 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1876 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1881 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1883 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1887 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1892 gen_movl_reg_T0(s
, rd
);
1894 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1895 if ((insn
& 0x000ff008) != 0x0003f000)
1897 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1898 switch ((insn
>> 22) & 3) {
1900 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1903 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1906 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1911 gen_op_shll_T1_im(28);
1912 gen_set_nzcv(cpu_T
[1]);
1914 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1915 rd
= (insn
>> 12) & 0xf;
1916 wrd
= (insn
>> 16) & 0xf;
1917 gen_movl_T0_reg(s
, rd
);
1918 switch ((insn
>> 6) & 3) {
1920 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1923 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1926 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1931 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1932 gen_op_iwmmxt_set_mup();
1934 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1935 if ((insn
& 0x000ff00f) != 0x0003f000)
1937 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1938 switch ((insn
>> 22) & 3) {
1940 for (i
= 0; i
< 7; i
++) {
1941 gen_op_shll_T1_im(4);
1942 gen_op_andl_T0_T1();
1946 for (i
= 0; i
< 3; i
++) {
1947 gen_op_shll_T1_im(8);
1948 gen_op_andl_T0_T1();
1952 gen_op_shll_T1_im(16);
1953 gen_op_andl_T0_T1();
1958 gen_set_nzcv(cpu_T
[0]);
1960 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1961 wrd
= (insn
>> 12) & 0xf;
1962 rd0
= (insn
>> 16) & 0xf;
1963 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1964 switch ((insn
>> 22) & 3) {
1966 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1969 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1972 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1977 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1978 gen_op_iwmmxt_set_mup();
1980 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1981 if ((insn
& 0x000ff00f) != 0x0003f000)
1983 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1984 switch ((insn
>> 22) & 3) {
1986 for (i
= 0; i
< 7; i
++) {
1987 gen_op_shll_T1_im(4);
1992 for (i
= 0; i
< 3; i
++) {
1993 gen_op_shll_T1_im(8);
1998 gen_op_shll_T1_im(16);
2004 gen_set_nzcv(cpu_T
[0]);
2006 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2007 rd
= (insn
>> 12) & 0xf;
2008 rd0
= (insn
>> 16) & 0xf;
2009 if ((insn
& 0xf) != 0)
2011 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2012 switch ((insn
>> 22) & 3) {
2014 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
2017 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
2020 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
2025 gen_movl_reg_T0(s
, rd
);
2027 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2028 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2029 wrd
= (insn
>> 12) & 0xf;
2030 rd0
= (insn
>> 16) & 0xf;
2031 rd1
= (insn
>> 0) & 0xf;
2032 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2033 switch ((insn
>> 22) & 3) {
2035 if (insn
& (1 << 21))
2036 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2038 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2041 if (insn
& (1 << 21))
2042 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2044 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2047 if (insn
& (1 << 21))
2048 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2050 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2055 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2056 gen_op_iwmmxt_set_mup();
2057 gen_op_iwmmxt_set_cup();
2059 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2060 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2061 wrd
= (insn
>> 12) & 0xf;
2062 rd0
= (insn
>> 16) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2064 switch ((insn
>> 22) & 3) {
2066 if (insn
& (1 << 21))
2067 gen_op_iwmmxt_unpacklsb_M0();
2069 gen_op_iwmmxt_unpacklub_M0();
2072 if (insn
& (1 << 21))
2073 gen_op_iwmmxt_unpacklsw_M0();
2075 gen_op_iwmmxt_unpackluw_M0();
2078 if (insn
& (1 << 21))
2079 gen_op_iwmmxt_unpacklsl_M0();
2081 gen_op_iwmmxt_unpacklul_M0();
2086 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2087 gen_op_iwmmxt_set_mup();
2088 gen_op_iwmmxt_set_cup();
2090 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2091 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2092 wrd
= (insn
>> 12) & 0xf;
2093 rd0
= (insn
>> 16) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2095 switch ((insn
>> 22) & 3) {
2097 if (insn
& (1 << 21))
2098 gen_op_iwmmxt_unpackhsb_M0();
2100 gen_op_iwmmxt_unpackhub_M0();
2103 if (insn
& (1 << 21))
2104 gen_op_iwmmxt_unpackhsw_M0();
2106 gen_op_iwmmxt_unpackhuw_M0();
2109 if (insn
& (1 << 21))
2110 gen_op_iwmmxt_unpackhsl_M0();
2112 gen_op_iwmmxt_unpackhul_M0();
2117 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2118 gen_op_iwmmxt_set_mup();
2119 gen_op_iwmmxt_set_cup();
2121 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2122 case 0x214: case 0x614: case 0xa14: case 0xe14:
2123 wrd
= (insn
>> 12) & 0xf;
2124 rd0
= (insn
>> 16) & 0xf;
2125 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2126 if (gen_iwmmxt_shift(insn
, 0xff))
2128 switch ((insn
>> 22) & 3) {
2132 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2135 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2138 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2141 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2142 gen_op_iwmmxt_set_mup();
2143 gen_op_iwmmxt_set_cup();
2145 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2146 case 0x014: case 0x414: case 0x814: case 0xc14:
2147 wrd
= (insn
>> 12) & 0xf;
2148 rd0
= (insn
>> 16) & 0xf;
2149 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2150 if (gen_iwmmxt_shift(insn
, 0xff))
2152 switch ((insn
>> 22) & 3) {
2156 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2159 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2162 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2165 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2166 gen_op_iwmmxt_set_mup();
2167 gen_op_iwmmxt_set_cup();
2169 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2170 case 0x114: case 0x514: case 0x914: case 0xd14:
2171 wrd
= (insn
>> 12) & 0xf;
2172 rd0
= (insn
>> 16) & 0xf;
2173 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2174 if (gen_iwmmxt_shift(insn
, 0xff))
2176 switch ((insn
>> 22) & 3) {
2180 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2183 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2186 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2189 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2190 gen_op_iwmmxt_set_mup();
2191 gen_op_iwmmxt_set_cup();
2193 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2194 case 0x314: case 0x714: case 0xb14: case 0xf14:
2195 wrd
= (insn
>> 12) & 0xf;
2196 rd0
= (insn
>> 16) & 0xf;
2197 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2198 switch ((insn
>> 22) & 3) {
2202 if (gen_iwmmxt_shift(insn
, 0xf))
2204 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2207 if (gen_iwmmxt_shift(insn
, 0x1f))
2209 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2212 if (gen_iwmmxt_shift(insn
, 0x3f))
2214 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2217 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2218 gen_op_iwmmxt_set_mup();
2219 gen_op_iwmmxt_set_cup();
2221 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2222 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2223 wrd
= (insn
>> 12) & 0xf;
2224 rd0
= (insn
>> 16) & 0xf;
2225 rd1
= (insn
>> 0) & 0xf;
2226 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2227 switch ((insn
>> 22) & 3) {
2229 if (insn
& (1 << 21))
2230 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2232 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2235 if (insn
& (1 << 21))
2236 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2238 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2241 if (insn
& (1 << 21))
2242 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2244 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2249 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2250 gen_op_iwmmxt_set_mup();
2252 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2253 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2254 wrd
= (insn
>> 12) & 0xf;
2255 rd0
= (insn
>> 16) & 0xf;
2256 rd1
= (insn
>> 0) & 0xf;
2257 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2258 switch ((insn
>> 22) & 3) {
2260 if (insn
& (1 << 21))
2261 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2263 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2266 if (insn
& (1 << 21))
2267 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2269 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2272 if (insn
& (1 << 21))
2273 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2275 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2280 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2281 gen_op_iwmmxt_set_mup();
2283 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2284 case 0x402: case 0x502: case 0x602: case 0x702:
2285 wrd
= (insn
>> 12) & 0xf;
2286 rd0
= (insn
>> 16) & 0xf;
2287 rd1
= (insn
>> 0) & 0xf;
2288 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2289 gen_op_movl_T0_im((insn
>> 20) & 3);
2290 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2291 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2292 gen_op_iwmmxt_set_mup();
2294 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2295 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2296 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2297 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2298 wrd
= (insn
>> 12) & 0xf;
2299 rd0
= (insn
>> 16) & 0xf;
2300 rd1
= (insn
>> 0) & 0xf;
2301 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2302 switch ((insn
>> 20) & 0xf) {
2304 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2307 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2310 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2313 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2316 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2319 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2322 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2325 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2328 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2333 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2334 gen_op_iwmmxt_set_mup();
2335 gen_op_iwmmxt_set_cup();
2337 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2338 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2339 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2340 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2341 wrd
= (insn
>> 12) & 0xf;
2342 rd0
= (insn
>> 16) & 0xf;
2343 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2344 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2345 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2346 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2347 gen_op_iwmmxt_set_mup();
2348 gen_op_iwmmxt_set_cup();
2350 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2351 case 0x418: case 0x518: case 0x618: case 0x718:
2352 case 0x818: case 0x918: case 0xa18: case 0xb18:
2353 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2354 wrd
= (insn
>> 12) & 0xf;
2355 rd0
= (insn
>> 16) & 0xf;
2356 rd1
= (insn
>> 0) & 0xf;
2357 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2358 switch ((insn
>> 20) & 0xf) {
2360 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2363 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2366 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2369 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2372 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2375 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2378 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2381 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2384 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2389 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2390 gen_op_iwmmxt_set_mup();
2391 gen_op_iwmmxt_set_cup();
2393 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2394 case 0x408: case 0x508: case 0x608: case 0x708:
2395 case 0x808: case 0x908: case 0xa08: case 0xb08:
2396 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2397 wrd
= (insn
>> 12) & 0xf;
2398 rd0
= (insn
>> 16) & 0xf;
2399 rd1
= (insn
>> 0) & 0xf;
2400 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2401 if (!(insn
& (1 << 20)))
2403 switch ((insn
>> 22) & 3) {
2407 if (insn
& (1 << 21))
2408 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2410 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2413 if (insn
& (1 << 21))
2414 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2416 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2419 if (insn
& (1 << 21))
2420 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2422 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2425 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2426 gen_op_iwmmxt_set_mup();
2427 gen_op_iwmmxt_set_cup();
2429 case 0x201: case 0x203: case 0x205: case 0x207:
2430 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2431 case 0x211: case 0x213: case 0x215: case 0x217:
2432 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2433 wrd
= (insn
>> 5) & 0xf;
2434 rd0
= (insn
>> 12) & 0xf;
2435 rd1
= (insn
>> 0) & 0xf;
2436 if (rd0
== 0xf || rd1
== 0xf)
2438 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2439 switch ((insn
>> 16) & 0xf) {
2440 case 0x0: /* TMIA */
2441 gen_movl_T0_reg(s
, rd0
);
2442 gen_movl_T1_reg(s
, rd1
);
2443 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2445 case 0x8: /* TMIAPH */
2446 gen_movl_T0_reg(s
, rd0
);
2447 gen_movl_T1_reg(s
, rd1
);
2448 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2450 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2451 gen_movl_T1_reg(s
, rd0
);
2452 if (insn
& (1 << 16))
2453 gen_op_shrl_T1_im(16);
2454 gen_op_movl_T0_T1();
2455 gen_movl_T1_reg(s
, rd1
);
2456 if (insn
& (1 << 17))
2457 gen_op_shrl_T1_im(16);
2458 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2463 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2464 gen_op_iwmmxt_set_mup();
2473 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2474 (ie. an undefined instruction). */
2475 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2477 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2479 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2480 /* Multiply with Internal Accumulate Format */
2481 rd0
= (insn
>> 12) & 0xf;
2483 acc
= (insn
>> 5) & 7;
2488 switch ((insn
>> 16) & 0xf) {
2490 gen_movl_T0_reg(s
, rd0
);
2491 gen_movl_T1_reg(s
, rd1
);
2492 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2494 case 0x8: /* MIAPH */
2495 gen_movl_T0_reg(s
, rd0
);
2496 gen_movl_T1_reg(s
, rd1
);
2497 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2499 case 0xc: /* MIABB */
2500 case 0xd: /* MIABT */
2501 case 0xe: /* MIATB */
2502 case 0xf: /* MIATT */
2503 gen_movl_T1_reg(s
, rd0
);
2504 if (insn
& (1 << 16))
2505 gen_op_shrl_T1_im(16);
2506 gen_op_movl_T0_T1();
2507 gen_movl_T1_reg(s
, rd1
);
2508 if (insn
& (1 << 17))
2509 gen_op_shrl_T1_im(16);
2510 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2516 gen_op_iwmmxt_movq_wRn_M0(acc
);
2520 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2521 /* Internal Accumulator Access Format */
2522 rdhi
= (insn
>> 16) & 0xf;
2523 rdlo
= (insn
>> 12) & 0xf;
2529 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2530 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2531 gen_movl_reg_T0(s
, rdlo
);
2532 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2533 gen_op_andl_T0_T1();
2534 gen_movl_reg_T0(s
, rdhi
);
2536 gen_movl_T0_reg(s
, rdlo
);
2537 gen_movl_T1_reg(s
, rdhi
);
2538 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2546 /* Disassemble system coprocessor instruction. Return nonzero if
2547 instruction is not defined. */
2548 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2551 uint32_t rd
= (insn
>> 12) & 0xf;
2552 uint32_t cp
= (insn
>> 8) & 0xf;
2557 if (insn
& ARM_CP_RW_BIT
) {
2558 if (!env
->cp
[cp
].cp_read
)
2560 gen_set_pc_im(s
->pc
);
2562 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2563 store_reg(s
, rd
, tmp
);
2565 if (!env
->cp
[cp
].cp_write
)
2567 gen_set_pc_im(s
->pc
);
2568 tmp
= load_reg(s
, rd
);
2569 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2575 static int cp15_user_ok(uint32_t insn
)
2577 int cpn
= (insn
>> 16) & 0xf;
2578 int cpm
= insn
& 0xf;
2579 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2581 if (cpn
== 13 && cpm
== 0) {
2583 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2587 /* ISB, DSB, DMB. */
2588 if ((cpm
== 5 && op
== 4)
2589 || (cpm
== 10 && (op
== 4 || op
== 5)))
2595 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2596 instruction is not defined. */
2597 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2602 /* M profile cores use memory mapped registers instead of cp15. */
2603 if (arm_feature(env
, ARM_FEATURE_M
))
2606 if ((insn
& (1 << 25)) == 0) {
2607 if (insn
& (1 << 20)) {
2611 /* mcrr. Used for block cache operations, so implement as no-op. */
2614 if ((insn
& (1 << 4)) == 0) {
2618 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2621 if ((insn
& 0x0fff0fff) == 0x0e070f90
2622 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2623 /* Wait for interrupt. */
2624 gen_set_pc_im(s
->pc
);
2625 s
->is_jmp
= DISAS_WFI
;
2628 rd
= (insn
>> 12) & 0xf;
2629 if (insn
& ARM_CP_RW_BIT
) {
2631 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2632 /* If the destination register is r15 then sets condition codes. */
2634 store_reg(s
, rd
, tmp
);
2638 tmp
= load_reg(s
, rd
);
2639 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2641 /* Normally we would always end the TB here, but Linux
2642 * arch/arm/mach-pxa/sleep.S expects two instructions following
2643 * an MMU enable to execute from cache. Imitate this behaviour. */
2644 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2645 (insn
& 0x0fff0fff) != 0x0e010f10)
2651 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2652 #define VFP_SREG(insn, bigbit, smallbit) \
2653 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2654 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2655 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2656 reg = (((insn) >> (bigbit)) & 0x0f) \
2657 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2659 if (insn & (1 << (smallbit))) \
2661 reg = ((insn) >> (bigbit)) & 0x0f; \
2664 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2665 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2666 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2667 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2668 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2669 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2671 /* Move between integer and VFP cores. */
2672 static TCGv
gen_vfp_mrs(void)
2674 TCGv tmp
= new_tmp();
2675 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2679 static void gen_vfp_msr(TCGv tmp
)
2681 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2686 vfp_enabled(CPUState
* env
)
2688 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2691 static void gen_neon_dup_u8(TCGv var
, int shift
)
2693 TCGv tmp
= new_tmp();
2695 tcg_gen_shri_i32(var
, var
, shift
);
2696 tcg_gen_ext8u_i32(var
, var
);
2697 tcg_gen_shli_i32(tmp
, var
, 8);
2698 tcg_gen_or_i32(var
, var
, tmp
);
2699 tcg_gen_shli_i32(tmp
, var
, 16);
2700 tcg_gen_or_i32(var
, var
, tmp
);
2704 static void gen_neon_dup_low16(TCGv var
)
2706 TCGv tmp
= new_tmp();
2707 tcg_gen_ext16u_i32(var
, var
);
2708 tcg_gen_shli_i32(tmp
, var
, 16);
2709 tcg_gen_or_i32(var
, var
, tmp
);
2713 static void gen_neon_dup_high16(TCGv var
)
2715 TCGv tmp
= new_tmp();
2716 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2717 tcg_gen_shri_i32(tmp
, var
, 16);
2718 tcg_gen_or_i32(var
, var
, tmp
);
2722 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2723 (ie. an undefined instruction). */
2724 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2726 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2731 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2734 if (!vfp_enabled(env
)) {
2735 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2736 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2738 rn
= (insn
>> 16) & 0xf;
2739 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2740 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2743 dp
= ((insn
& 0xf00) == 0xb00);
2744 switch ((insn
>> 24) & 0xf) {
2746 if (insn
& (1 << 4)) {
2747 /* single register transfer */
2748 rd
= (insn
>> 12) & 0xf;
2753 VFP_DREG_N(rn
, insn
);
2756 if (insn
& 0x00c00060
2757 && !arm_feature(env
, ARM_FEATURE_NEON
))
2760 pass
= (insn
>> 21) & 1;
2761 if (insn
& (1 << 22)) {
2763 offset
= ((insn
>> 5) & 3) * 8;
2764 } else if (insn
& (1 << 5)) {
2766 offset
= (insn
& (1 << 6)) ? 16 : 0;
2771 if (insn
& ARM_CP_RW_BIT
) {
2773 tmp
= neon_load_reg(rn
, pass
);
2777 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2778 if (insn
& (1 << 23))
2784 if (insn
& (1 << 23)) {
2786 tcg_gen_shri_i32(tmp
, tmp
, 16);
2792 tcg_gen_sari_i32(tmp
, tmp
, 16);
2801 store_reg(s
, rd
, tmp
);
2804 tmp
= load_reg(s
, rd
);
2805 if (insn
& (1 << 23)) {
2808 gen_neon_dup_u8(tmp
, 0);
2809 } else if (size
== 1) {
2810 gen_neon_dup_low16(tmp
);
2813 tcg_gen_mov_i32(tmp2
, tmp
);
2814 neon_store_reg(rn
, 0, tmp2
);
2815 neon_store_reg(rn
, 1, tmp
);
2820 tmp2
= neon_load_reg(rn
, pass
);
2821 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2825 tmp2
= neon_load_reg(rn
, pass
);
2826 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2832 neon_store_reg(rn
, pass
, tmp
);
2836 if ((insn
& 0x6f) != 0x00)
2838 rn
= VFP_SREG_N(insn
);
2839 if (insn
& ARM_CP_RW_BIT
) {
2841 if (insn
& (1 << 21)) {
2842 /* system register */
2847 /* VFP2 allows access to FSID from userspace.
2848 VFP3 restricts all id registers to privileged
2851 && arm_feature(env
, ARM_FEATURE_VFP3
))
2853 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2858 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2860 case ARM_VFP_FPINST
:
2861 case ARM_VFP_FPINST2
:
2862 /* Not present in VFP3. */
2864 || arm_feature(env
, ARM_FEATURE_VFP3
))
2866 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2870 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2871 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2874 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2880 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2882 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2888 gen_mov_F0_vreg(0, rn
);
2889 tmp
= gen_vfp_mrs();
2892 /* Set the 4 flag bits in the CPSR. */
2896 store_reg(s
, rd
, tmp
);
2900 tmp
= load_reg(s
, rd
);
2901 if (insn
& (1 << 21)) {
2903 /* system register */
2908 /* Writes are ignored. */
2911 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2918 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2921 case ARM_VFP_FPINST
:
2922 case ARM_VFP_FPINST2
:
2923 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2930 gen_mov_vreg_F0(0, rn
);
2935 /* data processing */
2936 /* The opcode is in bits 23, 21, 20 and 6. */
2937 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2941 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2943 /* rn is register number */
2944 VFP_DREG_N(rn
, insn
);
2947 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2948 /* Integer or single precision destination. */
2949 rd
= VFP_SREG_D(insn
);
2951 VFP_DREG_D(rd
, insn
);
2954 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2955 /* Integer source. */
2956 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2958 VFP_DREG_M(rm
, insn
);
2961 rn
= VFP_SREG_N(insn
);
2962 if (op
== 15 && rn
== 15) {
2963 /* Double precision destination. */
2964 VFP_DREG_D(rd
, insn
);
2966 rd
= VFP_SREG_D(insn
);
2968 rm
= VFP_SREG_M(insn
);
2971 veclen
= env
->vfp
.vec_len
;
2972 if (op
== 15 && rn
> 3)
2975 /* Shut up compiler warnings. */
2986 /* Figure out what type of vector operation this is. */
2987 if ((rd
& bank_mask
) == 0) {
2992 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2994 delta_d
= env
->vfp
.vec_stride
+ 1;
2996 if ((rm
& bank_mask
) == 0) {
2997 /* mixed scalar/vector */
3006 /* Load the initial operands. */
3011 /* Integer source */
3012 gen_mov_F0_vreg(0, rm
);
3017 gen_mov_F0_vreg(dp
, rd
);
3018 gen_mov_F1_vreg(dp
, rm
);
3022 /* Compare with zero */
3023 gen_mov_F0_vreg(dp
, rd
);
3030 /* Source and destination the same. */
3031 gen_mov_F0_vreg(dp
, rd
);
3034 /* One source operand. */
3035 gen_mov_F0_vreg(dp
, rm
);
3039 /* Two source operands. */
3040 gen_mov_F0_vreg(dp
, rn
);
3041 gen_mov_F1_vreg(dp
, rm
);
3045 /* Perform the calculation. */
3047 case 0: /* mac: fd + (fn * fm) */
3049 gen_mov_F1_vreg(dp
, rd
);
3052 case 1: /* nmac: fd - (fn * fm) */
3055 gen_mov_F1_vreg(dp
, rd
);
3058 case 2: /* msc: -fd + (fn * fm) */
3060 gen_mov_F1_vreg(dp
, rd
);
3063 case 3: /* nmsc: -fd - (fn * fm) */
3066 gen_mov_F1_vreg(dp
, rd
);
3069 case 4: /* mul: fn * fm */
3072 case 5: /* nmul: -(fn * fm) */
3076 case 6: /* add: fn + fm */
3079 case 7: /* sub: fn - fm */
3082 case 8: /* div: fn / fm */
3085 case 14: /* fconst */
3086 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3089 n
= (insn
<< 12) & 0x80000000;
3090 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3097 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3104 tcg_gen_movi_i32(cpu_F0s
, n
);
3107 case 15: /* extension space */
3130 case 11: /* cmpez */
3134 case 15: /* single<->double conversion */
3136 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3138 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3140 case 16: /* fuito */
3143 case 17: /* fsito */
3146 case 20: /* fshto */
3147 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3149 gen_vfp_shto(dp
, rm
);
3151 case 21: /* fslto */
3152 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3154 gen_vfp_slto(dp
, rm
);
3156 case 22: /* fuhto */
3157 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3159 gen_vfp_uhto(dp
, rm
);
3161 case 23: /* fulto */
3162 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3164 gen_vfp_ulto(dp
, rm
);
3166 case 24: /* ftoui */
3169 case 25: /* ftouiz */
3172 case 26: /* ftosi */
3175 case 27: /* ftosiz */
3178 case 28: /* ftosh */
3179 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3181 gen_vfp_tosh(dp
, rm
);
3183 case 29: /* ftosl */
3184 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3186 gen_vfp_tosl(dp
, rm
);
3188 case 30: /* ftouh */
3189 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3191 gen_vfp_touh(dp
, rm
);
3193 case 31: /* ftoul */
3194 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3196 gen_vfp_toul(dp
, rm
);
3198 default: /* undefined */
3199 printf ("rn:%d\n", rn
);
3203 default: /* undefined */
3204 printf ("op:%d\n", op
);
3208 /* Write back the result. */
3209 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3210 ; /* Comparison, do nothing. */
3211 else if (op
== 15 && rn
> 17)
3212 /* Integer result. */
3213 gen_mov_vreg_F0(0, rd
);
3214 else if (op
== 15 && rn
== 15)
3216 gen_mov_vreg_F0(!dp
, rd
);
3218 gen_mov_vreg_F0(dp
, rd
);
3220 /* break out of the loop if we have finished */
3224 if (op
== 15 && delta_m
== 0) {
3225 /* single source one-many */
3227 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3229 gen_mov_vreg_F0(dp
, rd
);
3233 /* Setup the next operands. */
3235 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3239 /* One source operand. */
3240 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3242 gen_mov_F0_vreg(dp
, rm
);
3244 /* Two source operands. */
3245 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3247 gen_mov_F0_vreg(dp
, rn
);
3249 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3251 gen_mov_F1_vreg(dp
, rm
);
3259 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3260 /* two-register transfer */
3261 rn
= (insn
>> 16) & 0xf;
3262 rd
= (insn
>> 12) & 0xf;
3264 VFP_DREG_M(rm
, insn
);
3266 rm
= VFP_SREG_M(insn
);
3269 if (insn
& ARM_CP_RW_BIT
) {
3272 gen_mov_F0_vreg(0, rm
* 2);
3273 tmp
= gen_vfp_mrs();
3274 store_reg(s
, rd
, tmp
);
3275 gen_mov_F0_vreg(0, rm
* 2 + 1);
3276 tmp
= gen_vfp_mrs();
3277 store_reg(s
, rn
, tmp
);
3279 gen_mov_F0_vreg(0, rm
);
3280 tmp
= gen_vfp_mrs();
3281 store_reg(s
, rn
, tmp
);
3282 gen_mov_F0_vreg(0, rm
+ 1);
3283 tmp
= gen_vfp_mrs();
3284 store_reg(s
, rd
, tmp
);
3289 tmp
= load_reg(s
, rd
);
3291 gen_mov_vreg_F0(0, rm
* 2);
3292 tmp
= load_reg(s
, rn
);
3294 gen_mov_vreg_F0(0, rm
* 2 + 1);
3296 tmp
= load_reg(s
, rn
);
3298 gen_mov_vreg_F0(0, rm
);
3299 tmp
= load_reg(s
, rd
);
3301 gen_mov_vreg_F0(0, rm
+ 1);
3306 rn
= (insn
>> 16) & 0xf;
3308 VFP_DREG_D(rd
, insn
);
3310 rd
= VFP_SREG_D(insn
);
3311 if (s
->thumb
&& rn
== 15) {
3312 gen_op_movl_T1_im(s
->pc
& ~2);
3314 gen_movl_T1_reg(s
, rn
);
3316 if ((insn
& 0x01200000) == 0x01000000) {
3317 /* Single load/store */
3318 offset
= (insn
& 0xff) << 2;
3319 if ((insn
& (1 << 23)) == 0)
3321 gen_op_addl_T1_im(offset
);
3322 if (insn
& (1 << 20)) {
3324 gen_mov_vreg_F0(dp
, rd
);
3326 gen_mov_F0_vreg(dp
, rd
);
3330 /* load/store multiple */
3332 n
= (insn
>> 1) & 0x7f;
3336 if (insn
& (1 << 24)) /* pre-decrement */
3337 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3343 for (i
= 0; i
< n
; i
++) {
3344 if (insn
& ARM_CP_RW_BIT
) {
3347 gen_mov_vreg_F0(dp
, rd
+ i
);
3350 gen_mov_F0_vreg(dp
, rd
+ i
);
3353 gen_op_addl_T1_im(offset
);
3355 if (insn
& (1 << 21)) {
3357 if (insn
& (1 << 24))
3358 offset
= -offset
* n
;
3359 else if (dp
&& (insn
& 1))
3365 gen_op_addl_T1_im(offset
);
3366 gen_movl_reg_T1(s
, rn
);
3372 /* Should never happen. */
3378 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3380 TranslationBlock
*tb
;
3383 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3385 gen_set_pc_im(dest
);
3386 tcg_gen_exit_tb((long)tb
+ n
);
3388 gen_set_pc_im(dest
);
3393 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3395 if (unlikely(s
->singlestep_enabled
)) {
3396 /* An indirect jump so that we still trigger the debug exception. */
3401 gen_goto_tb(s
, 0, dest
);
3402 s
->is_jmp
= DISAS_TB_JUMP
;
3406 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3409 tcg_gen_sari_i32(t0
, t0
, 16);
3413 tcg_gen_sari_i32(t1
, t1
, 16);
3416 tcg_gen_mul_i32(t0
, t0
, t1
);
3419 /* Return the mask of PSR bits set by a MSR instruction. */
3420 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3424 if (flags
& (1 << 0))
3426 if (flags
& (1 << 1))
3428 if (flags
& (1 << 2))
3430 if (flags
& (1 << 3))
3433 /* Mask out undefined bits. */
3434 mask
&= ~CPSR_RESERVED
;
3435 if (!arm_feature(env
, ARM_FEATURE_V6
))
3436 mask
&= ~(CPSR_E
| CPSR_GE
);
3437 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3439 /* Mask out execution state bits. */
3442 /* Mask out privileged bits. */
3448 /* Returns nonzero if access to the PSR is not permitted. */
3449 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3453 /* ??? This is also undefined in system mode. */
3457 tmp
= load_cpu_field(spsr
);
3458 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3459 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3460 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3461 store_cpu_field(tmp
, spsr
);
3463 gen_set_cpsr(cpu_T
[0], mask
);
3469 /* Generate an old-style exception return. */
3470 static void gen_exception_return(DisasContext
*s
)
3473 gen_movl_reg_T0(s
, 15);
3474 tmp
= load_cpu_field(spsr
);
3475 gen_set_cpsr(tmp
, 0xffffffff);
3477 s
->is_jmp
= DISAS_UPDATE
;
3480 /* Generate a v6 exception return. Marks both values as dead. */
3481 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3483 gen_set_cpsr(cpsr
, 0xffffffff);
3485 store_reg(s
, 15, pc
);
3486 s
->is_jmp
= DISAS_UPDATE
;
3490 gen_set_condexec (DisasContext
*s
)
3492 if (s
->condexec_mask
) {
3493 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3494 TCGv tmp
= new_tmp();
3495 tcg_gen_movi_i32(tmp
, val
);
3496 store_cpu_field(tmp
, condexec_bits
);
3500 static void gen_nop_hint(DisasContext
*s
, int val
)
3504 gen_set_pc_im(s
->pc
);
3505 s
->is_jmp
= DISAS_WFI
;
3509 /* TODO: Implement SEV and WFE. May help SMP performance. */
3515 /* These macros help make the code more readable when migrating from the
3516 old dyngen helpers. They should probably be removed when
3517 T0/T1 are removed. */
3518 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3519 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3521 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3523 static inline int gen_neon_add(int size
)
3526 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3527 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3528 case 2: gen_op_addl_T0_T1(); break;
3534 static inline void gen_neon_rsb(int size
)
3537 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3538 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3539 case 2: gen_op_rsbl_T0_T1(); break;
3544 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3545 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3546 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3547 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3548 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3550 /* FIXME: This is wrong. They set the wrong overflow bit. */
3551 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3552 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3553 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3554 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3556 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3557 switch ((size << 1) | u) { \
3559 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3562 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3565 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3568 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3571 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3574 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3576 default: return 1; \
3579 #define GEN_NEON_INTEGER_OP(name) do { \
3580 switch ((size << 1) | u) { \
3582 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3585 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3588 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3591 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3594 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3597 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3599 default: return 1; \
3603 gen_neon_movl_scratch_T0(int scratch
)
3607 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3608 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3612 gen_neon_movl_scratch_T1(int scratch
)
3616 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3617 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3621 gen_neon_movl_T0_scratch(int scratch
)
3625 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3626 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3630 gen_neon_movl_T1_scratch(int scratch
)
3634 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3635 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3638 static inline void gen_neon_get_scalar(int size
, int reg
)
3641 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3643 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3645 gen_neon_dup_low16(cpu_T
[0]);
3647 gen_neon_dup_high16(cpu_T
[0]);
3651 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3655 for (n
= 0; n
< q
+ 1; n
+= 2) {
3656 NEON_GET_REG(T0
, reg
, n
);
3657 NEON_GET_REG(T0
, reg
, n
+ n
);
3659 case 0: gen_helper_neon_unzip_u8(); break;
3660 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3661 case 2: /* no-op */; break;
3664 gen_neon_movl_scratch_T0(tmp
+ n
);
3665 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3673 } neon_ls_element_type
[11] = {
3687 /* Translate a NEON load/store element instruction. Return nonzero if the
3688 instruction is invalid. */
3689 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3705 if (!vfp_enabled(env
))
3707 VFP_DREG_D(rd
, insn
);
3708 rn
= (insn
>> 16) & 0xf;
3710 load
= (insn
& (1 << 21)) != 0;
3711 if ((insn
& (1 << 23)) == 0) {
3712 /* Load store all elements. */
3713 op
= (insn
>> 8) & 0xf;
3714 size
= (insn
>> 6) & 3;
3715 if (op
> 10 || size
== 3)
3717 nregs
= neon_ls_element_type
[op
].nregs
;
3718 interleave
= neon_ls_element_type
[op
].interleave
;
3719 gen_movl_T1_reg(s
, rn
);
3720 stride
= (1 << size
) * interleave
;
3721 for (reg
= 0; reg
< nregs
; reg
++) {
3722 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3723 gen_movl_T1_reg(s
, rn
);
3724 gen_op_addl_T1_im((1 << size
) * reg
);
3725 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3726 gen_movl_T1_reg(s
, rn
);
3727 gen_op_addl_T1_im(1 << size
);
3729 for (pass
= 0; pass
< 2; pass
++) {
3732 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3733 neon_store_reg(rd
, pass
, tmp
);
3735 tmp
= neon_load_reg(rd
, pass
);
3736 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3738 gen_op_addl_T1_im(stride
);
3739 } else if (size
== 1) {
3741 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3742 gen_op_addl_T1_im(stride
);
3743 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3744 gen_op_addl_T1_im(stride
);
3745 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3747 neon_store_reg(rd
, pass
, tmp
);
3749 tmp
= neon_load_reg(rd
, pass
);
3751 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3752 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3753 gen_op_addl_T1_im(stride
);
3754 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3755 gen_op_addl_T1_im(stride
);
3757 } else /* size == 0 */ {
3760 for (n
= 0; n
< 4; n
++) {
3761 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3762 gen_op_addl_T1_im(stride
);
3766 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3770 neon_store_reg(rd
, pass
, tmp2
);
3772 tmp2
= neon_load_reg(rd
, pass
);
3773 for (n
= 0; n
< 4; n
++) {
3776 tcg_gen_mov_i32(tmp
, tmp2
);
3778 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3780 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3781 gen_op_addl_T1_im(stride
);
3787 rd
+= neon_ls_element_type
[op
].spacing
;
3791 size
= (insn
>> 10) & 3;
3793 /* Load single element to all lanes. */
3796 size
= (insn
>> 6) & 3;
3797 nregs
= ((insn
>> 8) & 3) + 1;
3798 stride
= (insn
& (1 << 5)) ? 2 : 1;
3799 gen_movl_T1_reg(s
, rn
);
3800 for (reg
= 0; reg
< nregs
; reg
++) {
3803 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3804 gen_neon_dup_u8(tmp
, 0);
3807 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3808 gen_neon_dup_low16(tmp
);
3811 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3815 default: /* Avoid compiler warnings. */
3818 gen_op_addl_T1_im(1 << size
);
3820 tcg_gen_mov_i32(tmp2
, tmp
);
3821 neon_store_reg(rd
, 0, tmp2
);
3822 neon_store_reg(rd
, 1, tmp
);
3825 stride
= (1 << size
) * nregs
;
3827 /* Single element. */
3828 pass
= (insn
>> 7) & 1;
3831 shift
= ((insn
>> 5) & 3) * 8;
3835 shift
= ((insn
>> 6) & 1) * 16;
3836 stride
= (insn
& (1 << 5)) ? 2 : 1;
3840 stride
= (insn
& (1 << 6)) ? 2 : 1;
3845 nregs
= ((insn
>> 8) & 3) + 1;
3846 gen_movl_T1_reg(s
, rn
);
3847 for (reg
= 0; reg
< nregs
; reg
++) {
3851 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3854 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3857 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3859 default: /* Avoid compiler warnings. */
3863 tmp2
= neon_load_reg(rd
, pass
);
3864 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3867 neon_store_reg(rd
, pass
, tmp
);
3868 } else { /* Store */
3869 tmp
= neon_load_reg(rd
, pass
);
3871 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3874 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3877 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3880 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3885 gen_op_addl_T1_im(1 << size
);
3887 stride
= nregs
* (1 << size
);
3893 base
= load_reg(s
, rn
);
3895 tcg_gen_addi_i32(base
, base
, stride
);
3898 index
= load_reg(s
, rm
);
3899 tcg_gen_add_i32(base
, base
, index
);
3902 store_reg(s
, rn
, base
);
3907 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3908 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3910 tcg_gen_and_i32(t
, t
, c
);
3911 tcg_gen_bic_i32(f
, f
, c
);
3912 tcg_gen_or_i32(dest
, t
, f
);
3915 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3918 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3919 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3920 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3925 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3928 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3929 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3930 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3935 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3938 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3939 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3940 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3945 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3951 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3952 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3957 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3958 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3965 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3966 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3971 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3972 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3979 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3983 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3984 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3985 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3990 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3991 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3992 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
3999 static inline void gen_neon_addl(int size
)
4002 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4003 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4004 case 2: tcg_gen_add_i64(CPU_V001
); break;
4009 static inline void gen_neon_subl(int size
)
4012 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4013 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4014 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4019 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4022 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4023 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4024 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4029 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4032 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4033 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4038 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4042 switch ((size
<< 1) | u
) {
4043 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4044 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4045 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4046 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4048 tmp
= gen_muls_i64_i32(a
, b
);
4049 tcg_gen_mov_i64(dest
, tmp
);
4052 tmp
= gen_mulu_i64_i32(a
, b
);
4053 tcg_gen_mov_i64(dest
, tmp
);
4063 /* Translate a NEON data processing instruction. Return nonzero if the
4064 instruction is invalid.
4065 We process data in a mixture of 32-bit and 64-bit chunks.
4066 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4068 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4086 if (!vfp_enabled(env
))
4088 q
= (insn
& (1 << 6)) != 0;
4089 u
= (insn
>> 24) & 1;
4090 VFP_DREG_D(rd
, insn
);
4091 VFP_DREG_N(rn
, insn
);
4092 VFP_DREG_M(rm
, insn
);
4093 size
= (insn
>> 20) & 3;
4094 if ((insn
& (1 << 23)) == 0) {
4095 /* Three register same length. */
4096 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4097 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4098 || op
== 10 || op
== 11 || op
== 16)) {
4099 /* 64-bit element instructions. */
4100 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4101 neon_load_reg64(cpu_V0
, rn
+ pass
);
4102 neon_load_reg64(cpu_V1
, rm
+ pass
);
4106 gen_helper_neon_add_saturate_u64(CPU_V001
);
4108 gen_helper_neon_add_saturate_s64(CPU_V001
);
4113 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4115 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4120 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4122 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4127 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4130 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4134 case 10: /* VRSHL */
4136 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4138 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4141 case 11: /* VQRSHL */
4143 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4146 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4152 tcg_gen_sub_i64(CPU_V001
);
4154 tcg_gen_add_i64(CPU_V001
);
4160 neon_store_reg64(cpu_V0
, rd
+ pass
);
4167 case 10: /* VRSHL */
4168 case 11: /* VQRSHL */
4171 /* Shift instruction operands are reversed. */
4178 case 20: /* VPMAX */
4179 case 21: /* VPMIN */
4180 case 23: /* VPADD */
4183 case 26: /* VPADD (float) */
4184 pairwise
= (u
&& size
< 2);
4186 case 30: /* VPMIN/VPMAX (float) */
4193 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4202 NEON_GET_REG(T0
, rn
, n
);
4203 NEON_GET_REG(T1
, rn
, n
+ 1);
4205 NEON_GET_REG(T0
, rm
, n
);
4206 NEON_GET_REG(T1
, rm
, n
+ 1);
4210 NEON_GET_REG(T0
, rn
, pass
);
4211 NEON_GET_REG(T1
, rm
, pass
);
4215 GEN_NEON_INTEGER_OP(hadd
);
4218 GEN_NEON_INTEGER_OP_ENV(qadd
);
4220 case 2: /* VRHADD */
4221 GEN_NEON_INTEGER_OP(rhadd
);
4223 case 3: /* Logic ops. */
4224 switch ((u
<< 2) | size
) {
4226 gen_op_andl_T0_T1();
4229 gen_op_bicl_T0_T1();
4239 gen_op_xorl_T0_T1();
4242 tmp
= neon_load_reg(rd
, pass
);
4243 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4247 tmp
= neon_load_reg(rd
, pass
);
4248 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4252 tmp
= neon_load_reg(rd
, pass
);
4253 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4259 GEN_NEON_INTEGER_OP(hsub
);
4262 GEN_NEON_INTEGER_OP_ENV(qsub
);
4265 GEN_NEON_INTEGER_OP(cgt
);
4268 GEN_NEON_INTEGER_OP(cge
);
4271 GEN_NEON_INTEGER_OP(shl
);
4274 GEN_NEON_INTEGER_OP_ENV(qshl
);
4276 case 10: /* VRSHL */
4277 GEN_NEON_INTEGER_OP(rshl
);
4279 case 11: /* VQRSHL */
4280 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4283 GEN_NEON_INTEGER_OP(max
);
4286 GEN_NEON_INTEGER_OP(min
);
4289 GEN_NEON_INTEGER_OP(abd
);
4292 GEN_NEON_INTEGER_OP(abd
);
4293 NEON_GET_REG(T1
, rd
, pass
);
4297 if (!u
) { /* VADD */
4298 if (gen_neon_add(size
))
4302 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4303 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4304 case 2: gen_op_subl_T0_T1(); break;
4310 if (!u
) { /* VTST */
4312 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4313 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4314 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4319 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4320 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4321 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4326 case 18: /* Multiply. */
4328 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4329 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4330 case 2: gen_op_mul_T0_T1(); break;
4333 NEON_GET_REG(T1
, rd
, pass
);
4341 if (u
) { /* polynomial */
4342 gen_helper_neon_mul_p8(CPU_T001
);
4343 } else { /* Integer */
4345 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4346 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4347 case 2: gen_op_mul_T0_T1(); break;
4352 case 20: /* VPMAX */
4353 GEN_NEON_INTEGER_OP(pmax
);
4355 case 21: /* VPMIN */
4356 GEN_NEON_INTEGER_OP(pmin
);
4358 case 22: /* Hultiply high. */
4359 if (!u
) { /* VQDMULH */
4361 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4362 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4365 } else { /* VQRDHMUL */
4367 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4368 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4373 case 23: /* VPADD */
4377 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4378 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4379 case 2: gen_op_addl_T0_T1(); break;
4383 case 26: /* Floating point arithnetic. */
4384 switch ((u
<< 2) | size
) {
4386 gen_helper_neon_add_f32(CPU_T001
);
4389 gen_helper_neon_sub_f32(CPU_T001
);
4392 gen_helper_neon_add_f32(CPU_T001
);
4395 gen_helper_neon_abd_f32(CPU_T001
);
4401 case 27: /* Float multiply. */
4402 gen_helper_neon_mul_f32(CPU_T001
);
4404 NEON_GET_REG(T1
, rd
, pass
);
4406 gen_helper_neon_add_f32(CPU_T001
);
4408 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4412 case 28: /* Float compare. */
4414 gen_helper_neon_ceq_f32(CPU_T001
);
4417 gen_helper_neon_cge_f32(CPU_T001
);
4419 gen_helper_neon_cgt_f32(CPU_T001
);
4422 case 29: /* Float compare absolute. */
4426 gen_helper_neon_acge_f32(CPU_T001
);
4428 gen_helper_neon_acgt_f32(CPU_T001
);
4430 case 30: /* Float min/max. */
4432 gen_helper_neon_max_f32(CPU_T001
);
4434 gen_helper_neon_min_f32(CPU_T001
);
4438 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4440 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4445 /* Save the result. For elementwise operations we can put it
4446 straight into the destination register. For pairwise operations
4447 we have to be careful to avoid clobbering the source operands. */
4448 if (pairwise
&& rd
== rm
) {
4449 gen_neon_movl_scratch_T0(pass
);
4451 NEON_SET_REG(T0
, rd
, pass
);
4455 if (pairwise
&& rd
== rm
) {
4456 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4457 gen_neon_movl_T0_scratch(pass
);
4458 NEON_SET_REG(T0
, rd
, pass
);
4461 /* End of 3 register same size operations. */
4462 } else if (insn
& (1 << 4)) {
4463 if ((insn
& 0x00380080) != 0) {
4464 /* Two registers and shift. */
4465 op
= (insn
>> 8) & 0xf;
4466 if (insn
& (1 << 7)) {
4471 while ((insn
& (1 << (size
+ 19))) == 0)
4474 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4475 /* To avoid excessive dumplication of ops we implement shift
4476 by immediate using the variable shift operations. */
4478 /* Shift by immediate:
4479 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4480 /* Right shifts are encoded as N - shift, where N is the
4481 element size in bits. */
4483 shift
= shift
- (1 << (size
+ 3));
4491 imm
= (uint8_t) shift
;
4496 imm
= (uint16_t) shift
;
4507 for (pass
= 0; pass
< count
; pass
++) {
4509 neon_load_reg64(cpu_V0
, rm
+ pass
);
4510 tcg_gen_movi_i64(cpu_V1
, imm
);
4515 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4517 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4522 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4524 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4529 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4531 case 5: /* VSHL, VSLI */
4532 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4536 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4538 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4540 case 7: /* VQSHLU */
4541 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4544 if (op
== 1 || op
== 3) {
4546 neon_load_reg64(cpu_V0
, rd
+ pass
);
4547 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4548 } else if (op
== 4 || (op
== 5 && u
)) {
4550 cpu_abort(env
, "VS[LR]I.64 not implemented");
4552 neon_store_reg64(cpu_V0
, rd
+ pass
);
4553 } else { /* size < 3 */
4554 /* Operands in T0 and T1. */
4555 gen_op_movl_T1_im(imm
);
4556 NEON_GET_REG(T0
, rm
, pass
);
4560 GEN_NEON_INTEGER_OP(shl
);
4564 GEN_NEON_INTEGER_OP(rshl
);
4569 GEN_NEON_INTEGER_OP(shl
);
4571 case 5: /* VSHL, VSLI */
4573 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4574 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4575 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4580 GEN_NEON_INTEGER_OP_ENV(qshl
);
4582 case 7: /* VQSHLU */
4584 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4585 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4586 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4592 if (op
== 1 || op
== 3) {
4594 NEON_GET_REG(T1
, rd
, pass
);
4596 } else if (op
== 4 || (op
== 5 && u
)) {
4601 imm
= 0xff >> -shift
;
4603 imm
= (uint8_t)(0xff << shift
);
4609 imm
= 0xffff >> -shift
;
4611 imm
= (uint16_t)(0xffff << shift
);
4616 imm
= 0xffffffffu
>> -shift
;
4618 imm
= 0xffffffffu
<< shift
;
4623 tmp
= neon_load_reg(rd
, pass
);
4624 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4625 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4626 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4628 NEON_SET_REG(T0
, rd
, pass
);
4631 } else if (op
< 10) {
4632 /* Shift by immediate and narrow:
4633 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4634 shift
= shift
- (1 << (size
+ 3));
4638 imm
= (uint16_t)shift
;
4640 tmp2
= tcg_const_i32(imm
);
4641 TCGV_UNUSED_I64(tmp64
);
4644 imm
= (uint32_t)shift
;
4645 tmp2
= tcg_const_i32(imm
);
4646 TCGV_UNUSED_I64(tmp64
);
4648 tmp64
= tcg_const_i64(shift
);
4655 for (pass
= 0; pass
< 2; pass
++) {
4657 neon_load_reg64(cpu_V0
, rm
+ pass
);
4660 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4662 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4665 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4667 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4670 tmp
= neon_load_reg(rm
+ pass
, 0);
4671 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4672 tmp3
= neon_load_reg(rm
+ pass
, 1);
4673 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4674 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4679 if (op
== 8 && !u
) {
4680 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4683 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4685 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4690 neon_store_reg(rd
, 0, tmp2
);
4691 neon_store_reg(rd
, 1, tmp
);
4694 } else if (op
== 10) {
4698 tmp
= neon_load_reg(rm
, 0);
4699 tmp2
= neon_load_reg(rm
, 1);
4700 for (pass
= 0; pass
< 2; pass
++) {
4704 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4707 /* The shift is less than the width of the source
4708 type, so we can just shift the whole register. */
4709 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4710 if (size
< 2 || !u
) {
4713 imm
= (0xffu
>> (8 - shift
));
4716 imm
= 0xffff >> (16 - shift
);
4718 imm64
= imm
| (((uint64_t)imm
) << 32);
4719 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4722 neon_store_reg64(cpu_V0
, rd
+ pass
);
4724 } else if (op
== 15 || op
== 16) {
4725 /* VCVT fixed-point. */
4726 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4727 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4730 gen_vfp_ulto(0, shift
);
4732 gen_vfp_slto(0, shift
);
4735 gen_vfp_toul(0, shift
);
4737 gen_vfp_tosl(0, shift
);
4739 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4744 } else { /* (insn & 0x00380080) == 0 */
4747 op
= (insn
>> 8) & 0xf;
4748 /* One register and immediate. */
4749 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4750 invert
= (insn
& (1 << 5)) != 0;
4768 imm
= (imm
<< 8) | (imm
<< 24);
4771 imm
= (imm
< 8) | 0xff;
4774 imm
= (imm
<< 16) | 0xffff;
4777 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4782 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4783 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4789 if (op
!= 14 || !invert
)
4790 gen_op_movl_T1_im(imm
);
4792 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4793 if (op
& 1 && op
< 12) {
4794 tmp
= neon_load_reg(rd
, pass
);
4796 /* The immediate value has already been inverted, so
4798 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4800 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4805 if (op
== 14 && invert
) {
4808 for (n
= 0; n
< 4; n
++) {
4809 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4810 val
|= 0xff << (n
* 8);
4812 tcg_gen_movi_i32(tmp
, val
);
4814 tcg_gen_movi_i32(tmp
, imm
);
4817 neon_store_reg(rd
, pass
, tmp
);
4820 } else { /* (insn & 0x00800010 == 0x00800000) */
4822 op
= (insn
>> 8) & 0xf;
4823 if ((insn
& (1 << 6)) == 0) {
4824 /* Three registers of different lengths. */
4828 /* prewiden, src1_wide, src2_wide */
4829 static const int neon_3reg_wide
[16][3] = {
4830 {1, 0, 0}, /* VADDL */
4831 {1, 1, 0}, /* VADDW */
4832 {1, 0, 0}, /* VSUBL */
4833 {1, 1, 0}, /* VSUBW */
4834 {0, 1, 1}, /* VADDHN */
4835 {0, 0, 0}, /* VABAL */
4836 {0, 1, 1}, /* VSUBHN */
4837 {0, 0, 0}, /* VABDL */
4838 {0, 0, 0}, /* VMLAL */
4839 {0, 0, 0}, /* VQDMLAL */
4840 {0, 0, 0}, /* VMLSL */
4841 {0, 0, 0}, /* VQDMLSL */
4842 {0, 0, 0}, /* Integer VMULL */
4843 {0, 0, 0}, /* VQDMULL */
4844 {0, 0, 0} /* Polynomial VMULL */
4847 prewiden
= neon_3reg_wide
[op
][0];
4848 src1_wide
= neon_3reg_wide
[op
][1];
4849 src2_wide
= neon_3reg_wide
[op
][2];
4851 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4854 /* Avoid overlapping operands. Wide source operands are
4855 always aligned so will never overlap with wide
4856 destinations in problematic ways. */
4857 if (rd
== rm
&& !src2_wide
) {
4858 NEON_GET_REG(T0
, rm
, 1);
4859 gen_neon_movl_scratch_T0(2);
4860 } else if (rd
== rn
&& !src1_wide
) {
4861 NEON_GET_REG(T0
, rn
, 1);
4862 gen_neon_movl_scratch_T0(2);
4865 for (pass
= 0; pass
< 2; pass
++) {
4867 neon_load_reg64(cpu_V0
, rn
+ pass
);
4870 if (pass
== 1 && rd
== rn
) {
4871 gen_neon_movl_T0_scratch(2);
4873 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4875 tmp
= neon_load_reg(rn
, pass
);
4878 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4882 neon_load_reg64(cpu_V1
, rm
+ pass
);
4885 if (pass
== 1 && rd
== rm
) {
4886 gen_neon_movl_T0_scratch(2);
4888 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4890 tmp2
= neon_load_reg(rm
, pass
);
4893 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4897 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4898 gen_neon_addl(size
);
4900 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4901 gen_neon_subl(size
);
4903 case 5: case 7: /* VABAL, VABDL */
4904 switch ((size
<< 1) | u
) {
4906 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4909 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4912 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4915 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4918 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4921 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4928 case 8: case 9: case 10: case 11: case 12: case 13:
4929 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4930 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4932 case 14: /* Polynomial VMULL */
4933 cpu_abort(env
, "Polynomial VMULL not implemented");
4935 default: /* 15 is RESERVED. */
4938 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4940 if (op
== 10 || op
== 11) {
4941 gen_neon_negl(cpu_V0
, size
);
4945 neon_load_reg64(cpu_V1
, rd
+ pass
);
4949 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4950 gen_neon_addl(size
);
4952 case 9: case 11: /* VQDMLAL, VQDMLSL */
4953 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4954 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4957 case 13: /* VQDMULL */
4958 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4963 neon_store_reg64(cpu_V0
, rd
+ pass
);
4964 } else if (op
== 4 || op
== 6) {
4965 /* Narrowing operation. */
4970 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4973 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4976 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4977 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4984 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4987 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4990 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4991 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4992 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5000 neon_store_reg(rd
, 0, tmp3
);
5001 neon_store_reg(rd
, 1, tmp
);
5004 /* Write back the result. */
5005 neon_store_reg64(cpu_V0
, rd
+ pass
);
5009 /* Two registers and a scalar. */
5011 case 0: /* Integer VMLA scalar */
5012 case 1: /* Float VMLA scalar */
5013 case 4: /* Integer VMLS scalar */
5014 case 5: /* Floating point VMLS scalar */
5015 case 8: /* Integer VMUL scalar */
5016 case 9: /* Floating point VMUL scalar */
5017 case 12: /* VQDMULH scalar */
5018 case 13: /* VQRDMULH scalar */
5019 gen_neon_get_scalar(size
, rm
);
5020 gen_neon_movl_scratch_T0(0);
5021 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5023 gen_neon_movl_T0_scratch(0);
5024 NEON_GET_REG(T1
, rn
, pass
);
5027 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5029 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5031 } else if (op
== 13) {
5033 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5035 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5037 } else if (op
& 1) {
5038 gen_helper_neon_mul_f32(CPU_T001
);
5041 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5042 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5043 case 2: gen_op_mul_T0_T1(); break;
5049 NEON_GET_REG(T1
, rd
, pass
);
5055 gen_helper_neon_add_f32(CPU_T001
);
5061 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5067 NEON_SET_REG(T0
, rd
, pass
);
5070 case 2: /* VMLAL sclar */
5071 case 3: /* VQDMLAL scalar */
5072 case 6: /* VMLSL scalar */
5073 case 7: /* VQDMLSL scalar */
5074 case 10: /* VMULL scalar */
5075 case 11: /* VQDMULL scalar */
5076 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5079 gen_neon_get_scalar(size
, rm
);
5080 NEON_GET_REG(T1
, rn
, 1);
5082 for (pass
= 0; pass
< 2; pass
++) {
5084 tmp
= neon_load_reg(rn
, 0);
5087 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5090 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5091 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5092 if (op
== 6 || op
== 7) {
5093 gen_neon_negl(cpu_V0
, size
);
5096 neon_load_reg64(cpu_V1
, rd
+ pass
);
5100 gen_neon_addl(size
);
5103 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5104 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5110 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5115 neon_store_reg64(cpu_V0
, rd
+ pass
);
5118 default: /* 14 and 15 are RESERVED */
5122 } else { /* size == 3 */
5125 imm
= (insn
>> 8) & 0xf;
5132 neon_load_reg64(cpu_V0
, rn
);
5134 neon_load_reg64(cpu_V1
, rn
+ 1);
5136 } else if (imm
== 8) {
5137 neon_load_reg64(cpu_V0
, rn
+ 1);
5139 neon_load_reg64(cpu_V1
, rm
);
5142 tmp64
= tcg_temp_new_i64();
5144 neon_load_reg64(cpu_V0
, rn
);
5145 neon_load_reg64(tmp64
, rn
+ 1);
5147 neon_load_reg64(cpu_V0
, rn
+ 1);
5148 neon_load_reg64(tmp64
, rm
);
5150 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5151 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5152 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5154 neon_load_reg64(cpu_V1
, rm
);
5156 neon_load_reg64(cpu_V1
, rm
+ 1);
5159 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5160 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5161 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5164 neon_load_reg64(cpu_V0
, rn
);
5165 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5166 neon_load_reg64(cpu_V1
, rm
);
5167 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5168 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5170 neon_store_reg64(cpu_V0
, rd
);
5172 neon_store_reg64(cpu_V1
, rd
+ 1);
5174 } else if ((insn
& (1 << 11)) == 0) {
5175 /* Two register misc. */
5176 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5177 size
= (insn
>> 18) & 3;
5179 case 0: /* VREV64 */
5182 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5183 NEON_GET_REG(T0
, rm
, pass
* 2);
5184 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5186 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5187 case 1: gen_swap_half(cpu_T
[0]); break;
5188 case 2: /* no-op */ break;
5191 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5193 NEON_SET_REG(T1
, rd
, pass
* 2);
5195 gen_op_movl_T0_T1();
5197 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5198 case 1: gen_swap_half(cpu_T
[0]); break;
5201 NEON_SET_REG(T0
, rd
, pass
* 2);
5205 case 4: case 5: /* VPADDL */
5206 case 12: case 13: /* VPADAL */
5209 for (pass
= 0; pass
< q
+ 1; pass
++) {
5210 tmp
= neon_load_reg(rm
, pass
* 2);
5211 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5212 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5213 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5215 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5216 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5217 case 2: tcg_gen_add_i64(CPU_V001
); break;
5222 neon_load_reg64(cpu_V1
, rd
+ pass
);
5223 gen_neon_addl(size
);
5225 neon_store_reg64(cpu_V0
, rd
+ pass
);
5230 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5231 NEON_GET_REG(T0
, rm
, n
);
5232 NEON_GET_REG(T1
, rd
, n
+ 1);
5233 NEON_SET_REG(T1
, rm
, n
);
5234 NEON_SET_REG(T0
, rd
, n
+ 1);
5242 Rd A3 A2 A1 A0 B2 B0 A2 A0
5243 Rm B3 B2 B1 B0 B3 B1 A3 A1
5247 gen_neon_unzip(rd
, q
, 0, size
);
5248 gen_neon_unzip(rm
, q
, 4, size
);
5250 static int unzip_order_q
[8] =
5251 {0, 2, 4, 6, 1, 3, 5, 7};
5252 for (n
= 0; n
< 8; n
++) {
5253 int reg
= (n
< 4) ? rd
: rm
;
5254 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5255 NEON_SET_REG(T0
, reg
, n
% 4);
5258 static int unzip_order
[4] =
5260 for (n
= 0; n
< 4; n
++) {
5261 int reg
= (n
< 2) ? rd
: rm
;
5262 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5263 NEON_SET_REG(T0
, reg
, n
% 2);
5269 Rd A3 A2 A1 A0 B1 A1 B0 A0
5270 Rm B3 B2 B1 B0 B3 A3 B2 A2
5274 count
= (q
? 4 : 2);
5275 for (n
= 0; n
< count
; n
++) {
5276 NEON_GET_REG(T0
, rd
, n
);
5277 NEON_GET_REG(T1
, rd
, n
);
5279 case 0: gen_helper_neon_zip_u8(); break;
5280 case 1: gen_helper_neon_zip_u16(); break;
5281 case 2: /* no-op */; break;
5284 gen_neon_movl_scratch_T0(n
* 2);
5285 gen_neon_movl_scratch_T1(n
* 2 + 1);
5287 for (n
= 0; n
< count
* 2; n
++) {
5288 int reg
= (n
< count
) ? rd
: rm
;
5289 gen_neon_movl_T0_scratch(n
);
5290 NEON_SET_REG(T0
, reg
, n
% count
);
5293 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5297 for (pass
= 0; pass
< 2; pass
++) {
5298 neon_load_reg64(cpu_V0
, rm
+ pass
);
5300 if (op
== 36 && q
== 0) {
5301 gen_neon_narrow(size
, tmp
, cpu_V0
);
5303 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5305 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5310 neon_store_reg(rd
, 0, tmp2
);
5311 neon_store_reg(rd
, 1, tmp
);
5315 case 38: /* VSHLL */
5318 tmp
= neon_load_reg(rm
, 0);
5319 tmp2
= neon_load_reg(rm
, 1);
5320 for (pass
= 0; pass
< 2; pass
++) {
5323 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5324 neon_store_reg64(cpu_V0
, rd
+ pass
);
5329 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5330 if (op
== 30 || op
== 31 || op
>= 58) {
5331 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5332 neon_reg_offset(rm
, pass
));
5334 NEON_GET_REG(T0
, rm
, pass
);
5337 case 1: /* VREV32 */
5339 case 0: tcg_gen_bswap_i32(cpu_T
[0], cpu_T
[0]); break;
5340 case 1: gen_swap_half(cpu_T
[0]); break;
5344 case 2: /* VREV16 */
5347 gen_rev16(cpu_T
[0]);
5351 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5352 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5353 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5359 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5360 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5361 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5368 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5375 case 14: /* VQABS */
5377 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5378 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5379 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5383 case 15: /* VQNEG */
5385 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5386 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5387 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5391 case 16: case 19: /* VCGT #0, VCLE #0 */
5392 gen_op_movl_T1_im(0);
5394 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5395 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5396 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5402 case 17: case 20: /* VCGE #0, VCLT #0 */
5403 gen_op_movl_T1_im(0);
5405 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5406 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5407 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5413 case 18: /* VCEQ #0 */
5414 gen_op_movl_T1_im(0);
5416 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5417 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5418 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5424 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5425 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5426 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5431 gen_op_movl_T1_im(0);
5436 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5437 gen_op_movl_T1_im(0);
5438 gen_helper_neon_cgt_f32(CPU_T001
);
5442 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5443 gen_op_movl_T1_im(0);
5444 gen_helper_neon_cge_f32(CPU_T001
);
5448 case 26: /* Float VCEQ #0 */
5449 gen_op_movl_T1_im(0);
5450 gen_helper_neon_ceq_f32(CPU_T001
);
5452 case 30: /* Float VABS */
5455 case 31: /* Float VNEG */
5459 NEON_GET_REG(T1
, rd
, pass
);
5460 NEON_SET_REG(T1
, rm
, pass
);
5463 NEON_GET_REG(T1
, rd
, pass
);
5465 case 0: gen_helper_neon_trn_u8(); break;
5466 case 1: gen_helper_neon_trn_u16(); break;
5470 NEON_SET_REG(T1
, rm
, pass
);
5472 case 56: /* Integer VRECPE */
5473 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5475 case 57: /* Integer VRSQRTE */
5476 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5478 case 58: /* Float VRECPE */
5479 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5481 case 59: /* Float VRSQRTE */
5482 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5484 case 60: /* VCVT.F32.S32 */
5487 case 61: /* VCVT.F32.U32 */
5490 case 62: /* VCVT.S32.F32 */
5493 case 63: /* VCVT.U32.F32 */
5497 /* Reserved: 21, 29, 39-56 */
5500 if (op
== 30 || op
== 31 || op
>= 58) {
5501 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5502 neon_reg_offset(rd
, pass
));
5504 NEON_SET_REG(T0
, rd
, pass
);
5509 } else if ((insn
& (1 << 10)) == 0) {
5511 n
= ((insn
>> 5) & 0x18) + 8;
5512 if (insn
& (1 << 6)) {
5513 tmp
= neon_load_reg(rd
, 0);
5516 tcg_gen_movi_i32(tmp
, 0);
5518 tmp2
= neon_load_reg(rm
, 0);
5519 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5522 if (insn
& (1 << 6)) {
5523 tmp
= neon_load_reg(rd
, 1);
5526 tcg_gen_movi_i32(tmp
, 0);
5528 tmp3
= neon_load_reg(rm
, 1);
5529 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5531 neon_store_reg(rd
, 0, tmp2
);
5532 neon_store_reg(rd
, 1, tmp3
);
5534 } else if ((insn
& 0x380) == 0) {
5536 if (insn
& (1 << 19)) {
5537 NEON_SET_REG(T0
, rm
, 1);
5539 NEON_SET_REG(T0
, rm
, 0);
5541 if (insn
& (1 << 16)) {
5542 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5543 } else if (insn
& (1 << 17)) {
5544 if ((insn
>> 18) & 1)
5545 gen_neon_dup_high16(cpu_T
[0]);
5547 gen_neon_dup_low16(cpu_T
[0]);
5549 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5550 NEON_SET_REG(T0
, rd
, pass
);
5560 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5564 cpnum
= (insn
>> 8) & 0xf;
5565 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5566 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5572 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5573 return disas_iwmmxt_insn(env
, s
, insn
);
5574 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5575 return disas_dsp_insn(env
, s
, insn
);
5580 return disas_vfp_insn (env
, s
, insn
);
5582 return disas_cp15_insn (env
, s
, insn
);
5584 /* Unknown coprocessor. See if the board has hooked it. */
5585 return disas_cp_insn (env
, s
, insn
);
5590 /* Store a 64-bit value to a register pair. Clobbers val. */
5591 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5595 tcg_gen_trunc_i64_i32(tmp
, val
);
5596 store_reg(s
, rlow
, tmp
);
5598 tcg_gen_shri_i64(val
, val
, 32);
5599 tcg_gen_trunc_i64_i32(tmp
, val
);
5600 store_reg(s
, rhigh
, tmp
);
5603 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5604 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5609 /* Load value and extend to 64 bits. */
5610 tmp
= tcg_temp_new_i64();
5611 tmp2
= load_reg(s
, rlow
);
5612 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5614 tcg_gen_add_i64(val
, val
, tmp
);
5617 /* load and add a 64-bit value from a register pair. */
5618 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5624 /* Load 64-bit value rd:rn. */
5625 tmpl
= load_reg(s
, rlow
);
5626 tmph
= load_reg(s
, rhigh
);
5627 tmp
= tcg_temp_new_i64();
5628 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5631 tcg_gen_add_i64(val
, val
, tmp
);
5634 /* Set N and Z flags from a 64-bit value. */
5635 static void gen_logicq_cc(TCGv_i64 val
)
5637 TCGv tmp
= new_tmp();
5638 gen_helper_logicq_cc(tmp
, val
);
5643 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5645 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5652 insn
= ldl_code(s
->pc
);
5655 /* M variants do not implement ARM mode. */
5660 /* Unconditional instructions. */
5661 if (((insn
>> 25) & 7) == 1) {
5662 /* NEON Data processing. */
5663 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5666 if (disas_neon_data_insn(env
, s
, insn
))
5670 if ((insn
& 0x0f100000) == 0x04000000) {
5671 /* NEON load/store. */
5672 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5675 if (disas_neon_ls_insn(env
, s
, insn
))
5679 if ((insn
& 0x0d70f000) == 0x0550f000)
5681 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5684 if (insn
& (1 << 9)) {
5685 /* BE8 mode not implemented. */
5689 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5690 switch ((insn
>> 4) & 0xf) {
5693 gen_helper_clrex(cpu_env
);
5699 /* We don't emulate caches so these are a no-op. */
5704 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5710 op1
= (insn
& 0x1f);
5711 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5712 addr
= load_reg(s
, 13);
5715 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5717 i
= (insn
>> 23) & 3;
5719 case 0: offset
= -4; break; /* DA */
5720 case 1: offset
= -8; break; /* DB */
5721 case 2: offset
= 0; break; /* IA */
5722 case 3: offset
= 4; break; /* IB */
5726 tcg_gen_addi_i32(addr
, addr
, offset
);
5727 tmp
= load_reg(s
, 14);
5728 gen_st32(tmp
, addr
, 0);
5730 gen_helper_cpsr_read(tmp
);
5731 tcg_gen_addi_i32(addr
, addr
, 4);
5732 gen_st32(tmp
, addr
, 0);
5733 if (insn
& (1 << 21)) {
5734 /* Base writeback. */
5736 case 0: offset
= -8; break;
5737 case 1: offset
= -4; break;
5738 case 2: offset
= 4; break;
5739 case 3: offset
= 0; break;
5743 tcg_gen_addi_i32(addr
, tmp
, offset
);
5744 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5745 gen_movl_reg_T1(s
, 13);
5747 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5752 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5758 rn
= (insn
>> 16) & 0xf;
5759 addr
= load_reg(s
, rn
);
5760 i
= (insn
>> 23) & 3;
5762 case 0: offset
= -4; break; /* DA */
5763 case 1: offset
= -8; break; /* DB */
5764 case 2: offset
= 0; break; /* IA */
5765 case 3: offset
= 4; break; /* IB */
5769 tcg_gen_addi_i32(addr
, addr
, offset
);
5770 /* Load PC into tmp and CPSR into tmp2. */
5771 tmp
= gen_ld32(addr
, 0);
5772 tcg_gen_addi_i32(addr
, addr
, 4);
5773 tmp2
= gen_ld32(addr
, 0);
5774 if (insn
& (1 << 21)) {
5775 /* Base writeback. */
5777 case 0: offset
= -8; break;
5778 case 1: offset
= -4; break;
5779 case 2: offset
= 4; break;
5780 case 3: offset
= 0; break;
5784 tcg_gen_addi_i32(addr
, addr
, offset
);
5785 store_reg(s
, rn
, addr
);
5789 gen_rfe(s
, tmp
, tmp2
);
5790 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5791 /* branch link and change to thumb (blx <offset>) */
5794 val
= (uint32_t)s
->pc
;
5796 tcg_gen_movi_i32(tmp
, val
);
5797 store_reg(s
, 14, tmp
);
5798 /* Sign-extend the 24-bit offset */
5799 offset
= (((int32_t)insn
) << 8) >> 8;
5800 /* offset * 4 + bit24 * 2 + (thumb bit) */
5801 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5802 /* pipeline offset */
5806 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5807 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5808 /* iWMMXt register transfer. */
5809 if (env
->cp15
.c15_cpar
& (1 << 1))
5810 if (!disas_iwmmxt_insn(env
, s
, insn
))
5813 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5814 /* Coprocessor double register transfer. */
5815 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5816 /* Additional coprocessor register transfer. */
5817 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5820 /* cps (privileged) */
5824 if (insn
& (1 << 19)) {
5825 if (insn
& (1 << 8))
5827 if (insn
& (1 << 7))
5829 if (insn
& (1 << 6))
5831 if (insn
& (1 << 18))
5834 if (insn
& (1 << 17)) {
5836 val
|= (insn
& 0x1f);
5839 gen_op_movl_T0_im(val
);
5840 gen_set_psr_T0(s
, mask
, 0);
5847 /* if not always execute, we generate a conditional jump to
5849 s
->condlabel
= gen_new_label();
5850 gen_test_cc(cond
^ 1, s
->condlabel
);
5853 if ((insn
& 0x0f900000) == 0x03000000) {
5854 if ((insn
& (1 << 21)) == 0) {
5856 rd
= (insn
>> 12) & 0xf;
5857 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5858 if ((insn
& (1 << 22)) == 0) {
5861 tcg_gen_movi_i32(tmp
, val
);
5864 tmp
= load_reg(s
, rd
);
5865 tcg_gen_ext16u_i32(tmp
, tmp
);
5866 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5868 store_reg(s
, rd
, tmp
);
5870 if (((insn
>> 12) & 0xf) != 0xf)
5872 if (((insn
>> 16) & 0xf) == 0) {
5873 gen_nop_hint(s
, insn
& 0xff);
5875 /* CPSR = immediate */
5877 shift
= ((insn
>> 8) & 0xf) * 2;
5879 val
= (val
>> shift
) | (val
<< (32 - shift
));
5880 gen_op_movl_T0_im(val
);
5881 i
= ((insn
& (1 << 22)) != 0);
5882 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5886 } else if ((insn
& 0x0f900000) == 0x01000000
5887 && (insn
& 0x00000090) != 0x00000090) {
5888 /* miscellaneous instructions */
5889 op1
= (insn
>> 21) & 3;
5890 sh
= (insn
>> 4) & 0xf;
5893 case 0x0: /* move program status register */
5896 gen_movl_T0_reg(s
, rm
);
5897 i
= ((op1
& 2) != 0);
5898 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5902 rd
= (insn
>> 12) & 0xf;
5906 tmp
= load_cpu_field(spsr
);
5909 gen_helper_cpsr_read(tmp
);
5911 store_reg(s
, rd
, tmp
);
5916 /* branch/exchange thumb (bx). */
5917 tmp
= load_reg(s
, rm
);
5919 } else if (op1
== 3) {
5921 rd
= (insn
>> 12) & 0xf;
5922 tmp
= load_reg(s
, rm
);
5923 gen_helper_clz(tmp
, tmp
);
5924 store_reg(s
, rd
, tmp
);
5932 /* Trivial implementation equivalent to bx. */
5933 tmp
= load_reg(s
, rm
);
5943 /* branch link/exchange thumb (blx) */
5944 tmp
= load_reg(s
, rm
);
5946 tcg_gen_movi_i32(tmp2
, s
->pc
);
5947 store_reg(s
, 14, tmp2
);
5950 case 0x5: /* saturating add/subtract */
5951 rd
= (insn
>> 12) & 0xf;
5952 rn
= (insn
>> 16) & 0xf;
5953 tmp
= load_reg(s
, rm
);
5954 tmp2
= load_reg(s
, rn
);
5956 gen_helper_double_saturate(tmp2
, tmp2
);
5958 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
5960 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
5962 store_reg(s
, rd
, tmp
);
5965 gen_set_condexec(s
);
5966 gen_set_pc_im(s
->pc
- 4);
5967 gen_exception(EXCP_BKPT
);
5968 s
->is_jmp
= DISAS_JUMP
;
5970 case 0x8: /* signed multiply */
5974 rs
= (insn
>> 8) & 0xf;
5975 rn
= (insn
>> 12) & 0xf;
5976 rd
= (insn
>> 16) & 0xf;
5978 /* (32 * 16) >> 16 */
5979 tmp
= load_reg(s
, rm
);
5980 tmp2
= load_reg(s
, rs
);
5982 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
5985 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
5986 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
5988 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
5989 if ((sh
& 2) == 0) {
5990 tmp2
= load_reg(s
, rn
);
5991 gen_helper_add_setq(tmp
, tmp
, tmp2
);
5994 store_reg(s
, rd
, tmp
);
5997 tmp
= load_reg(s
, rm
);
5998 tmp2
= load_reg(s
, rs
);
5999 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6002 tmp64
= tcg_temp_new_i64();
6003 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6005 gen_addq(s
, tmp64
, rn
, rd
);
6006 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6009 tmp2
= load_reg(s
, rn
);
6010 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6013 store_reg(s
, rd
, tmp
);
6020 } else if (((insn
& 0x0e000000) == 0 &&
6021 (insn
& 0x00000090) != 0x90) ||
6022 ((insn
& 0x0e000000) == (1 << 25))) {
6023 int set_cc
, logic_cc
, shiftop
;
6025 op1
= (insn
>> 21) & 0xf;
6026 set_cc
= (insn
>> 20) & 1;
6027 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6029 /* data processing instruction */
6030 if (insn
& (1 << 25)) {
6031 /* immediate operand */
6033 shift
= ((insn
>> 8) & 0xf) * 2;
6035 val
= (val
>> shift
) | (val
<< (32 - shift
));
6036 gen_op_movl_T1_im(val
);
6037 if (logic_cc
&& shift
)
6038 gen_set_CF_bit31(cpu_T
[1]);
6042 gen_movl_T1_reg(s
, rm
);
6043 shiftop
= (insn
>> 5) & 3;
6044 if (!(insn
& (1 << 4))) {
6045 shift
= (insn
>> 7) & 0x1f;
6046 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
6048 rs
= (insn
>> 8) & 0xf;
6049 tmp
= load_reg(s
, rs
);
6050 gen_arm_shift_reg(cpu_T
[1], shiftop
, tmp
, logic_cc
);
6053 if (op1
!= 0x0f && op1
!= 0x0d) {
6054 rn
= (insn
>> 16) & 0xf;
6055 gen_movl_T0_reg(s
, rn
);
6057 rd
= (insn
>> 12) & 0xf;
6060 gen_op_andl_T0_T1();
6061 gen_movl_reg_T0(s
, rd
);
6063 gen_op_logic_T0_cc();
6066 gen_op_xorl_T0_T1();
6067 gen_movl_reg_T0(s
, rd
);
6069 gen_op_logic_T0_cc();
6072 if (set_cc
&& rd
== 15) {
6073 /* SUBS r15, ... is used for exception return. */
6076 gen_op_subl_T0_T1_cc();
6077 gen_exception_return(s
);
6080 gen_op_subl_T0_T1_cc();
6082 gen_op_subl_T0_T1();
6083 gen_movl_reg_T0(s
, rd
);
6088 gen_op_rsbl_T0_T1_cc();
6090 gen_op_rsbl_T0_T1();
6091 gen_movl_reg_T0(s
, rd
);
6095 gen_op_addl_T0_T1_cc();
6097 gen_op_addl_T0_T1();
6098 gen_movl_reg_T0(s
, rd
);
6102 gen_op_adcl_T0_T1_cc();
6105 gen_movl_reg_T0(s
, rd
);
6109 gen_op_sbcl_T0_T1_cc();
6112 gen_movl_reg_T0(s
, rd
);
6116 gen_op_rscl_T0_T1_cc();
6119 gen_movl_reg_T0(s
, rd
);
6123 gen_op_andl_T0_T1();
6124 gen_op_logic_T0_cc();
6129 gen_op_xorl_T0_T1();
6130 gen_op_logic_T0_cc();
6135 gen_op_subl_T0_T1_cc();
6140 gen_op_addl_T0_T1_cc();
6145 gen_movl_reg_T0(s
, rd
);
6147 gen_op_logic_T0_cc();
6150 if (logic_cc
&& rd
== 15) {
6151 /* MOVS r15, ... is used for exception return. */
6154 gen_op_movl_T0_T1();
6155 gen_exception_return(s
);
6157 gen_movl_reg_T1(s
, rd
);
6159 gen_op_logic_T1_cc();
6163 gen_op_bicl_T0_T1();
6164 gen_movl_reg_T0(s
, rd
);
6166 gen_op_logic_T0_cc();
6171 gen_movl_reg_T1(s
, rd
);
6173 gen_op_logic_T1_cc();
6177 /* other instructions */
6178 op1
= (insn
>> 24) & 0xf;
6182 /* multiplies, extra load/stores */
6183 sh
= (insn
>> 5) & 3;
6186 rd
= (insn
>> 16) & 0xf;
6187 rn
= (insn
>> 12) & 0xf;
6188 rs
= (insn
>> 8) & 0xf;
6190 op1
= (insn
>> 20) & 0xf;
6192 case 0: case 1: case 2: case 3: case 6:
6194 tmp
= load_reg(s
, rs
);
6195 tmp2
= load_reg(s
, rm
);
6196 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6198 if (insn
& (1 << 22)) {
6199 /* Subtract (mls) */
6201 tmp2
= load_reg(s
, rn
);
6202 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6204 } else if (insn
& (1 << 21)) {
6206 tmp2
= load_reg(s
, rn
);
6207 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6210 if (insn
& (1 << 20))
6212 store_reg(s
, rd
, tmp
);
6216 tmp
= load_reg(s
, rs
);
6217 tmp2
= load_reg(s
, rm
);
6218 if (insn
& (1 << 22))
6219 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6221 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6222 if (insn
& (1 << 21)) /* mult accumulate */
6223 gen_addq(s
, tmp64
, rn
, rd
);
6224 if (!(insn
& (1 << 23))) { /* double accumulate */
6226 gen_addq_lo(s
, tmp64
, rn
);
6227 gen_addq_lo(s
, tmp64
, rd
);
6229 if (insn
& (1 << 20))
6230 gen_logicq_cc(tmp64
);
6231 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6235 rn
= (insn
>> 16) & 0xf;
6236 rd
= (insn
>> 12) & 0xf;
6237 if (insn
& (1 << 23)) {
6238 /* load/store exclusive */
6239 op1
= (insn
>> 21) & 0x3;
6244 gen_movl_T1_reg(s
, rn
);
6246 if (insn
& (1 << 20)) {
6247 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6250 tmp
= gen_ld32(addr
, IS_USER(s
));
6252 case 1: /* ldrexd */
6253 tmp
= gen_ld32(addr
, IS_USER(s
));
6254 store_reg(s
, rd
, tmp
);
6255 tcg_gen_addi_i32(addr
, addr
, 4);
6256 tmp
= gen_ld32(addr
, IS_USER(s
));
6259 case 2: /* ldrexb */
6260 tmp
= gen_ld8u(addr
, IS_USER(s
));
6262 case 3: /* ldrexh */
6263 tmp
= gen_ld16u(addr
, IS_USER(s
));
6268 store_reg(s
, rd
, tmp
);
6270 int label
= gen_new_label();
6272 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6273 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6275 tmp
= load_reg(s
,rm
);
6278 gen_st32(tmp
, addr
, IS_USER(s
));
6280 case 1: /* strexd */
6281 gen_st32(tmp
, addr
, IS_USER(s
));
6282 tcg_gen_addi_i32(addr
, addr
, 4);
6283 tmp
= load_reg(s
, rm
+ 1);
6284 gen_st32(tmp
, addr
, IS_USER(s
));
6286 case 2: /* strexb */
6287 gen_st8(tmp
, addr
, IS_USER(s
));
6289 case 3: /* strexh */
6290 gen_st16(tmp
, addr
, IS_USER(s
));
6295 gen_set_label(label
);
6296 gen_movl_reg_T0(s
, rd
);
6299 /* SWP instruction */
6302 /* ??? This is not really atomic. However we know
6303 we never have multiple CPUs running in parallel,
6304 so it is good enough. */
6305 addr
= load_reg(s
, rn
);
6306 tmp
= load_reg(s
, rm
);
6307 if (insn
& (1 << 22)) {
6308 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6309 gen_st8(tmp
, addr
, IS_USER(s
));
6311 tmp2
= gen_ld32(addr
, IS_USER(s
));
6312 gen_st32(tmp
, addr
, IS_USER(s
));
6315 store_reg(s
, rd
, tmp2
);
6321 /* Misc load/store */
6322 rn
= (insn
>> 16) & 0xf;
6323 rd
= (insn
>> 12) & 0xf;
6324 addr
= load_reg(s
, rn
);
6325 if (insn
& (1 << 24))
6326 gen_add_datah_offset(s
, insn
, 0, addr
);
6328 if (insn
& (1 << 20)) {
6332 tmp
= gen_ld16u(addr
, IS_USER(s
));
6335 tmp
= gen_ld8s(addr
, IS_USER(s
));
6339 tmp
= gen_ld16s(addr
, IS_USER(s
));
6343 } else if (sh
& 2) {
6347 tmp
= load_reg(s
, rd
);
6348 gen_st32(tmp
, addr
, IS_USER(s
));
6349 tcg_gen_addi_i32(addr
, addr
, 4);
6350 tmp
= load_reg(s
, rd
+ 1);
6351 gen_st32(tmp
, addr
, IS_USER(s
));
6355 tmp
= gen_ld32(addr
, IS_USER(s
));
6356 store_reg(s
, rd
, tmp
);
6357 tcg_gen_addi_i32(addr
, addr
, 4);
6358 tmp
= gen_ld32(addr
, IS_USER(s
));
6362 address_offset
= -4;
6365 tmp
= load_reg(s
, rd
);
6366 gen_st16(tmp
, addr
, IS_USER(s
));
6369 /* Perform base writeback before the loaded value to
6370 ensure correct behavior with overlapping index registers.
6371 ldrd with base writeback is is undefined if the
6372 destination and index registers overlap. */
6373 if (!(insn
& (1 << 24))) {
6374 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6375 store_reg(s
, rn
, addr
);
6376 } else if (insn
& (1 << 21)) {
6378 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6379 store_reg(s
, rn
, addr
);
6384 /* Complete the load. */
6385 store_reg(s
, rd
, tmp
);
6394 if (insn
& (1 << 4)) {
6396 /* Armv6 Media instructions. */
6398 rn
= (insn
>> 16) & 0xf;
6399 rd
= (insn
>> 12) & 0xf;
6400 rs
= (insn
>> 8) & 0xf;
6401 switch ((insn
>> 23) & 3) {
6402 case 0: /* Parallel add/subtract. */
6403 op1
= (insn
>> 20) & 7;
6404 tmp
= load_reg(s
, rn
);
6405 tmp2
= load_reg(s
, rm
);
6406 sh
= (insn
>> 5) & 7;
6407 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6409 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6411 store_reg(s
, rd
, tmp
);
6414 if ((insn
& 0x00700020) == 0) {
6415 /* Halfword pack. */
6416 tmp
= load_reg(s
, rn
);
6417 tmp2
= load_reg(s
, rm
);
6418 shift
= (insn
>> 7) & 0x1f;
6419 if (insn
& (1 << 6)) {
6423 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6424 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6425 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6429 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6430 tcg_gen_ext16u_i32(tmp
, tmp
);
6431 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6433 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6435 store_reg(s
, rd
, tmp
);
6436 } else if ((insn
& 0x00200020) == 0x00200000) {
6438 tmp
= load_reg(s
, rm
);
6439 shift
= (insn
>> 7) & 0x1f;
6440 if (insn
& (1 << 6)) {
6443 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6445 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6447 sh
= (insn
>> 16) & 0x1f;
6449 if (insn
& (1 << 22))
6450 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6452 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6454 store_reg(s
, rd
, tmp
);
6455 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6457 tmp
= load_reg(s
, rm
);
6458 sh
= (insn
>> 16) & 0x1f;
6460 if (insn
& (1 << 22))
6461 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6463 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6465 store_reg(s
, rd
, tmp
);
6466 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6468 tmp
= load_reg(s
, rn
);
6469 tmp2
= load_reg(s
, rm
);
6471 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6472 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6475 store_reg(s
, rd
, tmp
);
6476 } else if ((insn
& 0x000003e0) == 0x00000060) {
6477 tmp
= load_reg(s
, rm
);
6478 shift
= (insn
>> 10) & 3;
6479 /* ??? In many cases it's not neccessary to do a
6480 rotate, a shift is sufficient. */
6482 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6483 op1
= (insn
>> 20) & 7;
6485 case 0: gen_sxtb16(tmp
); break;
6486 case 2: gen_sxtb(tmp
); break;
6487 case 3: gen_sxth(tmp
); break;
6488 case 4: gen_uxtb16(tmp
); break;
6489 case 6: gen_uxtb(tmp
); break;
6490 case 7: gen_uxth(tmp
); break;
6491 default: goto illegal_op
;
6494 tmp2
= load_reg(s
, rn
);
6495 if ((op1
& 3) == 0) {
6496 gen_add16(tmp
, tmp2
);
6498 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6502 store_reg(s
, rd
, tmp
);
6503 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6505 tmp
= load_reg(s
, rm
);
6506 if (insn
& (1 << 22)) {
6507 if (insn
& (1 << 7)) {
6511 gen_helper_rbit(tmp
, tmp
);
6514 if (insn
& (1 << 7))
6517 tcg_gen_bswap_i32(tmp
, tmp
);
6519 store_reg(s
, rd
, tmp
);
6524 case 2: /* Multiplies (Type 3). */
6525 tmp
= load_reg(s
, rm
);
6526 tmp2
= load_reg(s
, rs
);
6527 if (insn
& (1 << 20)) {
6528 /* Signed multiply most significant [accumulate]. */
6529 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6530 if (insn
& (1 << 5))
6531 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6532 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6534 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6536 tmp2
= load_reg(s
, rn
);
6537 if (insn
& (1 << 6)) {
6538 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6540 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6544 store_reg(s
, rd
, tmp
);
6546 if (insn
& (1 << 5))
6547 gen_swap_half(tmp2
);
6548 gen_smul_dual(tmp
, tmp2
);
6549 /* This addition cannot overflow. */
6550 if (insn
& (1 << 6)) {
6551 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6553 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6556 if (insn
& (1 << 22)) {
6557 /* smlald, smlsld */
6558 tmp64
= tcg_temp_new_i64();
6559 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6561 gen_addq(s
, tmp64
, rd
, rn
);
6562 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6564 /* smuad, smusd, smlad, smlsd */
6567 tmp2
= load_reg(s
, rd
);
6568 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6571 store_reg(s
, rn
, tmp
);
6576 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6578 case 0: /* Unsigned sum of absolute differences. */
6580 tmp
= load_reg(s
, rm
);
6581 tmp2
= load_reg(s
, rs
);
6582 gen_helper_usad8(tmp
, tmp
, tmp2
);
6585 tmp2
= load_reg(s
, rn
);
6586 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6589 store_reg(s
, rd
, tmp
);
6591 case 0x20: case 0x24: case 0x28: case 0x2c:
6592 /* Bitfield insert/clear. */
6594 shift
= (insn
>> 7) & 0x1f;
6595 i
= (insn
>> 16) & 0x1f;
6599 tcg_gen_movi_i32(tmp
, 0);
6601 tmp
= load_reg(s
, rm
);
6604 tmp2
= load_reg(s
, rd
);
6605 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6608 store_reg(s
, rd
, tmp
);
6610 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6611 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6612 tmp
= load_reg(s
, rm
);
6613 shift
= (insn
>> 7) & 0x1f;
6614 i
= ((insn
>> 16) & 0x1f) + 1;
6619 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6621 gen_sbfx(tmp
, shift
, i
);
6624 store_reg(s
, rd
, tmp
);
6634 /* Check for undefined extension instructions
6635 * per the ARM Bible IE:
6636 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6638 sh
= (0xf << 20) | (0xf << 4);
6639 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6643 /* load/store byte/word */
6644 rn
= (insn
>> 16) & 0xf;
6645 rd
= (insn
>> 12) & 0xf;
6646 tmp2
= load_reg(s
, rn
);
6647 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6648 if (insn
& (1 << 24))
6649 gen_add_data_offset(s
, insn
, tmp2
);
6650 if (insn
& (1 << 20)) {
6653 if (insn
& (1 << 22)) {
6654 tmp
= gen_ld8u(tmp2
, i
);
6656 tmp
= gen_ld32(tmp2
, i
);
6660 tmp
= load_reg(s
, rd
);
6661 if (insn
& (1 << 22))
6662 gen_st8(tmp
, tmp2
, i
);
6664 gen_st32(tmp
, tmp2
, i
);
6666 if (!(insn
& (1 << 24))) {
6667 gen_add_data_offset(s
, insn
, tmp2
);
6668 store_reg(s
, rn
, tmp2
);
6669 } else if (insn
& (1 << 21)) {
6670 store_reg(s
, rn
, tmp2
);
6674 if (insn
& (1 << 20)) {
6675 /* Complete the load. */
6679 store_reg(s
, rd
, tmp
);
6685 int j
, n
, user
, loaded_base
;
6687 /* load/store multiple words */
6688 /* XXX: store correct base if write back */
6690 if (insn
& (1 << 22)) {
6692 goto illegal_op
; /* only usable in supervisor mode */
6694 if ((insn
& (1 << 15)) == 0)
6697 rn
= (insn
>> 16) & 0xf;
6698 addr
= load_reg(s
, rn
);
6700 /* compute total size */
6702 TCGV_UNUSED(loaded_var
);
6705 if (insn
& (1 << i
))
6708 /* XXX: test invalid n == 0 case ? */
6709 if (insn
& (1 << 23)) {
6710 if (insn
& (1 << 24)) {
6712 tcg_gen_addi_i32(addr
, addr
, 4);
6714 /* post increment */
6717 if (insn
& (1 << 24)) {
6719 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6721 /* post decrement */
6723 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6728 if (insn
& (1 << i
)) {
6729 if (insn
& (1 << 20)) {
6731 tmp
= gen_ld32(addr
, IS_USER(s
));
6735 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6737 } else if (i
== rn
) {
6741 store_reg(s
, i
, tmp
);
6746 /* special case: r15 = PC + 8 */
6747 val
= (long)s
->pc
+ 4;
6749 tcg_gen_movi_i32(tmp
, val
);
6752 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6754 tmp
= load_reg(s
, i
);
6756 gen_st32(tmp
, addr
, IS_USER(s
));
6759 /* no need to add after the last transfer */
6761 tcg_gen_addi_i32(addr
, addr
, 4);
6764 if (insn
& (1 << 21)) {
6766 if (insn
& (1 << 23)) {
6767 if (insn
& (1 << 24)) {
6770 /* post increment */
6771 tcg_gen_addi_i32(addr
, addr
, 4);
6774 if (insn
& (1 << 24)) {
6777 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6779 /* post decrement */
6780 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6783 store_reg(s
, rn
, addr
);
6788 store_reg(s
, rn
, loaded_var
);
6790 if ((insn
& (1 << 22)) && !user
) {
6791 /* Restore CPSR from SPSR. */
6792 tmp
= load_cpu_field(spsr
);
6793 gen_set_cpsr(tmp
, 0xffffffff);
6795 s
->is_jmp
= DISAS_UPDATE
;
6804 /* branch (and link) */
6805 val
= (int32_t)s
->pc
;
6806 if (insn
& (1 << 24)) {
6808 tcg_gen_movi_i32(tmp
, val
);
6809 store_reg(s
, 14, tmp
);
6811 offset
= (((int32_t)insn
<< 8) >> 8);
6812 val
+= (offset
<< 2) + 4;
6820 if (disas_coproc_insn(env
, s
, insn
))
6825 gen_set_pc_im(s
->pc
);
6826 s
->is_jmp
= DISAS_SWI
;
6830 gen_set_condexec(s
);
6831 gen_set_pc_im(s
->pc
- 4);
6832 gen_exception(EXCP_UDEF
);
6833 s
->is_jmp
= DISAS_JUMP
;
6839 /* Return true if this is a Thumb-2 logical op. */
6841 thumb2_logic_op(int op
)
6846 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6847 then set condition code flags based on the result of the operation.
6848 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6849 to the high bit of T1.
6850 Returns zero if the opcode is valid. */
6853 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6860 gen_op_andl_T0_T1();
6864 gen_op_bicl_T0_T1();
6877 gen_op_xorl_T0_T1();
6882 gen_op_addl_T0_T1_cc();
6884 gen_op_addl_T0_T1();
6888 gen_op_adcl_T0_T1_cc();
6894 gen_op_sbcl_T0_T1_cc();
6900 gen_op_subl_T0_T1_cc();
6902 gen_op_subl_T0_T1();
6906 gen_op_rsbl_T0_T1_cc();
6908 gen_op_rsbl_T0_T1();
6910 default: /* 5, 6, 7, 9, 12, 15. */
6914 gen_op_logic_T0_cc();
6916 gen_set_CF_bit31(cpu_T
[1]);
6921 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6923 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6925 uint32_t insn
, imm
, shift
, offset
;
6926 uint32_t rd
, rn
, rm
, rs
;
6937 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
6938 || arm_feature (env
, ARM_FEATURE_M
))) {
6939 /* Thumb-1 cores may need to treat bl and blx as a pair of
6940 16-bit instructions to get correct prefetch abort behavior. */
6942 if ((insn
& (1 << 12)) == 0) {
6943 /* Second half of blx. */
6944 offset
= ((insn
& 0x7ff) << 1);
6945 tmp
= load_reg(s
, 14);
6946 tcg_gen_addi_i32(tmp
, tmp
, offset
);
6947 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
6950 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6951 store_reg(s
, 14, tmp2
);
6955 if (insn
& (1 << 11)) {
6956 /* Second half of bl. */
6957 offset
= ((insn
& 0x7ff) << 1) | 1;
6958 tmp
= load_reg(s
, 14);
6959 tcg_gen_addi_i32(tmp
, tmp
, offset
);
6962 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
6963 store_reg(s
, 14, tmp2
);
6967 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
6968 /* Instruction spans a page boundary. Implement it as two
6969 16-bit instructions in case the second half causes an
6971 offset
= ((int32_t)insn
<< 21) >> 9;
6972 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
6973 gen_movl_reg_T0(s
, 14);
6976 /* Fall through to 32-bit decode. */
6979 insn
= lduw_code(s
->pc
);
6981 insn
|= (uint32_t)insn_hw1
<< 16;
6983 if ((insn
& 0xf800e800) != 0xf000e800) {
6987 rn
= (insn
>> 16) & 0xf;
6988 rs
= (insn
>> 12) & 0xf;
6989 rd
= (insn
>> 8) & 0xf;
6991 switch ((insn
>> 25) & 0xf) {
6992 case 0: case 1: case 2: case 3:
6993 /* 16-bit instructions. Should never happen. */
6996 if (insn
& (1 << 22)) {
6997 /* Other load/store, table branch. */
6998 if (insn
& 0x01200000) {
6999 /* Load/store doubleword. */
7002 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7004 addr
= load_reg(s
, rn
);
7006 offset
= (insn
& 0xff) * 4;
7007 if ((insn
& (1 << 23)) == 0)
7009 if (insn
& (1 << 24)) {
7010 tcg_gen_addi_i32(addr
, addr
, offset
);
7013 if (insn
& (1 << 20)) {
7015 tmp
= gen_ld32(addr
, IS_USER(s
));
7016 store_reg(s
, rs
, tmp
);
7017 tcg_gen_addi_i32(addr
, addr
, 4);
7018 tmp
= gen_ld32(addr
, IS_USER(s
));
7019 store_reg(s
, rd
, tmp
);
7022 tmp
= load_reg(s
, rs
);
7023 gen_st32(tmp
, addr
, IS_USER(s
));
7024 tcg_gen_addi_i32(addr
, addr
, 4);
7025 tmp
= load_reg(s
, rd
);
7026 gen_st32(tmp
, addr
, IS_USER(s
));
7028 if (insn
& (1 << 21)) {
7029 /* Base writeback. */
7032 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7033 store_reg(s
, rn
, addr
);
7037 } else if ((insn
& (1 << 23)) == 0) {
7038 /* Load/store exclusive word. */
7039 gen_movl_T1_reg(s
, rn
);
7041 if (insn
& (1 << 20)) {
7042 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
7043 tmp
= gen_ld32(addr
, IS_USER(s
));
7044 store_reg(s
, rd
, tmp
);
7046 int label
= gen_new_label();
7047 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7048 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
7050 tmp
= load_reg(s
, rs
);
7051 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7052 gen_set_label(label
);
7053 gen_movl_reg_T0(s
, rd
);
7055 } else if ((insn
& (1 << 6)) == 0) {
7059 tcg_gen_movi_i32(addr
, s
->pc
);
7061 addr
= load_reg(s
, rn
);
7063 tmp
= load_reg(s
, rm
);
7064 tcg_gen_add_i32(addr
, addr
, tmp
);
7065 if (insn
& (1 << 4)) {
7067 tcg_gen_add_i32(addr
, addr
, tmp
);
7069 tmp
= gen_ld16u(addr
, IS_USER(s
));
7072 tmp
= gen_ld8u(addr
, IS_USER(s
));
7075 tcg_gen_shli_i32(tmp
, tmp
, 1);
7076 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7077 store_reg(s
, 15, tmp
);
7079 /* Load/store exclusive byte/halfword/doubleword. */
7080 /* ??? These are not really atomic. However we know
7081 we never have multiple CPUs running in parallel,
7082 so it is good enough. */
7083 op
= (insn
>> 4) & 0x3;
7084 /* Must use a global reg for the address because we have
7085 a conditional branch in the store instruction. */
7086 gen_movl_T1_reg(s
, rn
);
7088 if (insn
& (1 << 20)) {
7089 gen_helper_mark_exclusive(cpu_env
, addr
);
7092 tmp
= gen_ld8u(addr
, IS_USER(s
));
7095 tmp
= gen_ld16u(addr
, IS_USER(s
));
7098 tmp
= gen_ld32(addr
, IS_USER(s
));
7099 tcg_gen_addi_i32(addr
, addr
, 4);
7100 tmp2
= gen_ld32(addr
, IS_USER(s
));
7101 store_reg(s
, rd
, tmp2
);
7106 store_reg(s
, rs
, tmp
);
7108 int label
= gen_new_label();
7109 /* Must use a global that is not killed by the branch. */
7110 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7111 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7112 tmp
= load_reg(s
, rs
);
7115 gen_st8(tmp
, addr
, IS_USER(s
));
7118 gen_st16(tmp
, addr
, IS_USER(s
));
7121 gen_st32(tmp
, addr
, IS_USER(s
));
7122 tcg_gen_addi_i32(addr
, addr
, 4);
7123 tmp
= load_reg(s
, rd
);
7124 gen_st32(tmp
, addr
, IS_USER(s
));
7129 gen_set_label(label
);
7130 gen_movl_reg_T0(s
, rm
);
7134 /* Load/store multiple, RFE, SRS. */
7135 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7136 /* Not available in user mode. */
7139 if (insn
& (1 << 20)) {
7141 addr
= load_reg(s
, rn
);
7142 if ((insn
& (1 << 24)) == 0)
7143 tcg_gen_addi_i32(addr
, addr
, -8);
7144 /* Load PC into tmp and CPSR into tmp2. */
7145 tmp
= gen_ld32(addr
, 0);
7146 tcg_gen_addi_i32(addr
, addr
, 4);
7147 tmp2
= gen_ld32(addr
, 0);
7148 if (insn
& (1 << 21)) {
7149 /* Base writeback. */
7150 if (insn
& (1 << 24)) {
7151 tcg_gen_addi_i32(addr
, addr
, 4);
7153 tcg_gen_addi_i32(addr
, addr
, -4);
7155 store_reg(s
, rn
, addr
);
7159 gen_rfe(s
, tmp
, tmp2
);
7163 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7164 addr
= load_reg(s
, 13);
7167 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7169 if ((insn
& (1 << 24)) == 0) {
7170 tcg_gen_addi_i32(addr
, addr
, -8);
7172 tmp
= load_reg(s
, 14);
7173 gen_st32(tmp
, addr
, 0);
7174 tcg_gen_addi_i32(addr
, addr
, 4);
7176 gen_helper_cpsr_read(tmp
);
7177 gen_st32(tmp
, addr
, 0);
7178 if (insn
& (1 << 21)) {
7179 if ((insn
& (1 << 24)) == 0) {
7180 tcg_gen_addi_i32(addr
, addr
, -4);
7182 tcg_gen_addi_i32(addr
, addr
, 4);
7184 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7185 store_reg(s
, 13, addr
);
7187 gen_helper_set_r13_banked(cpu_env
,
7188 tcg_const_i32(op
), addr
);
7196 /* Load/store multiple. */
7197 addr
= load_reg(s
, rn
);
7199 for (i
= 0; i
< 16; i
++) {
7200 if (insn
& (1 << i
))
7203 if (insn
& (1 << 24)) {
7204 tcg_gen_addi_i32(addr
, addr
, -offset
);
7207 for (i
= 0; i
< 16; i
++) {
7208 if ((insn
& (1 << i
)) == 0)
7210 if (insn
& (1 << 20)) {
7212 tmp
= gen_ld32(addr
, IS_USER(s
));
7216 store_reg(s
, i
, tmp
);
7220 tmp
= load_reg(s
, i
);
7221 gen_st32(tmp
, addr
, IS_USER(s
));
7223 tcg_gen_addi_i32(addr
, addr
, 4);
7225 if (insn
& (1 << 21)) {
7226 /* Base register writeback. */
7227 if (insn
& (1 << 24)) {
7228 tcg_gen_addi_i32(addr
, addr
, -offset
);
7230 /* Fault if writeback register is in register list. */
7231 if (insn
& (1 << rn
))
7233 store_reg(s
, rn
, addr
);
7240 case 5: /* Data processing register constant shift. */
7242 gen_op_movl_T0_im(0);
7244 gen_movl_T0_reg(s
, rn
);
7245 gen_movl_T1_reg(s
, rm
);
7246 op
= (insn
>> 21) & 0xf;
7247 shiftop
= (insn
>> 4) & 3;
7248 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7249 conds
= (insn
& (1 << 20)) != 0;
7250 logic_cc
= (conds
&& thumb2_logic_op(op
));
7251 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7252 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7255 gen_movl_reg_T0(s
, rd
);
7257 case 13: /* Misc data processing. */
7258 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7259 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7262 case 0: /* Register controlled shift. */
7263 tmp
= load_reg(s
, rn
);
7264 tmp2
= load_reg(s
, rm
);
7265 if ((insn
& 0x70) != 0)
7267 op
= (insn
>> 21) & 3;
7268 logic_cc
= (insn
& (1 << 20)) != 0;
7269 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7272 store_reg(s
, rd
, tmp
);
7274 case 1: /* Sign/zero extend. */
7275 tmp
= load_reg(s
, rm
);
7276 shift
= (insn
>> 4) & 3;
7277 /* ??? In many cases it's not neccessary to do a
7278 rotate, a shift is sufficient. */
7280 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7281 op
= (insn
>> 20) & 7;
7283 case 0: gen_sxth(tmp
); break;
7284 case 1: gen_uxth(tmp
); break;
7285 case 2: gen_sxtb16(tmp
); break;
7286 case 3: gen_uxtb16(tmp
); break;
7287 case 4: gen_sxtb(tmp
); break;
7288 case 5: gen_uxtb(tmp
); break;
7289 default: goto illegal_op
;
7292 tmp2
= load_reg(s
, rn
);
7293 if ((op
>> 1) == 1) {
7294 gen_add16(tmp
, tmp2
);
7296 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7300 store_reg(s
, rd
, tmp
);
7302 case 2: /* SIMD add/subtract. */
7303 op
= (insn
>> 20) & 7;
7304 shift
= (insn
>> 4) & 7;
7305 if ((op
& 3) == 3 || (shift
& 3) == 3)
7307 tmp
= load_reg(s
, rn
);
7308 tmp2
= load_reg(s
, rm
);
7309 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7311 store_reg(s
, rd
, tmp
);
7313 case 3: /* Other data processing. */
7314 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7316 /* Saturating add/subtract. */
7317 tmp
= load_reg(s
, rn
);
7318 tmp2
= load_reg(s
, rm
);
7320 gen_helper_double_saturate(tmp
, tmp
);
7322 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7324 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7327 tmp
= load_reg(s
, rn
);
7329 case 0x0a: /* rbit */
7330 gen_helper_rbit(tmp
, tmp
);
7332 case 0x08: /* rev */
7333 tcg_gen_bswap_i32(tmp
, tmp
);
7335 case 0x09: /* rev16 */
7338 case 0x0b: /* revsh */
7341 case 0x10: /* sel */
7342 tmp2
= load_reg(s
, rm
);
7344 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7345 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7349 case 0x18: /* clz */
7350 gen_helper_clz(tmp
, tmp
);
7356 store_reg(s
, rd
, tmp
);
7358 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7359 op
= (insn
>> 4) & 0xf;
7360 tmp
= load_reg(s
, rn
);
7361 tmp2
= load_reg(s
, rm
);
7362 switch ((insn
>> 20) & 7) {
7363 case 0: /* 32 x 32 -> 32 */
7364 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7367 tmp2
= load_reg(s
, rs
);
7369 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7371 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7375 case 1: /* 16 x 16 -> 32 */
7376 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7379 tmp2
= load_reg(s
, rs
);
7380 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7384 case 2: /* Dual multiply add. */
7385 case 4: /* Dual multiply subtract. */
7387 gen_swap_half(tmp2
);
7388 gen_smul_dual(tmp
, tmp2
);
7389 /* This addition cannot overflow. */
7390 if (insn
& (1 << 22)) {
7391 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7393 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7398 tmp2
= load_reg(s
, rs
);
7399 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7403 case 3: /* 32 * 16 -> 32msb */
7405 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7408 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7409 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7411 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7414 tmp2
= load_reg(s
, rs
);
7415 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7419 case 5: case 6: /* 32 * 32 -> 32msb */
7420 gen_imull(tmp
, tmp2
);
7421 if (insn
& (1 << 5)) {
7422 gen_roundqd(tmp
, tmp2
);
7429 tmp2
= load_reg(s
, rs
);
7430 if (insn
& (1 << 21)) {
7431 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7433 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7438 case 7: /* Unsigned sum of absolute differences. */
7439 gen_helper_usad8(tmp
, tmp
, tmp2
);
7442 tmp2
= load_reg(s
, rs
);
7443 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7448 store_reg(s
, rd
, tmp
);
7450 case 6: case 7: /* 64-bit multiply, Divide. */
7451 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7452 tmp
= load_reg(s
, rn
);
7453 tmp2
= load_reg(s
, rm
);
7454 if ((op
& 0x50) == 0x10) {
7456 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7459 gen_helper_udiv(tmp
, tmp
, tmp2
);
7461 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7463 store_reg(s
, rd
, tmp
);
7464 } else if ((op
& 0xe) == 0xc) {
7465 /* Dual multiply accumulate long. */
7467 gen_swap_half(tmp2
);
7468 gen_smul_dual(tmp
, tmp2
);
7470 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7472 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7476 tmp64
= tcg_temp_new_i64();
7477 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7479 gen_addq(s
, tmp64
, rs
, rd
);
7480 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7483 /* Unsigned 64-bit multiply */
7484 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7488 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7490 tmp64
= tcg_temp_new_i64();
7491 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7494 /* Signed 64-bit multiply */
7495 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7500 gen_addq_lo(s
, tmp64
, rs
);
7501 gen_addq_lo(s
, tmp64
, rd
);
7502 } else if (op
& 0x40) {
7503 /* 64-bit accumulate. */
7504 gen_addq(s
, tmp64
, rs
, rd
);
7506 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7511 case 6: case 7: case 14: case 15:
7513 if (((insn
>> 24) & 3) == 3) {
7514 /* Translate into the equivalent ARM encoding. */
7515 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7516 if (disas_neon_data_insn(env
, s
, insn
))
7519 if (insn
& (1 << 28))
7521 if (disas_coproc_insn (env
, s
, insn
))
7525 case 8: case 9: case 10: case 11:
7526 if (insn
& (1 << 15)) {
7527 /* Branches, misc control. */
7528 if (insn
& 0x5000) {
7529 /* Unconditional branch. */
7530 /* signextend(hw1[10:0]) -> offset[:12]. */
7531 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7532 /* hw1[10:0] -> offset[11:1]. */
7533 offset
|= (insn
& 0x7ff) << 1;
7534 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7535 offset[24:22] already have the same value because of the
7536 sign extension above. */
7537 offset
^= ((~insn
) & (1 << 13)) << 10;
7538 offset
^= ((~insn
) & (1 << 11)) << 11;
7540 if (insn
& (1 << 14)) {
7541 /* Branch and link. */
7542 gen_op_movl_T1_im(s
->pc
| 1);
7543 gen_movl_reg_T1(s
, 14);
7547 if (insn
& (1 << 12)) {
7552 offset
&= ~(uint32_t)2;
7553 gen_bx_im(s
, offset
);
7555 } else if (((insn
>> 23) & 7) == 7) {
7557 if (insn
& (1 << 13))
7560 if (insn
& (1 << 26)) {
7561 /* Secure monitor call (v6Z) */
7562 goto illegal_op
; /* not implemented. */
7564 op
= (insn
>> 20) & 7;
7566 case 0: /* msr cpsr. */
7568 tmp
= load_reg(s
, rn
);
7569 addr
= tcg_const_i32(insn
& 0xff);
7570 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7575 case 1: /* msr spsr. */
7578 gen_movl_T0_reg(s
, rn
);
7579 if (gen_set_psr_T0(s
,
7580 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7584 case 2: /* cps, nop-hint. */
7585 if (((insn
>> 8) & 7) == 0) {
7586 gen_nop_hint(s
, insn
& 0xff);
7588 /* Implemented as NOP in user mode. */
7593 if (insn
& (1 << 10)) {
7594 if (insn
& (1 << 7))
7596 if (insn
& (1 << 6))
7598 if (insn
& (1 << 5))
7600 if (insn
& (1 << 9))
7601 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7603 if (insn
& (1 << 8)) {
7605 imm
|= (insn
& 0x1f);
7608 gen_op_movl_T0_im(imm
);
7609 gen_set_psr_T0(s
, offset
, 0);
7612 case 3: /* Special control operations. */
7613 op
= (insn
>> 4) & 0xf;
7616 gen_helper_clrex(cpu_env
);
7621 /* These execute as NOPs. */
7629 /* Trivial implementation equivalent to bx. */
7630 tmp
= load_reg(s
, rn
);
7633 case 5: /* Exception return. */
7634 /* Unpredictable in user mode. */
7636 case 6: /* mrs cpsr. */
7639 addr
= tcg_const_i32(insn
& 0xff);
7640 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7642 gen_helper_cpsr_read(tmp
);
7644 store_reg(s
, rd
, tmp
);
7646 case 7: /* mrs spsr. */
7647 /* Not accessible in user mode. */
7648 if (IS_USER(s
) || IS_M(env
))
7650 tmp
= load_cpu_field(spsr
);
7651 store_reg(s
, rd
, tmp
);
7656 /* Conditional branch. */
7657 op
= (insn
>> 22) & 0xf;
7658 /* Generate a conditional jump to next instruction. */
7659 s
->condlabel
= gen_new_label();
7660 gen_test_cc(op
^ 1, s
->condlabel
);
7663 /* offset[11:1] = insn[10:0] */
7664 offset
= (insn
& 0x7ff) << 1;
7665 /* offset[17:12] = insn[21:16]. */
7666 offset
|= (insn
& 0x003f0000) >> 4;
7667 /* offset[31:20] = insn[26]. */
7668 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7669 /* offset[18] = insn[13]. */
7670 offset
|= (insn
& (1 << 13)) << 5;
7671 /* offset[19] = insn[11]. */
7672 offset
|= (insn
& (1 << 11)) << 8;
7674 /* jump to the offset */
7675 gen_jmp(s
, s
->pc
+ offset
);
7678 /* Data processing immediate. */
7679 if (insn
& (1 << 25)) {
7680 if (insn
& (1 << 24)) {
7681 if (insn
& (1 << 20))
7683 /* Bitfield/Saturate. */
7684 op
= (insn
>> 21) & 7;
7686 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7689 tcg_gen_movi_i32(tmp
, 0);
7691 tmp
= load_reg(s
, rn
);
7694 case 2: /* Signed bitfield extract. */
7696 if (shift
+ imm
> 32)
7699 gen_sbfx(tmp
, shift
, imm
);
7701 case 6: /* Unsigned bitfield extract. */
7703 if (shift
+ imm
> 32)
7706 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7708 case 3: /* Bitfield insert/clear. */
7711 imm
= imm
+ 1 - shift
;
7713 tmp2
= load_reg(s
, rd
);
7714 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7720 default: /* Saturate. */
7723 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7725 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7727 tmp2
= tcg_const_i32(imm
);
7730 if ((op
& 1) && shift
== 0)
7731 gen_helper_usat16(tmp
, tmp
, tmp2
);
7733 gen_helper_usat(tmp
, tmp
, tmp2
);
7736 if ((op
& 1) && shift
== 0)
7737 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7739 gen_helper_ssat(tmp
, tmp
, tmp2
);
7743 store_reg(s
, rd
, tmp
);
7745 imm
= ((insn
& 0x04000000) >> 15)
7746 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7747 if (insn
& (1 << 22)) {
7748 /* 16-bit immediate. */
7749 imm
|= (insn
>> 4) & 0xf000;
7750 if (insn
& (1 << 23)) {
7752 tmp
= load_reg(s
, rd
);
7753 tcg_gen_ext16u_i32(tmp
, tmp
);
7754 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7758 tcg_gen_movi_i32(tmp
, imm
);
7761 /* Add/sub 12-bit immediate. */
7763 offset
= s
->pc
& ~(uint32_t)3;
7764 if (insn
& (1 << 23))
7769 tcg_gen_movi_i32(tmp
, offset
);
7771 tmp
= load_reg(s
, rn
);
7772 if (insn
& (1 << 23))
7773 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7775 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7778 store_reg(s
, rd
, tmp
);
7781 int shifter_out
= 0;
7782 /* modified 12-bit immediate. */
7783 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7784 imm
= (insn
& 0xff);
7787 /* Nothing to do. */
7789 case 1: /* 00XY00XY */
7792 case 2: /* XY00XY00 */
7796 case 3: /* XYXYXYXY */
7800 default: /* Rotated constant. */
7801 shift
= (shift
<< 1) | (imm
>> 7);
7803 imm
= imm
<< (32 - shift
);
7807 gen_op_movl_T1_im(imm
);
7808 rn
= (insn
>> 16) & 0xf;
7810 gen_op_movl_T0_im(0);
7812 gen_movl_T0_reg(s
, rn
);
7813 op
= (insn
>> 21) & 0xf;
7814 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7817 rd
= (insn
>> 8) & 0xf;
7819 gen_movl_reg_T0(s
, rd
);
7824 case 12: /* Load/store single data item. */
7829 if ((insn
& 0x01100000) == 0x01000000) {
7830 if (disas_neon_ls_insn(env
, s
, insn
))
7838 /* s->pc has already been incremented by 4. */
7839 imm
= s
->pc
& 0xfffffffc;
7840 if (insn
& (1 << 23))
7841 imm
+= insn
& 0xfff;
7843 imm
-= insn
& 0xfff;
7844 tcg_gen_movi_i32(addr
, imm
);
7846 addr
= load_reg(s
, rn
);
7847 if (insn
& (1 << 23)) {
7848 /* Positive offset. */
7850 tcg_gen_addi_i32(addr
, addr
, imm
);
7852 op
= (insn
>> 8) & 7;
7855 case 0: case 8: /* Shifted Register. */
7856 shift
= (insn
>> 4) & 0xf;
7859 tmp
= load_reg(s
, rm
);
7861 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7862 tcg_gen_add_i32(addr
, addr
, tmp
);
7865 case 4: /* Negative offset. */
7866 tcg_gen_addi_i32(addr
, addr
, -imm
);
7868 case 6: /* User privilege. */
7869 tcg_gen_addi_i32(addr
, addr
, imm
);
7872 case 1: /* Post-decrement. */
7875 case 3: /* Post-increment. */
7879 case 5: /* Pre-decrement. */
7882 case 7: /* Pre-increment. */
7883 tcg_gen_addi_i32(addr
, addr
, imm
);
7891 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7892 if (insn
& (1 << 20)) {
7894 if (rs
== 15 && op
!= 2) {
7897 /* Memory hint. Implemented as NOP. */
7900 case 0: tmp
= gen_ld8u(addr
, user
); break;
7901 case 4: tmp
= gen_ld8s(addr
, user
); break;
7902 case 1: tmp
= gen_ld16u(addr
, user
); break;
7903 case 5: tmp
= gen_ld16s(addr
, user
); break;
7904 case 2: tmp
= gen_ld32(addr
, user
); break;
7905 default: goto illegal_op
;
7910 store_reg(s
, rs
, tmp
);
7917 tmp
= load_reg(s
, rs
);
7919 case 0: gen_st8(tmp
, addr
, user
); break;
7920 case 1: gen_st16(tmp
, addr
, user
); break;
7921 case 2: gen_st32(tmp
, addr
, user
); break;
7922 default: goto illegal_op
;
7926 tcg_gen_addi_i32(addr
, addr
, imm
);
7928 store_reg(s
, rn
, addr
);
7942 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
7944 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
7951 if (s
->condexec_mask
) {
7952 cond
= s
->condexec_cond
;
7953 s
->condlabel
= gen_new_label();
7954 gen_test_cc(cond
^ 1, s
->condlabel
);
7958 insn
= lduw_code(s
->pc
);
7961 switch (insn
>> 12) {
7964 op
= (insn
>> 11) & 3;
7967 rn
= (insn
>> 3) & 7;
7968 gen_movl_T0_reg(s
, rn
);
7969 if (insn
& (1 << 10)) {
7971 gen_op_movl_T1_im((insn
>> 6) & 7);
7974 rm
= (insn
>> 6) & 7;
7975 gen_movl_T1_reg(s
, rm
);
7977 if (insn
& (1 << 9)) {
7978 if (s
->condexec_mask
)
7979 gen_op_subl_T0_T1();
7981 gen_op_subl_T0_T1_cc();
7983 if (s
->condexec_mask
)
7984 gen_op_addl_T0_T1();
7986 gen_op_addl_T0_T1_cc();
7988 gen_movl_reg_T0(s
, rd
);
7990 /* shift immediate */
7991 rm
= (insn
>> 3) & 7;
7992 shift
= (insn
>> 6) & 0x1f;
7993 tmp
= load_reg(s
, rm
);
7994 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
7995 if (!s
->condexec_mask
)
7997 store_reg(s
, rd
, tmp
);
8001 /* arithmetic large immediate */
8002 op
= (insn
>> 11) & 3;
8003 rd
= (insn
>> 8) & 0x7;
8005 gen_op_movl_T0_im(insn
& 0xff);
8007 gen_movl_T0_reg(s
, rd
);
8008 gen_op_movl_T1_im(insn
& 0xff);
8012 if (!s
->condexec_mask
)
8013 gen_op_logic_T0_cc();
8016 gen_op_subl_T0_T1_cc();
8019 if (s
->condexec_mask
)
8020 gen_op_addl_T0_T1();
8022 gen_op_addl_T0_T1_cc();
8025 if (s
->condexec_mask
)
8026 gen_op_subl_T0_T1();
8028 gen_op_subl_T0_T1_cc();
8032 gen_movl_reg_T0(s
, rd
);
8035 if (insn
& (1 << 11)) {
8036 rd
= (insn
>> 8) & 7;
8037 /* load pc-relative. Bit 1 of PC is ignored. */
8038 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8039 val
&= ~(uint32_t)2;
8041 tcg_gen_movi_i32(addr
, val
);
8042 tmp
= gen_ld32(addr
, IS_USER(s
));
8044 store_reg(s
, rd
, tmp
);
8047 if (insn
& (1 << 10)) {
8048 /* data processing extended or blx */
8049 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8050 rm
= (insn
>> 3) & 0xf;
8051 op
= (insn
>> 8) & 3;
8054 gen_movl_T0_reg(s
, rd
);
8055 gen_movl_T1_reg(s
, rm
);
8056 gen_op_addl_T0_T1();
8057 gen_movl_reg_T0(s
, rd
);
8060 gen_movl_T0_reg(s
, rd
);
8061 gen_movl_T1_reg(s
, rm
);
8062 gen_op_subl_T0_T1_cc();
8064 case 2: /* mov/cpy */
8065 gen_movl_T0_reg(s
, rm
);
8066 gen_movl_reg_T0(s
, rd
);
8068 case 3:/* branch [and link] exchange thumb register */
8069 tmp
= load_reg(s
, rm
);
8070 if (insn
& (1 << 7)) {
8071 val
= (uint32_t)s
->pc
| 1;
8073 tcg_gen_movi_i32(tmp2
, val
);
8074 store_reg(s
, 14, tmp2
);
8082 /* data processing register */
8084 rm
= (insn
>> 3) & 7;
8085 op
= (insn
>> 6) & 0xf;
8086 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8087 /* the shift/rotate ops want the operands backwards */
8096 if (op
== 9) /* neg */
8097 gen_op_movl_T0_im(0);
8098 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8099 gen_movl_T0_reg(s
, rd
);
8101 gen_movl_T1_reg(s
, rm
);
8104 gen_op_andl_T0_T1();
8105 if (!s
->condexec_mask
)
8106 gen_op_logic_T0_cc();
8109 gen_op_xorl_T0_T1();
8110 if (!s
->condexec_mask
)
8111 gen_op_logic_T0_cc();
8114 if (s
->condexec_mask
) {
8115 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8117 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8118 gen_op_logic_T1_cc();
8122 if (s
->condexec_mask
) {
8123 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8125 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8126 gen_op_logic_T1_cc();
8130 if (s
->condexec_mask
) {
8131 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8133 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8134 gen_op_logic_T1_cc();
8138 if (s
->condexec_mask
)
8141 gen_op_adcl_T0_T1_cc();
8144 if (s
->condexec_mask
)
8147 gen_op_sbcl_T0_T1_cc();
8150 if (s
->condexec_mask
) {
8151 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8153 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8154 gen_op_logic_T1_cc();
8158 gen_op_andl_T0_T1();
8159 gen_op_logic_T0_cc();
8163 if (s
->condexec_mask
)
8164 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8166 gen_op_subl_T0_T1_cc();
8169 gen_op_subl_T0_T1_cc();
8173 gen_op_addl_T0_T1_cc();
8178 if (!s
->condexec_mask
)
8179 gen_op_logic_T0_cc();
8182 gen_op_mull_T0_T1();
8183 if (!s
->condexec_mask
)
8184 gen_op_logic_T0_cc();
8187 gen_op_bicl_T0_T1();
8188 if (!s
->condexec_mask
)
8189 gen_op_logic_T0_cc();
8193 if (!s
->condexec_mask
)
8194 gen_op_logic_T1_cc();
8201 gen_movl_reg_T1(s
, rm
);
8203 gen_movl_reg_T0(s
, rd
);
8208 /* load/store register offset. */
8210 rn
= (insn
>> 3) & 7;
8211 rm
= (insn
>> 6) & 7;
8212 op
= (insn
>> 9) & 7;
8213 addr
= load_reg(s
, rn
);
8214 tmp
= load_reg(s
, rm
);
8215 tcg_gen_add_i32(addr
, addr
, tmp
);
8218 if (op
< 3) /* store */
8219 tmp
= load_reg(s
, rd
);
8223 gen_st32(tmp
, addr
, IS_USER(s
));
8226 gen_st16(tmp
, addr
, IS_USER(s
));
8229 gen_st8(tmp
, addr
, IS_USER(s
));
8232 tmp
= gen_ld8s(addr
, IS_USER(s
));
8235 tmp
= gen_ld32(addr
, IS_USER(s
));
8238 tmp
= gen_ld16u(addr
, IS_USER(s
));
8241 tmp
= gen_ld8u(addr
, IS_USER(s
));
8244 tmp
= gen_ld16s(addr
, IS_USER(s
));
8247 if (op
>= 3) /* load */
8248 store_reg(s
, rd
, tmp
);
8253 /* load/store word immediate offset */
8255 rn
= (insn
>> 3) & 7;
8256 addr
= load_reg(s
, rn
);
8257 val
= (insn
>> 4) & 0x7c;
8258 tcg_gen_addi_i32(addr
, addr
, val
);
8260 if (insn
& (1 << 11)) {
8262 tmp
= gen_ld32(addr
, IS_USER(s
));
8263 store_reg(s
, rd
, tmp
);
8266 tmp
= load_reg(s
, rd
);
8267 gen_st32(tmp
, addr
, IS_USER(s
));
8273 /* load/store byte immediate offset */
8275 rn
= (insn
>> 3) & 7;
8276 addr
= load_reg(s
, rn
);
8277 val
= (insn
>> 6) & 0x1f;
8278 tcg_gen_addi_i32(addr
, addr
, val
);
8280 if (insn
& (1 << 11)) {
8282 tmp
= gen_ld8u(addr
, IS_USER(s
));
8283 store_reg(s
, rd
, tmp
);
8286 tmp
= load_reg(s
, rd
);
8287 gen_st8(tmp
, addr
, IS_USER(s
));
8293 /* load/store halfword immediate offset */
8295 rn
= (insn
>> 3) & 7;
8296 addr
= load_reg(s
, rn
);
8297 val
= (insn
>> 5) & 0x3e;
8298 tcg_gen_addi_i32(addr
, addr
, val
);
8300 if (insn
& (1 << 11)) {
8302 tmp
= gen_ld16u(addr
, IS_USER(s
));
8303 store_reg(s
, rd
, tmp
);
8306 tmp
= load_reg(s
, rd
);
8307 gen_st16(tmp
, addr
, IS_USER(s
));
8313 /* load/store from stack */
8314 rd
= (insn
>> 8) & 7;
8315 addr
= load_reg(s
, 13);
8316 val
= (insn
& 0xff) * 4;
8317 tcg_gen_addi_i32(addr
, addr
, val
);
8319 if (insn
& (1 << 11)) {
8321 tmp
= gen_ld32(addr
, IS_USER(s
));
8322 store_reg(s
, rd
, tmp
);
8325 tmp
= load_reg(s
, rd
);
8326 gen_st32(tmp
, addr
, IS_USER(s
));
8332 /* add to high reg */
8333 rd
= (insn
>> 8) & 7;
8334 if (insn
& (1 << 11)) {
8336 tmp
= load_reg(s
, 13);
8338 /* PC. bit 1 is ignored. */
8340 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8342 val
= (insn
& 0xff) * 4;
8343 tcg_gen_addi_i32(tmp
, tmp
, val
);
8344 store_reg(s
, rd
, tmp
);
8349 op
= (insn
>> 8) & 0xf;
8352 /* adjust stack pointer */
8353 tmp
= load_reg(s
, 13);
8354 val
= (insn
& 0x7f) * 4;
8355 if (insn
& (1 << 7))
8356 val
= -(int32_t)val
;
8357 tcg_gen_addi_i32(tmp
, tmp
, val
);
8358 store_reg(s
, 13, tmp
);
8361 case 2: /* sign/zero extend. */
8364 rm
= (insn
>> 3) & 7;
8365 tmp
= load_reg(s
, rm
);
8366 switch ((insn
>> 6) & 3) {
8367 case 0: gen_sxth(tmp
); break;
8368 case 1: gen_sxtb(tmp
); break;
8369 case 2: gen_uxth(tmp
); break;
8370 case 3: gen_uxtb(tmp
); break;
8372 store_reg(s
, rd
, tmp
);
8374 case 4: case 5: case 0xc: case 0xd:
8376 addr
= load_reg(s
, 13);
8377 if (insn
& (1 << 8))
8381 for (i
= 0; i
< 8; i
++) {
8382 if (insn
& (1 << i
))
8385 if ((insn
& (1 << 11)) == 0) {
8386 tcg_gen_addi_i32(addr
, addr
, -offset
);
8388 for (i
= 0; i
< 8; i
++) {
8389 if (insn
& (1 << i
)) {
8390 if (insn
& (1 << 11)) {
8392 tmp
= gen_ld32(addr
, IS_USER(s
));
8393 store_reg(s
, i
, tmp
);
8396 tmp
= load_reg(s
, i
);
8397 gen_st32(tmp
, addr
, IS_USER(s
));
8399 /* advance to the next address. */
8400 tcg_gen_addi_i32(addr
, addr
, 4);
8404 if (insn
& (1 << 8)) {
8405 if (insn
& (1 << 11)) {
8407 tmp
= gen_ld32(addr
, IS_USER(s
));
8408 /* don't set the pc until the rest of the instruction
8412 tmp
= load_reg(s
, 14);
8413 gen_st32(tmp
, addr
, IS_USER(s
));
8415 tcg_gen_addi_i32(addr
, addr
, 4);
8417 if ((insn
& (1 << 11)) == 0) {
8418 tcg_gen_addi_i32(addr
, addr
, -offset
);
8420 /* write back the new stack pointer */
8421 store_reg(s
, 13, addr
);
8422 /* set the new PC value */
8423 if ((insn
& 0x0900) == 0x0900)
8427 case 1: case 3: case 9: case 11: /* czb */
8429 tmp
= load_reg(s
, rm
);
8430 s
->condlabel
= gen_new_label();
8432 if (insn
& (1 << 11))
8433 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8435 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8437 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8438 val
= (uint32_t)s
->pc
+ 2;
8443 case 15: /* IT, nop-hint. */
8444 if ((insn
& 0xf) == 0) {
8445 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8449 s
->condexec_cond
= (insn
>> 4) & 0xe;
8450 s
->condexec_mask
= insn
& 0x1f;
8451 /* No actual code generated for this insn, just setup state. */
8454 case 0xe: /* bkpt */
8455 gen_set_condexec(s
);
8456 gen_set_pc_im(s
->pc
- 2);
8457 gen_exception(EXCP_BKPT
);
8458 s
->is_jmp
= DISAS_JUMP
;
8463 rn
= (insn
>> 3) & 0x7;
8465 tmp
= load_reg(s
, rn
);
8466 switch ((insn
>> 6) & 3) {
8467 case 0: tcg_gen_bswap_i32(tmp
, tmp
); break;
8468 case 1: gen_rev16(tmp
); break;
8469 case 3: gen_revsh(tmp
); break;
8470 default: goto illegal_op
;
8472 store_reg(s
, rd
, tmp
);
8480 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8483 addr
= tcg_const_i32(16);
8484 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8488 addr
= tcg_const_i32(17);
8489 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8493 if (insn
& (1 << 4))
8494 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8498 val
= ((insn
& 7) << 6) & shift
;
8499 gen_op_movl_T0_im(val
);
8500 gen_set_psr_T0(s
, shift
, 0);
8510 /* load/store multiple */
8511 rn
= (insn
>> 8) & 0x7;
8512 addr
= load_reg(s
, rn
);
8513 for (i
= 0; i
< 8; i
++) {
8514 if (insn
& (1 << i
)) {
8515 if (insn
& (1 << 11)) {
8517 tmp
= gen_ld32(addr
, IS_USER(s
));
8518 store_reg(s
, i
, tmp
);
8521 tmp
= load_reg(s
, i
);
8522 gen_st32(tmp
, addr
, IS_USER(s
));
8524 /* advance to the next address */
8525 tcg_gen_addi_i32(addr
, addr
, 4);
8528 /* Base register writeback. */
8529 if ((insn
& (1 << rn
)) == 0) {
8530 store_reg(s
, rn
, addr
);
8537 /* conditional branch or swi */
8538 cond
= (insn
>> 8) & 0xf;
8544 gen_set_condexec(s
);
8545 gen_set_pc_im(s
->pc
);
8546 s
->is_jmp
= DISAS_SWI
;
8549 /* generate a conditional jump to next instruction */
8550 s
->condlabel
= gen_new_label();
8551 gen_test_cc(cond
^ 1, s
->condlabel
);
8553 gen_movl_T1_reg(s
, 15);
8555 /* jump to the offset */
8556 val
= (uint32_t)s
->pc
+ 2;
8557 offset
= ((int32_t)insn
<< 24) >> 24;
8563 if (insn
& (1 << 11)) {
8564 if (disas_thumb2_insn(env
, s
, insn
))
8568 /* unconditional branch */
8569 val
= (uint32_t)s
->pc
;
8570 offset
= ((int32_t)insn
<< 21) >> 21;
8571 val
+= (offset
<< 1) + 2;
8576 if (disas_thumb2_insn(env
, s
, insn
))
8582 gen_set_condexec(s
);
8583 gen_set_pc_im(s
->pc
- 4);
8584 gen_exception(EXCP_UDEF
);
8585 s
->is_jmp
= DISAS_JUMP
;
8589 gen_set_condexec(s
);
8590 gen_set_pc_im(s
->pc
- 2);
8591 gen_exception(EXCP_UDEF
);
8592 s
->is_jmp
= DISAS_JUMP
;
8595 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8596 basic block 'tb'. If search_pc is TRUE, also generate PC
8597 information for each intermediate instruction. */
8598 static inline void gen_intermediate_code_internal(CPUState
*env
,
8599 TranslationBlock
*tb
,
8602 DisasContext dc1
, *dc
= &dc1
;
8604 uint16_t *gen_opc_end
;
8606 target_ulong pc_start
;
8607 uint32_t next_page_start
;
8611 /* generate intermediate code */
8613 memset(temps
, 0, sizeof(temps
));
8619 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8621 dc
->is_jmp
= DISAS_NEXT
;
8623 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8625 dc
->thumb
= env
->thumb
;
8626 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8627 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8629 #if !defined(CONFIG_USER_ONLY)
8631 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8633 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8636 cpu_F0s
= tcg_temp_new_i32();
8637 cpu_F1s
= tcg_temp_new_i32();
8638 cpu_F0d
= tcg_temp_new_i64();
8639 cpu_F1d
= tcg_temp_new_i64();
8642 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8643 cpu_M0
= tcg_temp_new_i64();
8644 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8647 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8649 max_insns
= CF_COUNT_MASK
;
8652 /* Reset the conditional execution bits immediately. This avoids
8653 complications trying to do it at the end of the block. */
8654 if (env
->condexec_bits
)
8656 TCGv tmp
= new_tmp();
8657 tcg_gen_movi_i32(tmp
, 0);
8658 store_cpu_field(tmp
, condexec_bits
);
8661 #ifdef CONFIG_USER_ONLY
8662 /* Intercept jump to the magic kernel page. */
8663 if (dc
->pc
>= 0xffff0000) {
8664 /* We always get here via a jump, so know we are not in a
8665 conditional execution block. */
8666 gen_exception(EXCP_KERNEL_TRAP
);
8667 dc
->is_jmp
= DISAS_UPDATE
;
8671 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8672 /* We always get here via a jump, so know we are not in a
8673 conditional execution block. */
8674 gen_exception(EXCP_EXCEPTION_EXIT
);
8675 dc
->is_jmp
= DISAS_UPDATE
;
8680 if (unlikely(!TAILQ_EMPTY(&env
->breakpoints
))) {
8681 TAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8682 if (bp
->pc
== dc
->pc
) {
8683 gen_set_condexec(dc
);
8684 gen_set_pc_im(dc
->pc
);
8685 gen_exception(EXCP_DEBUG
);
8686 dc
->is_jmp
= DISAS_JUMP
;
8687 /* Advance PC so that clearing the breakpoint will
8688 invalidate this TB. */
8690 goto done_generating
;
8696 j
= gen_opc_ptr
- gen_opc_buf
;
8700 gen_opc_instr_start
[lj
++] = 0;
8702 gen_opc_pc
[lj
] = dc
->pc
;
8703 gen_opc_instr_start
[lj
] = 1;
8704 gen_opc_icount
[lj
] = num_insns
;
8707 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8711 disas_thumb_insn(env
, dc
);
8712 if (dc
->condexec_mask
) {
8713 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8714 | ((dc
->condexec_mask
>> 4) & 1);
8715 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8716 if (dc
->condexec_mask
== 0) {
8717 dc
->condexec_cond
= 0;
8721 disas_arm_insn(env
, dc
);
8724 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8728 if (dc
->condjmp
&& !dc
->is_jmp
) {
8729 gen_set_label(dc
->condlabel
);
8732 /* Translation stops when a conditional branch is enoutered.
8733 * Otherwise the subsequent code could get translated several times.
8734 * Also stop translation when a page boundary is reached. This
8735 * ensures prefetch aborts occur at the right place. */
8737 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8738 !env
->singlestep_enabled
&&
8739 dc
->pc
< next_page_start
&&
8740 num_insns
< max_insns
);
8742 if (tb
->cflags
& CF_LAST_IO
) {
8744 /* FIXME: This can theoretically happen with self-modifying
8746 cpu_abort(env
, "IO on conditional branch instruction");
8751 /* At this stage dc->condjmp will only be set when the skipped
8752 instruction was a conditional branch or trap, and the PC has
8753 already been written. */
8754 if (unlikely(env
->singlestep_enabled
)) {
8755 /* Make sure the pc is updated, and raise a debug exception. */
8757 gen_set_condexec(dc
);
8758 if (dc
->is_jmp
== DISAS_SWI
) {
8759 gen_exception(EXCP_SWI
);
8761 gen_exception(EXCP_DEBUG
);
8763 gen_set_label(dc
->condlabel
);
8765 if (dc
->condjmp
|| !dc
->is_jmp
) {
8766 gen_set_pc_im(dc
->pc
);
8769 gen_set_condexec(dc
);
8770 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8771 gen_exception(EXCP_SWI
);
8773 /* FIXME: Single stepping a WFI insn will not halt
8775 gen_exception(EXCP_DEBUG
);
8778 /* While branches must always occur at the end of an IT block,
8779 there are a few other things that can cause us to terminate
8780 the TB in the middel of an IT block:
8781 - Exception generating instructions (bkpt, swi, undefined).
8783 - Hardware watchpoints.
8784 Hardware breakpoints have already been handled and skip this code.
8786 gen_set_condexec(dc
);
8787 switch(dc
->is_jmp
) {
8789 gen_goto_tb(dc
, 1, dc
->pc
);
8794 /* indicate that the hash table must be used to find the next TB */
8798 /* nothing more to generate */
8804 gen_exception(EXCP_SWI
);
8808 gen_set_label(dc
->condlabel
);
8809 gen_set_condexec(dc
);
8810 gen_goto_tb(dc
, 1, dc
->pc
);
8816 gen_icount_end(tb
, num_insns
);
8817 *gen_opc_ptr
= INDEX_op_end
;
8820 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
8821 fprintf(logfile
, "----------------\n");
8822 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
8823 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8824 fprintf(logfile
, "\n");
8828 j
= gen_opc_ptr
- gen_opc_buf
;
8831 gen_opc_instr_start
[lj
++] = 0;
8833 tb
->size
= dc
->pc
- pc_start
;
8834 tb
->icount
= num_insns
;
8838 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8840 gen_intermediate_code_internal(env
, tb
, 0);
8843 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8845 gen_intermediate_code_internal(env
, tb
, 1);
8848 static const char *cpu_mode_names
[16] = {
8849 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8850 "???", "???", "???", "und", "???", "???", "???", "sys"
8853 void cpu_dump_state(CPUState
*env
, FILE *f
,
8854 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8864 /* ??? This assumes float64 and double have the same layout.
8865 Oh well, it's only debug dumps. */
8874 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8876 cpu_fprintf(f
, "\n");
8878 cpu_fprintf(f
, " ");
8880 psr
= cpsr_read(env
);
8881 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8883 psr
& (1 << 31) ? 'N' : '-',
8884 psr
& (1 << 30) ? 'Z' : '-',
8885 psr
& (1 << 29) ? 'C' : '-',
8886 psr
& (1 << 28) ? 'V' : '-',
8887 psr
& CPSR_T
? 'T' : 'A',
8888 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8891 for (i
= 0; i
< 16; i
++) {
8892 d
.d
= env
->vfp
.regs
[i
];
8896 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8897 i
* 2, (int)s0
.i
, s0
.s
,
8898 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8899 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8902 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
8906 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
8907 unsigned long searched_pc
, int pc_pos
, void *puc
)
8909 env
->regs
[15] = gen_opc_pc
[pc_pos
];